0

I've been using Python 3 and Numpy to handle an image processing task where I'm assembling small tiles into a large, complete image.

I'd do this:

canvas = np.zeros((max_y + tilesize_y, max_x + tilesize_x, 3), dtype='uint8')

Where max_x, max_y are the maximum starting coordinates of individual image tiles. Then I'd paste images into this large canvas like this:

canvas[jj['YStart']: jj['YStart'] + tilesize_y, jj['XStart']: jj['XStart'] + tilesize_x] = temp_img

Where jj is an entry of the filelist that records where each tile beblongs. I'm wondering if similar operation can be achieved in VIPS with Python ?

user3667217
  • 2,172
  • 2
  • 17
  • 29

1 Answers1

1

VIPS has no destructive operations: you can only build new images, you can't modify existing images. This restriction is why vips can do things like automatic parallelisation and operation caching.

Behind the scenes it has some extra machinery to make this less inefficient than it sounds. You can solve your problem like this:

#!/usr/bin/python

import sys
import random

from gi.repository import Vips

# make vips leaktest itself .. this also reports a memory high-water mark
# you'll get a small speedup if you comment this out
Vips.leak_set(True)

composite = Vips.Image.black(10000, 10000)

for filename in sys.argv[1:]:
    tile = Vips.Image.new_from_file(filename, access = Vips.Access.SEQUENTIAL)
    x = random.randint(0, 10000)
    y = random.randint(0, 10000)
    composite = composite.insert(tile, x, y)

composite.write_to_file("output.tif")

There's a searchable list of all the vips operators here:

http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/func-list.html

The docs for insert are here:

http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/libvips-conversion.html#vips-insert

Although you seem to be making a new (huge) image for every iteration, in fact behind your back vips will share the images and only create the bits it needs. Additionally, setting the "sequential" hint on open means vips can stream the sub images in as it writes the final tiff.

Run like this:

$ time ./insert.py ~/pics/k*.jpg 
memory: high-water mark 53.81 MB
real    0m1.913s
user    0m0.939s
sys 0m0.266s
$ ls ~/pics/k*.jpg | wc
       8       8     278

That's pasting in 8 large jpg images. The reported memory use is for pixel buffers, it doesn't include all memory. This script will break if you try pasting in a mix of RGB and RGBA images, you'll need to add some stuff to handle alpha channels.

(in fact there is a destructive paste operation:

http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/libvips-draw.html#vips-draw-image

it's there for paintbox-style programs that really do need to modify images, it's not really suitable for general use)

jcupitt
  • 10,213
  • 2
  • 23
  • 39