OpenCV:创建一个透明蒙版?

Posted

技术标签:

【中文标题】OpenCV:创建一个透明蒙版?【英文标题】:OpenCV: Create a transparent mask? 【发布时间】:2014-10-13 07:57:06 【问题描述】:

我目前正在做的是将面部图像加载到 Mat 中,设置每只眼睛的中心点 X 和 Y 坐标,在每只眼睛周围创建一个圆圈,将 ROI 设置为眼睛周围的圆圈(使用 Rect 并设置遮罩),并降低眼睛图像中的红色值。

我的问题是将校正后的眼睛(红色降低)重新合并到原始图像上,因为校正后的眼睛有一个黑色蒙版。我不知道如何摆脱黑色面具。

我目前卡在一些 OpenCV 代码上,这让我走到了这一步:

原图:

用黑色面具提取的眼睛:

矫正眼睛:

当前结果显示我的问题:

这是我的帖子的延续:Getting ROI from a Circle/Point

我的理解是您无法创建圆形 ROI,因此我选择了 Rect ROI 和黑色蒙版。普通的 Rect 是不够的。

非常感谢任何建议!谢谢。

【问题讨论】:

呵呵,对你现在的麻烦有点负责。 ;) 如果您检查croppedEye 图像(使用蒙版,以去除皮肤部分),但write_to/correct cloneRoi(甚至是 roi,您会不必写回去)并将其用于copyTo()? 嘿@berak!诺诺,你帮了我很多忙!我现在明白你在说什么了!!这就是我目前所拥有的(快速更改代码):i.imgur.com/4CmL2KJ.jpg 我认为他是出了点小事故……哈哈。可能是用错眼了,现在检查一下。 是的,我用错了眼睛,呵呵。 :) 【参考方案1】:

您可以使用蒙版的 roi 图像进行 测试 像素,但写入您的真实图像:


 cv::Mat plotImage;
    int radius = 15;
    float threshold = 1.8;

    plotImage = cv::imread("C:/temp/debug.jpg", cv::IMREAD_COLOR);

    cv::Point leftEye(person.GetLeftEyePoint().X, person.GetLeftEyePoint().Y);
    cv::Point rightEye(person.GetRightEyePoint().X, person.GetRightEyePoint().Y);

    //get the Rect containing the circle
    cv::Rect r(leftEye.x-radius, leftEye.y-radius, radius*2, radius*2);
    //obtain the image ROI
    cv::Mat roi(plotImage, r);
    //make a black mask, same size
    cv::Mat mask(roi.size(), roi.type(), cv::Scalar::all(0));
    //with a white filled circle in it
    cv::circle(mask, cv::Point(radius, radius), radius, cv::Scalar::all(255), -1);
    //combine roi & mask
    cv::Mat croppedEye = roi&mask;

    //conduct red eye detection/removal on croppedEye
    int count = 0;
    for(int y=0;y<croppedEye.rows;y++)
    
            for(int x=0;x<croppedEye.cols;x++)
            
                    double b = croppedEye.at<cv::Vec3b>(y, x)[0];
                    double g = croppedEye.at<cv::Vec3b>(y, x)[1];
                    double r = croppedEye.at<cv::Vec3b>(y, x)[2];

                    double redIntensity = r / ((g + b) / 2);

                    //currently causes issues with non-red-eye images
                    if (redIntensity >= threshold)
                    
                            double newRedValue = (g + b) / 2;
                            cv::Vec3b pixelColor(newRedValue,g,b);
                            //
                            // here's the trick now, just write back to the original image ;)
                            //
                            roi.at<cv::Vec3b>(cv::Point(x,y)) = pixelColor;
                            count++;
                    
            
    

    cv::imwrite("C:\\temp\\test.jpg", plotImage);

【讨论】:

很高兴,玩得很开心;)【参考方案2】:

查看这篇文章。 Transparent mask

if (imageMask.at<Vec3b>(xx,yy)[0] < 10)
// This mean If the color of mask in one channel is < 10 replace the original Image
                              
                                                    // Copy to original image on (y,x) places  the pixel of xx,yy mask
    OriginalImage.at<Vec3b>(y,x)[0] =  imageMask .at<Vec3b>(xx,yy)[0];
    OriginalImage.at<Vec3b>(y,x)[1] =  imageMask .at<Vec3b>(xx,yy)[1];
    OriginalImage.at<Vec3b>(y,x)[2] =  imageMask .at<Vec3b>(xx,yy)[2]; 
                               

【讨论】:

以上是关于OpenCV:创建一个透明蒙版?的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenCV 在图像上创建矩形区域蒙版

带有opencv的三角形蒙版

Opencv检测边界和ROI掩码

OpenCV - 将蒙版应用于彩色图像

在 OpenCV 中应用蒙版

使用 OpenCV 进行天空分析的图像 [关闭]