0

I have 360000 images of 800x600 pixel size. I need to stitch with overlap all these images to create a full image that can be zoomed in to view details. How do I make a .dzi image from these base tiles using pyvips library?

I tried to create a jpeg image before coverting it to .dzi. Which is not something that i want. I want to build .dzi image from the base tile image.

the following is what i did until now:

import pyvips
import glob

#creating image array
jpeg_images = glob.glob('*.jpg')
array_images= []
for i in jpeg_images:
    tile = pyvips.Image.new_from_file(i, access="sequential")
    array_images.append(tile)

#Join them, across is how many pictures there be next to each other
out = pyvips.Image.arrayjoin(array_images, 
across=len(jpeg_images)/2)

#write it out to file
out.write_to_file('big_dummy.jpg', Q=95)

#read the image
source_image = pyvips.Image.new_from_file(r'D:\Image 
processing\merge_images_python\dummy_images3\big_dummy.joeg')

#create the dzi image
source_image.dzsave('pyramid_new')
  • Maybe you can share what you done so far. snippet of code will do – Bismark Asiedu Asante Apr 19 '23 at 00:29
  • Wow that's a lot of images. Do they need to be positioned individually, or are they in a regular grid? You don't need to write to a temp file, you can save the result of arrayjoin directly to dzi. – jcupitt Apr 21 '23 at 09:10

1 Answers1

1

I made you a tiny test prog:

#!/usr/bin/python3

import sys
import glob
import pyvips

input_directory = sys.argv[1]
output_file = sys.argv[2]
tiles_across = int(sys.argv[3])

images = [pyvips.Image.new_from_file(filename, access="sequential")
          for filename in glob.glob(f"{input_directory}/*.jpg")]

joined = pyvips.Image.arrayjoin(images, across=tiles_across)

joined.write_to_file(output_file)

I made some sample data like this:

$ mkdir sample
$ vips crop ~/pics/k2.jpg x.jpg 0 0 800 600
$ for i in {1..2500}; do cp x.jpg sample/$i.jpg; done

ie. enough jpg tiles for a 50x50 mosaic, then ran the python program like this:

$ /usr/bin/time -f %M:%e ./arrayjoin.py sample x.dz 50
3893844:14.39

So 4g of memory for a 50x50 mosaic and it took 14 seconds. A 100x100 took 1 minute and 9.6gb, and a 150x150 mosaic took 2 minutes and 17gb.

Therefore, memory use scales approximately with tiles across and elapsed time scales with number of pixels (very roughly).

You need about 600x600 (wow!) so I'd expect you to need maybe 100gb of memory and 30 minutes of processing time.

You are going to need a very large PC, or to assemble the mosaic in sections. You could do a series of 100x100 joins to a set of 36 temporary files, then do a second 6x6 join, for example.

Update to join a set of tiles with the coordinates in the filename, just use the names to make a row-major list, perhaps:

images = []
for y in range(tiles_down):
    for x in range(tiles_across):
        filename = f"{input_directory}/{x}_{y}.jpg"
        images.append(pyvips.Image.new_from_file(filename, 
                                                 access="sequential"))
jcupitt
  • 10,213
  • 2
  • 23
  • 39
  • I tried your test program. It works!!!. But still I have to figure out how to scale this code for 600x600. I am thinking to add two more functionality: 1. I would like to have less levels in pyramid file so that I can save some memory. I can sacrifice the smoothness in zooming. 2.My image files are named with coordinate of its center. I would like to stitch it according to its coordinate. Is there any solution available in pyvips library? – Aswin G Nath May 02 '23 at 12:54
  • 1
    Omitting levels won't save memory, unfortunately. You could reduce the concurrency, that would help a bit -- set `VIPS_CONCURRENCY` to 1. Just parse the filenames and sort the list into row-major order. – jcupitt May 02 '23 at 14:31
  • Is it possible to join tiles with coordinates? – Aswin G Nath May 02 '23 at 18:27
  • 1
    Yes, parse the filenames and use the coordinates to sort images into row-major order. – jcupitt May 03 '23 at 08:02
  • 1
    I added some sample code. – jcupitt May 03 '23 at 08:08
  • ok. I have some areas where there is an overlap between the images. May be I can make a uniform overlap between all the images. Is there any overlap attribute in Image.arrayjoin? – Aswin G Nath May 03 '23 at 10:34
  • arrayjoin only does regular grids of images. I would look into the merge operator, but it's quite a bit more complex. – jcupitt May 03 '23 at 10:46