28

So for this project, I'm working on, I have 2 non-overlapping photos. These two photos need to be stitched together, one on the top and one on the bottom, and then you will be able to see the whole picture. Any ideas on what module I should use to do this?

G M
  • 20,759
  • 10
  • 81
  • 84
Justin Gardner
  • 605
  • 2
  • 9
  • 17
  • 4
    Do they overlap like a panorama? Or do you just need to make one bigger image by putting two smaller ones next to each other? – Leopd May 18 '12 at 18:05

5 Answers5

38

Here's a code sample using Pillow. Hope it helps someone!

from PIL import Image

def merge_images(file1, file2):
    """Merge two images into one, displayed side by side
    :param file1: path to first image file
    :param file2: path to second image file
    :return: the merged Image object
    """
    image1 = Image.open(file1)
    image2 = Image.open(file2)

    (width1, height1) = image1.size
    (width2, height2) = image2.size

    result_width = width1 + width2
    result_height = max(height1, height2)

    result = Image.new('RGB', (result_width, result_height))
    result.paste(im=image1, box=(0, 0))
    result.paste(im=image2, box=(width1, 0))
    return result
d3ming
  • 8,496
  • 5
  • 31
  • 33
  • 4
    this code works, I just tested it now. You can save the file by using this code -> merged = merge_images( file1, file2 ) merged.save( file_dest ) – fedmich Mar 31 '16 at 08:18
  • 2
    The question was for one image on top of another, which is just flipping the actions on result_width with result_height – Ywapom Dec 13 '17 at 16:38
  • 1
    @Ywapom Side-by-side works. I tried vertically (per the flip you suggested), however the bottom image is only black (empty?). Any advice? – boloyao Mar 29 '18 at 20:33
  • @boloyao changing the box argument in the second paste to (0,height1) works. – boloyao Mar 29 '18 at 20:37
26

The python imaging library (updated link) will eat that task for breakfast.

See the tutorial in particular the "Cutting, Pasting and Merging Images" section for some relevant help.

For rough outline, load both images with Image.open, find out how big the output image will be by using the size attribute and some addition, create the output image with Image.new and then use the paste method to past the two original images in.

Nathan
  • 3,558
  • 1
  • 18
  • 38
Nick Craig-Wood
  • 52,955
  • 12
  • 126
  • 132
4

Use numpy.hstack() or numpy.vstack() based on whether you want the images next to each other or on top of each other. You can transform your images into numpy arrays if they are some weird format that numpy doesn't accept. Make sure that you set dtype=np.uint8 if you interpret images as arrays using the np.asarray() method.

kasper_341
  • 85
  • 1
  • 9
3

This is some code from Jan Erik Solems computer vision with python book; you can probably edit it to fit your top/bottom needs

def stitchImages(im1,im2):
    '''Takes 2 PIL Images and returns a new image that 
    appends the two images side-by-side. '''

    # select the image with the fewest rows and fill in enough empty rows
    rows1 = im1.shape[0]    
    rows2 = im2.shape[0]

    if rows1 < rows2:
        im1 = concatenate((im1,zeros((rows2-rows1,im1.shape[1]))), axis=0)
    elif rows1 > rows2:
        im2 = concatenate((im2,zeros((rows1-rows2,im2.shape[1]))), axis=0)
    # if none of these cases they are equal, no filling needed.

    return concatenate((im1,im2), axis=1)
loonyuni
  • 1,373
  • 3
  • 16
  • 24
2

I did vertical stitching like this - it is same code from @d3ming

07: def merge_images(file1, file2):
08:     """Merge two images into one vertical image
09:     :param file1: path to first image file
10:     :param file2: path to second image file
11:     :return: the merged Image object
12:     """
13:     image1 = Image.open(file1)
14:     image2 = Image.open(file2)
15: 
16:     (width1, height1) = image1.size
17:     (width2, height2) = image2.size
18: 
19:     # result_width = width1 + width2
20:     result_width = width1
21:     # result_height = max(height1, height2)
22:     result_height = height1 + height2
23: 
24:     print (height2)
25: 
26:     result = Image.new('RGB', (result_width, result_height))
27:     result.paste(im=image1, box=(0, 0))
28:     result.paste(im=image2, box=(0, height1))
29:     return result

line 19-22 - only height will change for stitching

paste the second image on line-28 box=(width1, 0) changes to box=(0, height1)

kasper_341
  • 85
  • 1
  • 9