[英]OpenCV: Colorization failure
我正在读取图像,并且希望将所有非零像素的颜色都变为红色。 此外,背景仅由黑色组成。 我编写的尝试执行的代码如下所示:
import numpy as np
import cv2
second=cv2.imread('second.png') # read the picture
for i in range(second.shape[0]):
for j in range(second.shape[1]):
if second[i,j,0]!=0 and second[i,j,1]!=0 and second[i,j,2]!=0:# if it is not black pixel
second[i,j,0]=0
second[i,j,1]=0
second[i,j,2]=255 # color it in red
cv2.imwrite('result.png',second) # save the colored picture
这是图片second.png :
这是彩色图像result.png :
为何有些像素没有被着色为红色? 需要注意的是,当我打印在这些位置的颜色像素值second.png
对于未在红result.png
,我看他们是不是黑色的。
有谁知道为什么会这样吗?
您应使用or
在您的条件下使用,以替换所有非黑色的像素:
import numpy as np
import cv2
second=cv2.imread('second.png') # read the picture
for i in range(second.shape[0]):
for j in range(second.shape[1]):
if second[i,j,0]!=0 or second[i,j,1]!=0 or second[i,j,2]!=0:# if it is not black pixel
second[i,j,0]=0
second[i,j,1]=0
second[i,j,2]=255 # color it in red
cv2.imwrite('result.png',second) # save the colored picture
或者,您可以写if not(second[i,j,0]==0 and second[i,j,1]==0 and second[i,j,2]==0):
作为条件,是等效的。
如果您不想只留下读通道,则可以使用cv::split
和cv::merge
。 这是C ++示例:
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[])
{
cv::Mat src = cv::imread("second.png");
cv::Mat b_g_r[3];
cv::split(src, b_g_r);
b_g_r[0] = cv::Mat::zeros(src.rows, src.cols, CV_8UC1); //blue to zeros
b_g_r[1] = cv::Mat::zeros(src.rows, src.cols, CV_8UC1); //green to zeros
cv::merge(b_g_r, 3, src);
cv::imshow("Red", src);
cv::waitKey();
return 0;
}
结果:
David Zwicker接受的答案当然是正确的方法。 但是,我想提出一些建议,而不是 for
numpy
数组的循环。 我建议您使用向量化解决方案,因为您绝对可以提高性能。 对我来说,这就是使用numpy
的方式。
我要做的是使用numpy.split
将图像分成单独的通道,然后独立检查每个通道。 我们分配一个与通道之一大小相同的蒙版,并且对于图像中的每个位置,如果任何一个通道都不为零,则将该位置标记为True
。 此操作的结果将是一个掩码,其中True
表示非零像素,否则为False
。 您可以使用numpy.logical_or
,但是标准语法仅接受两个输入。 如果要在多个输入(即大于2)上使用它,则需要使用reduce
惯用语。
找到该蒙版之后,请使用numpy.nonzero
确定蒙版中非零或True
,并创建一个最初为全零的输出图像,然后将红色通道设置为255,以与这些对应非零位置。
换句话说:
import numpy as np
import cv2
img = cv2.imread('second.png') # read in image
# Look at each channel independently and see if there are any non-zero pixels
# and merge them together to create a mask
mask = np.logical_or.reduce(np.split(img, 3, axis=2))
# Find those locations in the mask that are non-zero
(rows, cols, _) = np.nonzero(mask)
# Create a blank image, then set the red channel to 255 for those non-zero locations
out = np.zeros(img.shape).astype('uint8')
out[rows,cols,2] = 255
# Show image, wait for key, then close window after
cv2.imshow('Red', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们得到这个:
完全由您决定要执行的操作,但是(对我来说)以上内容更像Python。 使用最舒适的东西!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.