【问题标题】:Face mask in opencvopencv中的面罩
【发布时间】:2014-04-21 01:48:33
【问题描述】:

输入:人脸图像

问题:在应用 Canny 查找轮廓之前对图像进行阈值处理但不返回面罩

期望的输出如果输入不同的面部,它应该生成一个合适的面罩(面部区域白色和背景白色)

用苹果图片试过..效果很好

            #include <opencv2/highgui/highgui.hpp>
            #include <opencv2/core/core.hpp>
            #include <opencv2/imgproc/imgproc.hpp>

            using namespace cv;
            using namespace std;

            int main(){
              Mat right=imread("front.jpg");
              Mat img1;
              cvtColor(right, img1, CV_RGB2GRAY);
              threshold(img1,img1,160,255,cv::THRESH_BINARY);
              Canny(img1, img1, 128, 350);
              vector< vector<Point> > contours;
              findContours(img1, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
              Mat mask = Mat::zeros(img1.rows, img1.cols, CV_8UC1);
              drawContours(mask, contours, -1, Scalar(255), CV_FILLED);
              normalize(mask.clone(), mask, 0.0, 255.0, CV_MINMAX, CV_8UC1);

              imshow("original", right);
              imshow("thresh",img1);
              imshow("mask", mask);

              waitKey(0);
              return 0;
    }

这是我使用的图像

请忽略下面的前 3 个 cmets

【问题讨论】:

  • 因此您可以定义眼角:矩形(垂直)中间最靠近耳朵位置的点。或者如果您知道面部方向,您可以定义眼角,即眼睛矩形中间的最外侧位置。
  • 我认为更稳健的方法是对内部 ROI 设置阈值并在那里进行简单的 Harris 角检测。它很可能会拿起两个眼角。当然,你需要做一些额外的检查,看看那个角是朝向耳朵还是鼻子(取决于数据集)。
  • @Steph 似乎阈值二进制反转对于上面的图像效果很好,像threshold(img1,img1,160,255,cv::THRESH_BINARY_INV); 这样的东西在这里看到结果i.stack.imgur.com/VtB3Q.jpg,你也不需要在找到轮廓之前做精明。
  • 你好@Micka。记住你写的混合函数,我想要一个单独的函数来生成对齐图像的面罩,然后在混合函数中使用它。但它不起作用:/ 这是上面图片的 findContours 的图片i.imgur.com/5BaqwqJ.jpg
  • 那么你为什么不设置背景的颜色范围(那个灰色的颜色,但它必须是RGB的范围,而不是单一的RGB,更好的是HSV颜色空间,看看HSV 颜色分割)为黑色,所有其他像素为白色。

标签: c++ opencv computer-vision mask


【解决方案1】:

使用下面的代码,可以完美地为您在上述命令中提供的示例图像创建蒙版。

这里假设,你的背景是任何颜色,没有其他物体。

下面的代码就可以了

  • 找边

  • 通过morphology操作加强边缘。

  • 在边缘找到最大的轮廓(始终是前景的边界)并通过填充来绘制它。

有时您的轮廓可能不会在底部关闭(底部没有边缘),因此填充轮廓将不起作用,因此要使其关闭,代码首先找到最大轮廓(前景)的边界矩形,然后绘制矩形的底部到边缘图像,然后再次找到最大轮廓将为您提供正确的蒙版图像。

Rect R;

Mat findLargestContour(Mat thr){

vector< vector <Point> > contours; // Vector for storing contour
vector< Vec4i > hierarchy;
int largest_contour_index=0;
int largest_area=0;
Mat dst(thr.rows,thr.cols,CV_8UC1,Scalar::all(0)); //create destination image

findContours( thr, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
      {
       double a=contourArea( contours[i],false);  //  Find the area of contour
       if(a>largest_area){
       largest_area=a;
       largest_contour_index=i;                //Store the index of largest contour
       }
      }
drawContours( dst,contours, largest_contour_index, Scalar(255,255,255),CV_FILLED, 8, hierarchy );
R= boundingRect( contours[largest_contour_index]);
return dst;

}

int main( )
{

              Mat right=imread("1.jpg");
           // blur(right,right,Size(3,3));
              Mat gray;
              cvtColor(right, gray, CV_RGB2GRAY);

              int borderW=10;
              //Mat ROI=gray(Rect(borderW,borderW,img1.cols-2*borderW,img1.rows-2*borderW));
              Canny(gray, gray, 30, 255);

              Size kernalSize (5,5);
              Mat element = getStructuringElement (MORPH_RECT, kernalSize, Point(1,1)  );
              morphologyEx(gray, gray, MORPH_CLOSE, element );
              imshow("canny", gray);

              Mat largestCon=findLargestContour(gray.clone());
              line(largestCon, Point(R.x,R.y+R.height), Point(R.x+R.width,R.y+R.height), Scalar(255),2,8,0);

              Mat mask=findLargestContour(largestCon.clone());

              Mat A;
              right.copyTo(A,mask);
              imshow("original", right);
              imshow("dst", A);
              imshow("mask", mask);

              waitKey(0);


  return 0;
  }

查看一些示例掩码

【讨论】:

  • 嗨@Haris。我在理解将 Size kernelSize 指定为morphologyEx() 的部分时遇到了一些问题。为什么一定要使用这些?
  • 如果你 imshow() 刚刚在 canny 之后的图像,你可以看到前景的边缘没有连接到某处,这会在找到最大轮廓时造成问题。因此,为了使边缘连接所使用的形态,请参阅更多信息here
  • 嗨@Haris。我在使用此代码时遇到了一些问题。当图像处于其原始状态时,会完美生成蒙版。但是当我对齐它们时,它们的视角会发生变化,并且面具是这样的i.imgur.com/sxMhyOz.jpg:S
  • @Steph 那是因为你有两个背景,白色和黑色,所以你必须先排除黑色背景。
  • 没有,但原始照片是这张i.imgur.com/dYUC2BV.jpg。我非常需要这个面具来生成我的输出..如果面具的某些部分有洞,那就不好了
猜你喜欢
  • 2021-06-18
  • 2021-07-24
  • 2019-09-24
  • 2020-09-25
  • 1970-01-01
  • 2015-05-30
  • 1970-01-01
  • 2012-03-03
  • 2018-04-01
相关资源
最近更新 更多