How to convert a 1 channel image into a 3 channel with opencv2?
Question:
I’m really stumped on this one. I have an image that was [BGR2GRAY]’d earlier in my code, and now I need to add colored circles and such to it. Of course this can’t be done in a 1 channel matrix, and I can’t seem to turn the damned thing back into 3.
numpy.dstack()
crashes everything
GRAY2BGR does not exist in opencv2
cv.merge(src1, src2, src3, dst)
has been turned into cv2.merge(mv)
where mv = "a vector of matrices", whatever that means.
Any ideas?
Answers:
I cant say about python but I can tell you the C++ interface…
gray_image //you have it already
Mat im_coloured = Mat::zeros(gray_image.rows,gray_image.cols,CV_8UC3);
vector<Mat> planes;
for(int i=0;i<3;i++)
planes.push_back(gray_image);
merge(planes,im_coloured);
Here’s a way of doing that in Python:
img = cv2.imread("D:\img.jpg")
gray = cv2.cvtColor(img, cv.CV_BGR2GRAY)
img2 = np.zeros_like(img)
img2[:,:,0] = gray
img2[:,:,1] = gray
img2[:,:,2] = gray
cv2.circle(img2, (10,10), 5, (255,255,0))
cv2.imshow("colour again", img2)
cv2.waitKey()
Here’s the complete code for OpenCV3:
import cv2
import numpy as np
img = cv2.imread('10524.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = np.zeros_like(img)
img2[:,:,0] = gray
img2[:,:,1] = gray
img2[:,:,2] = gray
cv2.imwrite('10524.jpg', img2)
It is the python equivalent:
imgray is a numpy array containing 1-channel image.
img2 = cv2.merge((imgray,imgray,imgray))
Below I assume you don’t have 3-channel image in proper shape, so zeros_like function (used in answer above) will not be useful.
img2 = np.zeros( ( np.array(img).shape[0], np.array(img).shape[1], 3 ) )
img2[:,:,0] = img # same value in each channel
img2[:,:,1] = img
img2[:,:,2] = img
if img is numpy array then it can be shorten from np.array(img).shape
to img.shape
I was using tensorflow when I needed this. Here’s my solution:
image = tf.expand_dims(image, -1)
x1 = image.shape[0]
x2 = image.shape[1]
image = tf.reshape(tf.broadcast_to(image, (x1, x2, 3)), (x1, x2, 3))
Why is everybody using cv2.merge
and low level array operations? Why not simply use cv2.cvtColor
?
img = np.zeros((640, 480), np.uint8) # create grayscale image
print(img.shape)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # grayscale --> BGR
print(img.shape)
which outputs:
(640, 480)
(640, 480, 3)
RGB = np.stack([gray, gray, gray], axis = -1)
if use opencv-python, can use np.repeat function.
img = np.array([[1, 2], [1, 2]])
img2 = np.repeat(img[:, :, np.newaxis], 3, axis=2)
I’m really stumped on this one. I have an image that was [BGR2GRAY]’d earlier in my code, and now I need to add colored circles and such to it. Of course this can’t be done in a 1 channel matrix, and I can’t seem to turn the damned thing back into 3.
numpy.dstack()
crashes everything
GRAY2BGR does not exist in opencv2
cv.merge(src1, src2, src3, dst)
has been turned into cv2.merge(mv)
where mv = "a vector of matrices", whatever that means.
Any ideas?
I cant say about python but I can tell you the C++ interface…
gray_image //you have it already
Mat im_coloured = Mat::zeros(gray_image.rows,gray_image.cols,CV_8UC3);
vector<Mat> planes;
for(int i=0;i<3;i++)
planes.push_back(gray_image);
merge(planes,im_coloured);
Here’s a way of doing that in Python:
img = cv2.imread("D:\img.jpg")
gray = cv2.cvtColor(img, cv.CV_BGR2GRAY)
img2 = np.zeros_like(img)
img2[:,:,0] = gray
img2[:,:,1] = gray
img2[:,:,2] = gray
cv2.circle(img2, (10,10), 5, (255,255,0))
cv2.imshow("colour again", img2)
cv2.waitKey()
Here’s the complete code for OpenCV3:
import cv2
import numpy as np
img = cv2.imread('10524.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = np.zeros_like(img)
img2[:,:,0] = gray
img2[:,:,1] = gray
img2[:,:,2] = gray
cv2.imwrite('10524.jpg', img2)
It is the python equivalent:
imgray is a numpy array containing 1-channel image.
img2 = cv2.merge((imgray,imgray,imgray))
Below I assume you don’t have 3-channel image in proper shape, so zeros_like function (used in answer above) will not be useful.
img2 = np.zeros( ( np.array(img).shape[0], np.array(img).shape[1], 3 ) )
img2[:,:,0] = img # same value in each channel
img2[:,:,1] = img
img2[:,:,2] = img
if img is numpy array then it can be shorten from np.array(img).shape
to img.shape
I was using tensorflow when I needed this. Here’s my solution:
image = tf.expand_dims(image, -1)
x1 = image.shape[0]
x2 = image.shape[1]
image = tf.reshape(tf.broadcast_to(image, (x1, x2, 3)), (x1, x2, 3))
Why is everybody using cv2.merge
and low level array operations? Why not simply use cv2.cvtColor
?
img = np.zeros((640, 480), np.uint8) # create grayscale image
print(img.shape)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # grayscale --> BGR
print(img.shape)
which outputs:
(640, 480)
(640, 480, 3)
RGB = np.stack([gray, gray, gray], axis = -1)
if use opencv-python, can use np.repeat function.
img = np.array([[1, 2], [1, 2]])
img2 = np.repeat(img[:, :, np.newaxis], 3, axis=2)