2015-04-29 228 views
2

我已经编写了一个实时检测正方形(白色)并在其周围绘制框架的代码。正方形的长度l的每一边被分成7部分。然后在垂直于三角形边缘的偏差(蓝色)演变出来的六个点中的每一点绘制一条长度为h = l/7的线。角落标记为红色。然后,它看起来是这样的:从颜色创建遮罩在C++中创建遮罩(叠加彩色图像遮罩)

enter image description here

对于蓝线和圆圈我有一个3通道(CV_8UC3)矩阵drawing,它是一个零无处不在,除了在的位置的绘制的红色,蓝色和白线。然后,我通过opencv的addWeighted函数将这个矩阵放在我的摄像头图像上。 ()。 但是,正如你所看到的,我得到的效果是我的破折号和圆圈的颜色在黑色区域外面是错误的(可能在黑色区域内也不正确,但在那里更好)。它完全理解它为什么会发生,因为它只是增加了一个重量的矩阵。

我想让矩阵drawing在我的图像上显示正确的颜色。问题是,我不知道如何解决它。我不知何故需要一个面具drawing_mask,我的破折号在那里叠加在我的相机图像上。在Matlab的东西dst=webcam_img; dst(drawing>0)=drawing(drawing>0);

任何一个想法如何在C++中做到这一点?

回答

2

1.定制版本

我会明确地写:

const int cols = drawing.cols; 
const int rows = drawing.rows; 

for (int j = 0; j < rows; j++) { 
    const uint8_t* p_draw = drawing.ptr(j); //Take a pointer to j-th row of the image to be drawn 
    uint8_t* p_dest = webcam_img.ptr(j); //Take a pointer to j-th row of the destination image 
    for (int i = 0; i < cols; i++) { 
     //Check all three channels BGR 
     if(p_draw[0] | p_draw[1] | p_draw[2]) { //Using binary OR should ease the optimization work for the compiler 
      p_dest[0] = p_draw[0]; //If the pixel is not zero, 
      p_dest[1] = p_draw[1]; //copy it (overwrite) in the destination image 
      p_dest[2] = p_draw[2]; 
     } 
     p_dest += 3; //Move to the next pixel 
     p_draw += 3; 
    } 
} 

当然你也可以在参数(const cv::Mat& drawing, cv::Mat& webcam_img)功能移到此代码。

2. OpenCV的“纯粹”的版本

但纯OpenCV的方法是如下:

cv::Mat mask; 
//Create a single channel image where each pixel != 0 if it is colored in your "drawing" image 
cv::cvtColor(drawing, mask, CV_BGR2GRAY); 
//Copy to destination image only pixels that are != 0 in the mask 
drawing.copyTo(webcam_img, mask); 

效率较低(颜色转换,以创建蒙版是有点贵),但肯定更紧凑。小记:如果您有一种非常暗的颜色,例如(0,0,1),它将在灰度级中转换为0,但它不起作用。


另外请注意,这可能是重新绘制相同覆盖(线条,圆)在您的目的地形象,基本上调用所做创建您drawing图像相同的抽签操作成本更低。

+1

完美的作品,非常感谢。我在一个函数中实现了第一个解决方案。这工作得很好。 然后我读了最后一个注释,只是将我的覆盖图重绘到'webcam_img'中。这可能是我说的最快最简单的解决方案。太好了谢谢。 SemtexB – SemtexB