Create mask from color Image in C++(叠加彩色图像蒙版)
Create mask from color Image in C++ (Superimposing a colored image mask)
我编写了一个代码,可以实时检测正方形(白色)并在其周围绘制一个框。正方形的每条边长l被分成7份。然后我在从垂直于三角形边(蓝色)的偏差演变而来的六个点中的每一个处绘制一条长度为 h=l/7 的线。角落用红色标记。它看起来像这样:
为了绘制蓝线和圆圈,我有一个 3 通道 (CV_8UC3
) 矩阵 drawing
,除了红线、蓝线和白线的位置外,它在任何地方都是零。然后我使用 opencv 的 addWeighted
函数将这个矩阵放在我的网络摄像头图像上。
addWeighted( drawing, 1, webcam_img, 1, 0.0, dst);
(Description for addWeighted here)。
但是,正如您所看到的,我得到的效果是我的破折号和圆圈的颜色在黑色区域之外是错误的(可能在黑色区域内也不正确,但在那里更好)。它发生的原因完全有道理,因为它只是给矩阵加上一个权重。
我希望矩阵 drawing
在我的图像上具有正确的颜色。问题是,我不知道如何修复它。我不知何故需要一个遮罩 drawing_mask
,其中我的破折号有点叠加到我的相机图像上。在 Matlab 中类似于 dst=webcam_img; dst(drawing>0)=drawing(drawing>0);
有人知道如何在 C++ 中执行此操作吗?
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
图像相同的绘制操作。
我编写了一个代码,可以实时检测正方形(白色)并在其周围绘制一个框。正方形的每条边长l被分成7份。然后我在从垂直于三角形边(蓝色)的偏差演变而来的六个点中的每一个处绘制一条长度为 h=l/7 的线。角落用红色标记。它看起来像这样:
为了绘制蓝线和圆圈,我有一个 3 通道 (CV_8UC3
) 矩阵 drawing
,除了红线、蓝线和白线的位置外,它在任何地方都是零。然后我使用 opencv 的 addWeighted
函数将这个矩阵放在我的网络摄像头图像上。
addWeighted( drawing, 1, webcam_img, 1, 0.0, dst);
(Description for addWeighted here)。
但是,正如您所看到的,我得到的效果是我的破折号和圆圈的颜色在黑色区域之外是错误的(可能在黑色区域内也不正确,但在那里更好)。它发生的原因完全有道理,因为它只是给矩阵加上一个权重。
我希望矩阵 drawing
在我的图像上具有正确的颜色。问题是,我不知道如何修复它。我不知何故需要一个遮罩 drawing_mask
,其中我的破折号有点叠加到我的相机图像上。在 Matlab 中类似于 dst=webcam_img; dst(drawing>0)=drawing(drawing>0);
有人知道如何在 C++ 中执行此操作吗?
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
图像相同的绘制操作。