简体   繁体   中英

Numbering/Labeling images (eg 1,2,3 or A,B,C) with ImageMagick montage

I'm using

montage *.tif output.tif

to combine several images to one. I would now like them to be numbered (sometimes 1,2,3 …; somtimes A,B,C …) What possibilities are there to label the single images in the combined? Is there an option to put the label not underneath the picture but eg in the upper left or lower right corner?

Unfortunately I could't really figure out how to use the -label command to achieve that. Thanks for any suggestions.

If you want to invest a little more effort you can have more control. If you do it like this, you can label the images "on-the-fly" as you montage them rather than having to save them all labelled and then montage them. You can also control the width, in terms of number of images per line, more easily:

#!/bin/bash
number=0
for f in *.tif; do
   convert "$f" -gravity northwest -annotate +0+0 "$number" miff:-
   ((number++))
done | montage -tile x3 - result.png

在此处输入图片说明

It takes advantage of ImageMagick miff format, which means Multiple Image File Format, to concatenate all the output images and send them into the stdin of the montage command.

Or, you can change the script like this:

#!/bin/bash
number=0
for f in *.tif; do
   convert "$f" -gravity northwest -fill white -annotate +0+0 "$number" miff:-
   ((number++))
done | montage -tile 2x - result.png

to get

在此处输入图片说明

Or maybe this...

#!/bin/bash
number=0
for f in *.tif; do
   convert "$f" -gravity northwest -background gray90 label:"$number" -composite miff:-
   ((number++))
done | montage -tile 2x - result.png

在此处输入图片说明

Or with letters...

#!/bin/bash
number=0
letters="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for f in *.tif; do
   label=${letters:number:1}
   convert "$f" -gravity northwest -background gray90 label:"$label" -composite miff:-
   ((number++))
done | montage -tile 2x - result.png

在此处输入图片说明

What possibilities are there to label the single images in the combined?

Iterate with a for loop.

for INDEX in {A,B,C}; do
    convert ${INDEX}.jpg labeled_${INDEX}.jpg
done

Is there an option to put the label not underneath the picture but eg in the upper left or lower right corner?

Try using the -annotate with -gravity

convert rose: -fill white \
        -gravity NorthWest -annotate +0+0 "A" \
        A.png

一朵玫瑰

convert rose: -fill white \
        -gravity SouthEast -annotate +0+0 "B" \
        B.png

玫瑰B

Based on the answers above, I wrote a small perl script to combine figures into labelled subfigures, which might be useful to others. It works for me on a Mac, but I didn't really test it.

Usage: pics2grid geometry output_file [-title title] [-bycols] input_files

where the geometry format is [# cols]x[# rows] and input_files accept wild cards. If your title contains spaces, the title must be quoted and the spaces escaped.

I paste it below, but it can also be downloaded from http://endress.org/progs.html#subfigs

#!/usr/bin/perl -l

use strict;
use warnings;
use autodie;
use Getopt::Long 'HelpMessage';

### Process options and arguments ###
if (@ARGV < 3){
  HelpMessage(1);
}

if (($ARGV[0] !~ /^\d+x/) && ($ARGV[0] !~ /x\d+$/)){
  HelpMessage(1);
}

my $geometry = shift @ARGV;

my $output_file = shift @ARGV;

my $title = "";
my $bycols = "";

GetOptions ('bycols' => \$bycols,
        'title=s' => \$title,
        'help'     =>   sub { HelpMessage() },
       ) or HelpMessage(1);


# Wildcards are automatically expanded in @ARGV, but just make sure that they are
my @input_files = map { glob } @ARGV;

$title = "-title $title"
  if ($title);

if ($bycols){
  die "When option -bycols is set, a fully specified geometry is needed."
    unless ($geometry =~ /^\d+x\d+$/);
 }


 @input_files = reorder_input_files (\@input_files, $geometry)
   if ($bycols);

### Define the labels for the subfigures. If you want different figures, change it here. ###
my @labels = "a".."z";
@labels = @labels[0..$#input_files];
@labels = reorder_input_files (\@labels, $geometry)
   if ($bycols);


my $pic_data;

foreach my $f (@input_files){
  # Pictures are combined by rows
  my $lab = shift @labels;
  $pic_data .= `convert \"$f\" -pointsize 48 -font Arial-Regular -gravity northwest -annotate +20+10 \'$lab\' \\
                -bordercolor black -border 1 \\
                 miff:-`;

}

open (OUT,  "| montage -tile $geometry -geometry +0+0 -background white -pointsize 60 -font Arial-Regular $title - $output_file");
print OUT $pic_data;
close (OUT);

sub reorder_input_files {

  my ($input_files, $geometry) = @_;

  my ($ncols, $nrows) = split (/x/, $geometry);

  my @rows = ([]) x $nrows;

  foreach my $i (0..$#$input_files){

    my @tmp_array = @{$rows[$i % $nrows]};
    push (@tmp_array, $input_files->[$i]);
    $rows[$i % $nrows] = \@tmp_array;

  }

  my @reordered_files = ();

  map {push (@reordered_files, @$_)} @rows;

  return (@reordered_files);

}

=head1 NAME

pics2grid - arrange pictures on a grid of sub-figures and number the individual pictures with letters

=head1 SYNOPSIS

  pics2grid geometry output [-title title] [-bycols] inputfiles

  The inputfiles argument accepts wild cards.

  Geometry format: [\# cols]x[\# rows]. 
                   Unless you set the option -bycols, specifying either 
                   the number of rows or of columns is sufficient. 

  Options:
    --title,-t      Title. If your title contains spaces, the title needs 
                    to be quoted *and* the spaces need to be escaped. 
    --bycols,-b     Arrange and number pictures by columns rather than rows
    --geometry,-g   Not yet implemented
    --help,-h       Print this help message

  Examples:
    # Create grid with 3 columns and 2 rows in which images are arranged by *rows*
    pics2grid.pl 3x2 output.pdf input1.png input2.png input3.png\
                                input4.png input5.png input6.png

    # Create grid with 2 columns and 3 rows in which images are arranged by *columns*
    pics2grid.pl 2x3 output.pdf -bycols input1.png input2.png input3.png\
                                        input4.png input5.png input6.png

    # Same as above but with a title including spaces. 
    # Note that the title needs to be quoted *and* the space needs to be escaped 
    # (i.e., put \ in front of the space)
    pics2grid.pl 2x3 output.pdf -bycols -title "My\ title" input1.png\
                 input2.png input3.png input4.png input5.png input6.png

    # Create grid with 4 columns of all png files in the current directory. Images 
    # are arranged by *columns*.
    # It will stop labeling the subfigures for more than 26 images
    pics2grid.pl 4x output.pdf *.png

=head1 VERSION

0.01

=cut

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM