在以二进制形式处理图像后,如何在 OpenCV (Python) 中将灰度图像转换为 RGB 以可视化轮廓?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21596281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:14:10  来源:igfitidea点击:

How does one convert a grayscale image to RGB in OpenCV (Python) for visualizing contours after processing an image in binary?

pythonopencvimage-processing

提问by user391339

I am learning image processing using OpenCV for a realtime application. 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.

我正在学习使用 OpenCV 进行实时应用程序的图像处理。我对图像做了一些阈值处理,想用绿色标记轮廓,但它们没有显示为绿色,因为我的图像是黑白的。

Early in the program I used gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) to convert from RGB to grayscale, but to go back I am confused, and the function backtorgb = cv2.cvtColor(gray,cv2.CV_GRAY2RGB) is giving AttributeError: 'module' object has no attribute 'CV_GRAY2RGB'.

在程序的早期我使用 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 从 RGB 转换为灰度,但回去我很困惑,函数 backtorgb = cv2.cvtColor(gray,cv2.CV_GRAY2RGB) 给出AttributeError: 'module' 对象没有属性 'CV_GRAY2RGB'。

The code below does not appear to be drawing contours in green - is this because it's a greyscale image? If so, can I convert the grayscale image back to RGB to visualize the contours in green?

下面的代码似乎没有以绿色绘制轮廓 - 这是因为它是灰度图像吗?如果是这样,我可以将灰度图像转换回 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()

采纳答案by Anoop K. Prabhu

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.

backtorgb = cv2.cvtColor(gray,cv2.COLOR_GRAY2RGB)是正确的语法。

回答by grromrell

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:

一个你将你的图像转换为灰度,你无法恢复。你已经从三个通道变成了一个通道,当你尝试返回时,所有三个数字都将是相同的。所以简短的回答是不,你不能回去。您的 backtorgb 函数抛出该错误的原因是它需要采用以下格式:

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.

OpenCV 使用 BGR 而不是 RGB,因此如果您修复顺序,它应该可以工作,尽管您的图像仍然是灰色的。

回答by delicasso

Try this:

尝试这个:

import cv2
import cv

color_img = cv2.cvtColor(gray_img, cv.CV_GRAY2RGB)

I discovered, while using opencv, that some of the constants are defined in the cv2 module, and other in the cv module.

我发现,在使用 opencv 时,一些常量是在 cv2 模块中定义的,而其他常量是在 cv 模块中定义的。

回答by nathancy

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)

或者,cv2.merge()可用于通过将与新图像的蓝色、绿色和红色图层相同的图层合并在一起,将单通道二值蒙版图层转换为三通道彩色图像。我们传入三个颜色通道层的列表 - 在这种情况下都是相同的 - 并且该函数返回具有这些颜色通道的单个图像。这有效地将形状的灰度图像(height, width, 1)转换为(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)

我们创建具有尺寸的彩色图像 (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

接下来我们将其转换为灰度并使用cv2.merge()三个灰度通道创建另一个图像

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

我们现在在具有形状的单通道灰度图像(左)和具有形状(200,200,1)的三通道灰度图像(200,200,3)(右)上绘制填充轮廓。左图展示了您遇到的问题,因为您试图在单个通道图像上显示三个通道。将灰度图像合并为三个通道后,我们现在可以将颜色应用到图像上

enter image description hereenter 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()