在 OpenCV (Python)中,如何将灰度图像转换为 RGB?

我正在学习使用 OpenCV 实时应用程序的图像处理。我做了一些阈值的图像,并希望标签的轮廓绿色,但他们没有显示在绿色,因为我的图像是在黑色和白色。

在程序的早期,我使用 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)将 RGB 转换为灰度,但是返回时我感到困惑,而且函数 backtorgb = cv2.cvtColor(gray,cv2.CV_GRAY2RGB)给出了:

AttributeError: ‘ module’对象没有属性‘ CV _ GRAY2RGB’。

下面的代码似乎没有用绿色绘制轮廓。是因为这是灰度图像吗?如果是这样,我可以转换灰度图像回到 RGB 可视化的等高线在绿色?

import numpy as np
import cv2
import time


cap = cv2.VideoCapture(0)
while(cap.isOpened()):


ret, frame = cap.read()


gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)


ret, gb = cv2.threshold(gray,128,255,cv2.THRESH_BINARY)


gb = cv2.bitwise_not(gb)


contour,hier = cv2.findContours(gb,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)


for cnt in contour:
cv2.drawContours(gb,[cnt],0,255,-1)
gray = cv2.bitwise_not(gb)


cv2.drawContours(gray,contour,-1,(0,255,0),3)


cv2.imshow('test', gray)


if cv2.waitKey(1) & 0xFF == ord('q'):
break


cap.release()
cv2.destroyAllWindows()
357886 次浏览

One you convert your image to gray-scale you cannot got back. You have gone from three channel to one, when you try to go back all three numbers will be the same. So the short answer is no you cannot go back. The reason your backtorgb function this throwing that error is because it needs to be in the format:

CvtColor(input, output, CV_GRAY2BGR)

OpenCV use BGR not RGB, so if you fix the ordering it should work, though your image will still be gray.

I am promoting my comment to an answer:

The easy way is:

You could draw in the original 'frame' itself instead of using gray image.

The hard way (method you were trying to implement):

backtorgb = cv2.cvtColor(gray,cv2.COLOR_GRAY2RGB)

is the correct syntax.

Try this:

import cv2


color_img = cv2.cvtColor(gray_img, cv2.COLOR_GRAY2RGB)

Alternatively, cv2.merge() can be used to turn a single channel binary mask layer into a three channel color image by merging the same layer together as the blue, green, and red layers of the new image. We pass in a list of the three color channel layers - all the same in this case - and the function returns a single image with those color channels. This effectively transforms a grayscale image of shape (height, width, 1) into (height, width, 3)

To address your problem

I did some thresholding on an image and want to label the contours in green, but they aren't showing up in green because my image is in black and white.

This is because you're trying to display three channels on a single channel image. To fix this, you can simply merge the three single channels

image = cv2.imread('image.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_three = cv2.merge([gray,gray,gray])

Example

We create a color image with dimensions (200,200,3)

enter image description here

image = (np.random.standard_normal([200,200,3]) * 255).astype(np.uint8)

Next we convert it to grayscale and create another image using cv2.merge() with three gray channels

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_three = cv2.merge([gray,gray,gray])

We now draw a filled contour onto the single channel grayscale image (left) with shape (200,200,1) and the three channel grayscale image with shape (200,200,3) (right). The left image showcases the problem you're experiencing since you're trying to display three channels on a single channel image. After merging the grayscale image into three channels, we can now apply color onto the image

enter image description here enter image description here

contour = np.array([[10,10], [190, 10], [190, 80], [10, 80]])
cv2.fillPoly(gray, [contour], [36,255,12])
cv2.fillPoly(gray_three, [contour], [36,255,12])

Full code

import cv2
import numpy as np


# Create random color image
image = (np.random.standard_normal([200,200,3]) * 255).astype(np.uint8)


# Convert to grayscale (1 channel)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


# Merge channels to create color image (3 channels)
gray_three = cv2.merge([gray,gray,gray])


# Fill a contour on both the single channel and three channel image
contour = np.array([[10,10], [190, 10], [190, 80], [10, 80]])
cv2.fillPoly(gray, [contour], [36,255,12])
cv2.fillPoly(gray_three, [contour], [36,255,12])


cv2.imshow('image', image)
cv2.imshow('gray', gray)
cv2.imshow('gray_three', gray_three)
cv2.waitKey()
rgb_image = cv2.cvtColor(binary_image, cv2.COLOR_GRAY2RGB) * 255

There can be a case when you think that your image is a gray-scale one, but in reality, it is a binary image. In such a case you have an array of 0's and 1's where 1 is white and 0 is black (for example).

In RGB space, pixel values are between 0 and 255. Therefore it is necessary to multiply by 255 your converted image. If not, you will receive an almost blank image, because pixels with value 0 are almost the same as the ones with value 1, when the values of pixels varies between <0, 255>