我正在阅读图像,我想将所有非零像素着色为红色。此外,背景仅由黑色组成。我写的尝试执行此操作的代码如下所示:
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
中不是红色的那些位置的颜色像素值时,我发现它们不是黑色。
有谁知道为什么会这样?
答案 0 :(得分:1)
您应该在条件中使用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):
写为条件,这是等效的。
答案 1 :(得分:1)
如果您只想留下阅读频道,可以使用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;
}
结果:
答案 2 :(得分:1)
David Zwicker接受的答案肯定是要走的路。但是,我想建议一些内容,并且不使用for
循环和numpy
数组。我建议使用矢量化解决方案,因为你肯定会获得性能提升。对我来说,这就是numpy
的用法。
我要做的是将图像分割为numpy.split
的单独通道,然后单独检查每个通道。我们为其中一个频道分配了相同大小的掩码,如果任何频道非零,我们会将此位置标记为{{1} }。此操作的结果将是掩码,其中True
表示非零像素,否则为True
。您可以使用numpy.logical_or
,但标准语法只接受两个输入。如果您想在多个输入(即大于2)上使用此输入,则需要使用reduce
惯用法。
找到此掩码后,使用numpy.nonzero
确定掩码中非零或False
的位置,并创建一个最初全为零的输出图像,然后将红色通道设置为255,对应于这些非零位置。
或换句话说:
True
我们得到了这个:
完全取决于你想要做什么,但上面(对我而言)更像是Pythonic。使用你最熟悉的任何东西!