Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing more than 4 channel images in OpenCV Python

this is sort of an ongoing challenge for me. I'm trying to combine two 3 RGB images into a single 6 channel TIFF image using openCV.

So far my code is as follows:

import cv2
import numpy as np

im1 = cv2.imread('im1.jpg')
im2 = cv2.imread('im2.jpg')

merged = np.concatenate((im1, im2), axis=2) # creates a numpy array with 6 channels 

cv2.imwrite('merged.tiff', merged)

I've also tried using openCV's split() and merge() methods and get the same results

import cv2
import numpy as np

im1 = cv2.imread('im1.jpg')
im2 = cv2.imread('im2.jpg')

b1,g1,r1 = cv2.split(im1)
b2,g2,r2 = cv2.split(im2)

merged = cv2.merge((b1,g1,r1,b2,g2,r2))

cv2.imwrite('merged.tiff', merged)

When I run the imwrite() function I get the following error:

OpenCV Error: Assertion failed (image.channels() == 1 || image.channels() == 3 || image.channels() == 4) in cv::imwrite_, file C:\builds\master_PackSlaveAddon-win32-vc12-static\opencv\modules\imgcodecs\src\loadsave.cpp, line 455
Traceback (most recent call last):
  File "", line 1, in 
cv2.error: C:\builds\master_PackSlaveAddon-win32-vc12-static\opencv\modules\imgcodecs\src\loadsave.cpp:455: error: (-215) image.channels() == 1 || image.channels() == 3 || image.channels() == 4 in function cv::imwrite_ 

Both images are identical in dimensions (900X1200). I'm thinking that openCV can't write more than 4 channels (RGBA) to a tiff image and I'm having no luck with finding an alternative way to encode this image.

I'm flirting with the idea of creating my own function to write the binary data with appropriate headers but that is way deeper than I want to go.

Is there another function in openCV that I can use that will work, or another library that can write this numpy array to tiff with 6 channels?

like image 903
tpubbsGIS Avatar asked Apr 08 '17 23:04

tpubbsGIS


People also ask

Which is faster PIL or cv2?

Most of cases, cv2 method is faster than pil one.

How do I stack images in OpenCV?

We can use the concatenate() function of NumPy to concatenate the matrices of the images along different axes. For example, let's use the zeros() function of NumPy to create two images with different colors and then combine them horizontally using the concatenate() function.

Does cv2 read BGR images?

OpenCV uses BGR image format. So, when we read an image using cv2. imread() it interprets in BGR format by default. We can use cvtColor() method to convert a BGR image to RGB and vice-versa.


1 Answers

The OpenCV uses libpng, libtiff, etc modules internally to write RGB images, As various image representation formats like jpg, png, etc. assume the fact that the input array must be a single channel, 3 channel or 4 channel. The assumption is made to optimize the disk size of image. But the same assumption would be violated in 6-channel matrix.

So you may use a serialization library like pickle, it can be used in general to serialize any Python Object and in this case you want to serialize a numpy matrix, so it will work fine, However You won't be able to take the advantage of compression techniques used by png or jpg format.

import numpy as np
import pickle

arr = np.ones((1000, 1000, 6), dtype=np.uint8) * 255

with open("arr_dump.pickle", "wb") as f_out:
    pickle.dump(arr, f_out)

with open("arr_dump.pickle", "rb") as f_in:
    arr_new = pickle.load(f_in)
    print arr_new.shape

However if you are concerned with the size of the file, and want to use the memory optimization of tiff or png, etc. then I would recommend you to split your 6-channel image to various channels and create 2 new 3-channel matrices and use imwrite on them to save, and while reading, read both images and combine them to 6-channel image.

like image 141
ZdaR Avatar answered Sep 28 '22 11:09

ZdaR