gpt4 book ai didi

c++ - 如何处理蒙版图像

转载 作者:行者123 更新时间:2023-11-28 02:52:04 25 4
gpt4 key购买 nike

我正在尝试在图像上绘制椭圆,然后遮盖我所做的区域,如下图所示

enter image description here

好吧,每个人都知道 lena 的原始图像,所以我不会上传它 :),好吧,我有 lena 的 img A,我上传的蒙版图像是 img Mask,现在我想在填充区域以外的区域对图像 mask 执行功能,我如何改变 mask /填充图像以外区域的颜色,然后我想把 lena 的图像(只有填充椭圆下的区域)进入处理过的图像蒙版(其中我更改了填充颜色以外的颜色)然后将我蒙版的 lena 图像放入图像蒙版中,如何执行该任务也是如此,是opencv 中有任何函数可以做到这一点

This circle image into the proceed mask image

这个圆圈图片变成了继续蒙版图片

我真正想要实现的是

enter image description here

我做的代码是:

void main ()
{
Mat img = imread ("E:\\lena.jpg");
Mat mask = img.clone();
ellipse(mask,Point(img.cols/2,img.rows/2),Size(img.cols/2,img.rows/2),0,0,360,Scalar(255,255,255), CV_FILLED, 8,0);
Mat mask2;
inRange(mask, Scalar(255,255,255), Scalar(255,255,255), mask2);
mask.setTo(Scalar(255,0,0), mask2);
}

编辑结果.jpg

enter image description here

编辑以获得额外帮助:

最佳答案

试试这个:

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;
}

输入:

enter image description here

计算掩码:

enter image description here

结果:

enter image description here

idea:创建一个黑色图像,只复制 mask 区域。这是行 img.copyTo(result, mask);。 openCV 掩码是与图像大小相同的 1 channel 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. 如果有前景 mask ,如何创建背景 mask 2. 如何只循环前景/背景并对那些像素执行一些任务3. 如何使用 mask 从图像复制

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;
}

图片是这样的:

像以前一样输入:

enter image description here

前景 mask :就是我们画的椭圆:

enter image description here

背景 mask :所有不是前景的部分:

enter image description here

在我的示例中,原始背景图像只是一个白色图像。这是修改后的背景图像,其中修改了一些蒙版背景图像,不在背景蒙版中的所有内容均未修改(参见代码):

enter image description here

现在修改后的前景图像,看到没有被修改为前景的像素没有被修改

enter image description here

最后在使用掩码使用 .copyTo() 之后:

enter image description here

您可以很容易地看到,您甚至不必复制两个图像,如果您将一个图像复制到另一个图像中并且可以进行许多其他简单的简化,该代码只是为了演示如何以多种不同方式使用蒙版。

希望对你有所帮助,你可以在理解代码后做任何你想做的事 =)

关于c++ - 如何处理蒙版图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22831607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com