96

I'm trying to use OpenCV 2.1 to combine two images into one, with the two images placed adjacent to each other. In Python, I'm doing:

import numpy as np, cv

img1 = cv.LoadImage(fn1, 0)
img2 = cv.LoadImage(fn2, 0)

h1, w1 = img1.height,img1.width
h2, w2 = img2.height,img2.width

# Create an array big enough to hold both images next to each other.
vis = np.zeros((max(h1, h2), w1+w2), np.float32)

mat1 = cv.CreateMat(img1.height,img1.width, cv.CV_32FC1)
cv.Convert( img1, mat1 )

mat2 = cv.CreateMat(img2.height, img2.width, cv.CV_32FC1)
cv.Convert( img2, mat2 )

# Copy both images into the composite image.
vis[:h1, :w1] = mat1
vis[:h2, w1:w1+w2] = mat2

h,w = vis.shape
vis2 = cv.CreateMat(h, w, cv.CV_32FC3)
vis0 = cv.fromarray(vis)
cv.CvtColor(vis0, vis2, cv.CV_GRAY2BGR)
cv.ShowImage('test', vis2)
cv.WaitKey()

The two input images are:

https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/c/box.png?rev=2270

https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/c/box_in_scene.png?rev=2270

The resulting image is:

enter image description here

It may be hard to distinguish from the rest of the site, but most of the image is white, corresponding to where the individual images should be. The black area is where no image data was written.

Why is all my image data being converted to white?

Cerin
  • 60,957
  • 96
  • 316
  • 522
  • Have you seen [find_obj.py sample](https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/python2/find_obj.py) from OpenCV 2.3.1? It looks exactly as what you are trying to do. – Andrey Kamaev Sep 28 '11 at 21:20
  • @Andrey, Yes, that's actually what I'm trying to convert to OpenCV 2.1. I don't have 2.3 and can't get it to compile, so I'm working with 2.1 for now. – Cerin Sep 28 '11 at 23:42
  • You can also create a question about your compilation problem. I think it is solvable. And please note that flann part of this sample can not be implemented with OpenCV 2.1 because python bindings for flann index were added only in 2.3.1. – Andrey Kamaev Sep 29 '11 at 05:16
  • 2
    You can also use `cv2.vconcat()` and `cv2.hconcat()`, see here: https://stackoverflow.com/questions/14579541/how-do-i-concatenate-two-matrices-in-python-opencv/72177160#72177160 – Jeru Luke May 09 '22 at 19:18

7 Answers7

170

For cases where your images happen to be the same size (which is a common case for displaying image processing results), you can use numpy's concatenate to simplify your code.

To stack vertically (img1 over img2):

vis = np.concatenate((img1, img2), axis=0)

To stack horizontally (img1 to the left of img2):

vis = np.concatenate((img1, img2), axis=1)

To verify:

import cv2
import numpy as np
img1 = cv2.imread('img1.png')
img2 = cv2.imread('img2.png')
vis = np.concatenate((img1, img2), axis=1)
cv2.imwrite('out.png', vis)

The out.png image will contain img1 on the left and img2 on the right.

Matt Liberty
  • 2,416
  • 1
  • 18
  • 17
45

For those who are looking to combine 2 color images into one, this is a slight mod on Andrey's answer which worked for me :

img1 = cv2.imread(imageFile1)
img2 = cv2.imread(imageFile2)

h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]

#create empty matrix
vis = np.zeros((max(h1, h2), w1+w2,3), np.uint8)

#combine 2 images
vis[:h1, :w1,:3] = img1
vis[:h2, w1:w1+w2,:3] = img2
FacePalm
  • 10,992
  • 5
  • 48
  • 50
  • This code work for me. I'm not sure why recommend way "np.concatenate" doesn't work well in my case (show different pics). I suspect because it concatenate only one axis not two. tip delete 3 if it's grey scale. – Semooze Jun 13 '22 at 17:29
22

You can also use OpenCV's inbuilt functions cv2.hconcat and cv2.vconcat which like their names suggest are used to join images horizontally and vertically respectively.

import cv2

img1 = cv2.imread('opencv/lena.jpg')
img2 = cv2.imread('opencv/baboon.jpg')

v_img = cv2.vconcat([img1, img2])
h_img = cv2.hconcat([img1, img2])

cv2.imshow('Horizontal', h_img)
cv2.imshow('Vertical', v_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Horizontal Concatenation

Horizontal

Vertical Concatenation

Vertical

Vardan Agarwal
  • 2,023
  • 2
  • 15
  • 27
22
import numpy as np, cv2

img1 = cv2.imread(fn1, 0)
img2 = cv2.imread(fn2, 0)
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
vis = np.zeros((max(h1, h2), w1+w2), np.uint8)
vis[:h1, :w1] = img1
vis[:h2, w1:w1+w2] = img2
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)

cv2.imshow("test", vis)
cv2.waitKey()

or if you prefer legacy way:

import numpy as np, cv

img1 = cv.LoadImage(fn1, 0)
img2 = cv.LoadImage(fn2, 0)

h1, w1 = img1.height,img1.width
h2, w2 = img2.height,img2.width
vis = np.zeros((max(h1, h2), w1+w2), np.uint8)
vis[:h1, :w1] = cv.GetMat(img1)
vis[:h2, w1:w1+w2] = cv.GetMat(img2)
vis2 = cv.CreateMat(vis.shape[0], vis.shape[1], cv.CV_8UC3)
cv.CvtColor(cv.fromarray(vis), vis2, cv.CV_GRAY2BGR)

cv.ShowImage("test", vis2)
cv.WaitKey()
Andrey Kamaev
  • 29,582
  • 6
  • 94
  • 88
  • 2
    cv2.COLOR_GRAY2BGR seems to not exists in OpenCV 2.3. Further you read grayscale images and convert them afterwards back to RGB. So you result will be grayscaled isn't it? – dmorlock May 11 '12 at 12:15
  • 2
    Can we do this for color images?? – Krish Feb 09 '13 at 00:34
6

In order to stack horizontally:

imgHor = np.hstack((img, img))

In order to stack vertically:

imgVer = np.vstack((img, img))

In order to display:

cv2.imshow("Horizontal", imgHor) # horizontal stack
cv2.imshow("Vertical", imgVer)   # vertical stack
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Mayura Pavan
  • 111
  • 1
  • 1
1

The three best way to do it using a single line of code

import cv2
import numpy as np 


img = cv2.imread('Imgs/Saint_Roch_new/data/Point_4_Face.jpg')
dim = (256, 256)
resizedLena = cv2.resize(img, dim, interpolation = cv2.INTER_LINEAR)
X, Y = resizedLena, resizedLena

# Methode 1: Using Numpy (hstack, vstack)
Fusion_Horizontal = np.hstack((resizedLena, Y, X))
Fusion_Vertical   = np.vstack((newIMG, X))

cv2.imshow('Fusion_Vertical using vstack', Fusion_Vertical)
cv2.waitKey(0)

# Methode 2: Using Numpy (contanate)
Fusion_Vertical   = np.concatenate((resizedLena, X, Y), axis=0)
Fusion_Horizontal = np.concatenate((resizedLena, X, Y), axis=1)

cv2.imshow("Fusion_Horizontal usung concatenate", Fusion_Horizontal)
cv2.waitKey(0)


# Methode 3: Using OpenCV (vconcat, hconcat)
Fusion_Vertical   = cv2.vconcat([resizedLena, X, Y])
Fusion_Horizontal = cv2.hconcat([resizedLena, X, Y])

cv2.imshow("Fusion_Horizontal Using hconcat", Fusion_Horizontal)
cv2.waitKey(0)
RashidLadj_Winux
  • 810
  • 1
  • 6
  • 17
-2

in OpenCV 3.0 you can use it easily as follow:

#combine 2 images same as to concatenate images with two different sizes
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
#create empty martrix (Mat)
res = np.zeros(shape=(max(h1, h2), w1 + w2, 3), dtype=np.uint8)
# assign BGR values to concatenate images
for i in range(res.shape[2]):
    # assign img1 colors
    res[:h1, :w1, i] = np.ones([img1.shape[0], img1.shape[1]]) * img1[:, :, i]
    # assign img2 colors
    res[:h2, w1:w1 + w2, i] = np.ones([img2.shape[0], img2.shape[1]]) * img2[:, :, i]

output_img = res.astype('uint8')
  • this code constructs a result array that assumed the height of the taller of both images. -- there is no need at all for the loop, nor the np.ones() multiplication. – Christoph Rackwitz Jun 26 '22 at 19:49