试试这个:
int main()
{
cv::Mat img = imread ("E:\\lena.jpg");
cv::Mat mask = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
cv::ellipse(mask,cv::Point(mask.cols/2,mask.rows/2),cv::Size(mask.cols/2,mask.rows/2),0,0,360,cv::Scalar(255), CV_FILLED, 8,0);
cv::imshow("mask", mask);
cv::Mat result = cv::Mat(img.rows, img.cols, CV_8UC1, img.type());
result.setTo(cv::Scalar(0,0,0));
img.copyTo(result, mask);
cv::imshow("result", result);
cv::waitKey(-1);
return 0;
}
输入:
计算掩码:
结果:
idea:创建一个黑色图像并仅将蒙版区域复制到它。
这是img.copyTo(result, mask); 行。 openCV 掩码是与图像大小相同的 1 通道 CV_8U 图像。
如果您一般只想在遮罩区域中操作像素,您可以这样做:
loop over y and x coordinate of the image
if(mask.at<unsigned char>(cv::Point(x,y)) != 0)
manipulate the pixel in img
else
do not manipulate the pixel
这是另一个例子,你可以看到不同的东西:
1.如果有前景蒙版,如何创建背景蒙版
2.如何只循环前景/背景并在这些像素上执行一些任务
3. 如何从图像中复制,使用蒙版
int main()
{
// load image:
cv::Mat img = cv::imread ("lena.jpg");
// create the foreground mask in form of an ellipse:
cv::Mat foregroundMask = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
cv::ellipse(foregroundMask,cv::Point(foregroundMask.cols/2,foregroundMask.rows/2),cv::Size(foregroundMask.cols/2,foregroundMask.rows/2),0,0,360,cv::Scalar(255), CV_FILLED, 8,0);
cv::Mat foreground = img.clone();
// create the background mask which is just everything that is not foreground
cv::imshow("mask", foregroundMask);
cv::Mat backgroundMask = 255-foregroundMask;
// create a background and give it some color. this could be another loaded image instead.
cv::Mat background = cv::Mat(img.rows, img.cols, img.type());
// give the background some color. here white for example.
background.setTo(cv::Scalar(255,255,255));
// do some computation on the background image, but only where the background mask is not zero!
for(int y=0; y<backgroundMask.rows; ++y)
for(int x=0; x<backgroundMask.cols; ++x)
{
cv::Point pixelPos(x,y);
if(backgroundMask.at<unsigned char>(pixelPos))
{
// manipulate the background
// I choose to set every 8th pixel in a random color, you could do any filter or something:
if(x%8 == 0)
{
// create random color
cv::Vec3b randomColor(rand()%255, rand()%255, rand()%255);
// use .at<Vec3b> for 24 bit BGR values
background.at<cv::Vec3b>(pixelPos) = randomColor;
}
}
else
{
// you could process any pixel here which is NOT in your background mask, but I'll process foreground explicitly later
}
}
// just in case that you want to modify the foreground too, here's an example:
for(int y=0; y<foregroundMask.rows; ++y)
for(int x=0; x<foregroundMask.cols; ++x)
{
cv::Point pixelPos(x,y);
if(foregroundMask.at<unsigned char>(pixelPos))
{
// manipulate the background
// for example, set every 12th row to blue color:
if(y%12 == 0)
{
// create random color
cv::Vec3b blueColor(255, 0, 0);
// use .at<Vec3b> for 24 bit BGR values
foreground.at<cv::Vec3b>(pixelPos) = blueColor;
}
}
else
{
// you could process any pixel here which is NOT in your foreground mask, but I've processed background explicitly earlier
}
}
cv::imshow("modified background", background);
cv::imshow("modified foreground", foreground);
// this is how to copy something using masks:
cv::Mat result;
// copy background masked pixel from background image to the result:
background.copyTo(result, backgroundMask);
// copy foreground masked pixel from foreground image to the result:
foreground.copyTo(result, foregroundMask);
cv::imshow("result", result);
cv::waitKey(-1);
return 0;
}
图片是这样的:
像以前一样输入:
前景蒙版:它只是我们绘制的椭圆:
背景掩码:这就是所有不是前景的东西:
在我的示例中,原始背景图像只是一张白色图像。
这是修改后的背景图片,其中一些被蒙版的背景图片被修改了,所有不在背景蒙版中的东西都没有被修改(见代码):
现在是修改后的前景图像,看到没有被掩蔽为前景的像素没有被修改
最后在使用 .copyTo() 和使用掩码之后:
您可以很容易地看到,您甚至不必复制两个图像,如果您将一个图像复制到另一个图像中并且可以进行许多其他简单的简化,那么该代码只是为了演示如何以多种不同方式使用掩码。
希望对你有所帮助,理解代码后你可以做任何你想做的事=)