'Create a montage of 15000 images
I am trying to create a collage/montage of 15000 images using imagemagick montage command.The tool works perfectly for a small subset of the images but when trying to create a montage using 15K images the program crashes because it can't just load 15K images into main memory. I think opening the files in streams and then stacking in batches of 100 would work but if someone has a nice solution,it would be helpful.
Solution 1:[1]
It's a bit late here to write and test anything, but I'd probably do something like this:
- generate a text file with all the filenames to montage
- use
splitcommand to break that into groups of 100 - iterate over all the groups making a row of images from each
- stack the rows
First part is like:
find . -name "*.jpg" -print > filelist.txt
Next part is like:
split -l 100 filelist.txt ROWS
Next part is like:
n=0
for f in ROWS* ; do
magick @"$f" +append row${n}.jpg
((n=n+1))
done
Last part is like:
magick row*.jpg -append result.jpg
Solution 2:[2]
libvips can make huge image montages without needing a lot of memory. For example:
$ vips arrayjoin "a.png b.png c.png d.png" output.png --across 2
This will read the four PNG images, lay them out in rows in a 2 x 2 grid, and write to out.png. You can use $() to find lots of images and sort by filename, perhaps:
$ vips arrayjoin "$(ls *.jpeg | sort -t_ -k2g -k1g)" x.tif --across 20
That will load all JPEG images with filenames of the form x_y.jpeg, sort them numerically by row and then by column, and assemble them into a 20 x N grid.
15,000 images is too much for the command-line on linux (you'll get an Argument list too long error from bash), but you can do it from python with pyvips. Perhaps:
#!/usr/bin/python3
import sys
import glob
import pyvips
images = [pyvips.Image.new_from_file(filename, access="sequential")
for filename in glob.glob(sys.argv[1] + "/*.jpg")]
joined = pyvips.Image.arrayjoin(images, across=100)
joined.write_to_file(sys.argv[2])
Then:
$ vips crop ~/pics/k2.jpg x.jpg 0 0 1000 1000
$ for i in {1..15000}; do cp x.jpg $i.jpg; done
$ VIPS_CONCURRENCY=1 /usr/bin/time -f %M:%e \
./arrayjoin.py . x.tif[compression=jpeg,tile]
4689264:78.38
$ vipsheader x.tif
x.tif: 100000x150000 uchar, 3 bands, srgb, tiffload
So that's assembling 15,000 1,000 x 1,000 pixel JPG images to make a 100,000 x 150,000 pixel JPEG-compressed TIFF. It takes 80s and needs a peak of 4.7gb of memory.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
