Zhongwei +

人像头部检测

0. 我的图像处理项目

1. 区域分割Demo

最开始我以为只是简单的抠图,所以花一晚上做了下面这个Demo。

抠图的方法分为三步: 1. Canny算子检测; 2. 形态学上的腐蚀以连接断点; 3. 通过漫水填充分割区域。

分割的效果还不错,处理速度很快,可以批量分割图片而不用调节阈值:

Git Bash

Git Bash

Git Bash

部分代码如下:

int main(int argc, char* argv[])
{
    char srcName[] = "test.jpg";
    IplImage * rgb = cvLoadImage(srcName);
    IplImage * src = cvLoadImage(srcName, 0);

    IplImage * img = src;
    IplImage * imgSrc = img;
    CvSize sizeSrc = cvGetSize(imgSrc);

    CEdge edgeTemp;
    edgeTemp.setEdgeThresh(20);
    edgeTemp.extractEdge(srcName);
    imgSrc = edgeTemp.getEdge();

    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
    dilate((Mat)imgSrc, (Mat)imgSrc, element);

    cvMin(img, imgSrc, imgSrc);

    cvFloodFill(imgSrc, Point(sizeSrc.width*0.5, 10), Scalar(255, 255, 255), Scalar(5, 5, 5), Scalar(5, 5, 5));

    cvMax(src, imgSrc, imgSrc);

    IplImage * mask = cvCreateImage(sizeSrc, imgSrc->depth, 1);
    cvSet(mask, cvScalar(255, 255, 255));
    for (int i = 0; i < sizeSrc.width; i += 1)
    {
        for (int j = 0; j < sizeSrc.height; j += 1)
        {
            Scalar tmp = cvGet2D(imgSrc, j, i);
            if (tmp.val[0]
                == 255)
            {
                tmp.val[0] = 0;
            }
            cvSet2D(mask, j, i, tmp);
        }
    }


    IplImage * dst = cvCreateImage(sizeSrc, rgb->depth, 3);
    cvCopy(rgb, dst, mask);

    waitKey(0);

    cvReleaseImage(&src);
    cvReleaseImage(&img);
    cvReleaseImage(&imgSrc);
    cvReleaseImage(&mask);
    cvReleaseImage(&dst);

    return 0;
}

但是我对需求描述产生一个疑问,整个头部(包括头发和脸部)是指下图I和II中的哪一个:

Git Bash

如果是第二种,情况会复杂很多,因为需要检测头部在图片中的位置。

2. Hough随机变换+OneCut分割

针对第二种情况,我的想法是先用识别Hough变化识别近似头部的圆形区域,然后提取头部区域的骨架,作为OneCut算法的输入,最后分割头部图像。

OneCut是个开源库,可以在下面的地址找到论文: http://www.csd.uwo.ca/~ygorelic/iccv13_one_cut.pdf

论文中,该算法的效果可以达到下图的程度: Git Bash

Blog

Project

Favorite