前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV实现照片自动红眼去除

OpenCV实现照片自动红眼去除

作者头像
OpenCV学堂
发布2018-04-04 11:03:42
1.2K0
发布2018-04-04 11:03:42
举报

OpenCV实现照片自动红眼去除

使用闪光照相机拍照,在光线条件不足的情况,如果眼睛盯着相机镜头很容易造成拍出的照片中人眼球变成红色,虽然现在相机从系统和镜头上做了大量改进工作,防止这种情况发生,但是还是会出现这样的情况。这些照片后期可以通过PS手段进行修复,去除红眼得到正常照片显示。而做图像处理开发者可以借助OpenCV提供API功能轻松实现自动红眼去除修复。首先看一下效果吧图像

有红眼照片

修复之后的照片

实现步骤

眼睛检测

基于OpenCV自带的HAAR眼睛级联分类器特征数据(haarcascade_eye.xml),通过调用级联分类器实现眼睛检测,对检测到的眼睛用红色矩形框标注,如第一张图所示。

实现代码如下:

代码语言:javascript
复制
vector<Rect> eyes;cvtColor(src, gray, COLOR_BGR2GRAY);equalizeHist(gray, gray);eye_detector.detectMultiScale(gray, eyes, 1.1, 3, 0, Size(100, 100));

提取红色眼球区域

根据红眼颜色特征可以看出这种情况下,对每个像素点来说在RGB三通道中红色通道的分量明显要大于其它两个通道的值,所以通过三个通道分离,对每个像素红色通道来说值大于150(R>150)而且R >(G+B)时候我们把它保留作为眼球区域。最终对两个眼睛提取区域图像如下:

代码实现如下:

代码语言:javascript
复制
for (size_t t = 0; t < eyes.size(); t++) {    // 通道分离    Mat eye = src(eyes[t]);    vector<Mat>bgr(3);    split(eye, bgr);    // 基于像素模型的红眼区域检测    Mat mask = (bgr[2] > 150) & (bgr[2] > (bgr[1] + bgr[0]));}

逻辑操作与形态学处理

上述的白色区域就是红色眼球所在的区域,但是这样的情况下白色区域内部还有一些黑色小块,我们可以通过漫水填充与逻辑操作完整填充整个内部区域,然后通过形态的膨胀操作,让红色眼球进一步扩展,这样就会让整个处理之后的边界处看上去比较自然圆润一点。处理之后的效果如下:

代码实现如下:

代码语言:javascript
复制
// 区域填充与提取Mat mask_floodfill = mask.clone();floodFill(mask_floodfill, cv::Point(0, 0), Scalar(255));Mat mask2;bitwise_not(mask_floodfill, mask2);mask = (mask2 | mask);dilate(mask, mask, Mat(), Point(-1, -1), 3, 1, 1);

红眼修复

对上面得到白色区域即为红眼区域,通过把上面结果作为遮罩,对检测到人眼区域进行修复即可。一般情况下人的眼球都是黑色,越中心地方越黑色越暗,对白色区域内的每个像素点,取它的B和G两个通道的平均值作为修复处理之后的R,G,B三通道的值,这样就得到修复之后的眼球区域,然后用修复之后的眼球区域替代原来的红眼区域即可得到修复之后的图像:

代码实现如下:

代码语言:javascript
复制
// 修复Mat mean = (bgr[0] + bgr[1]) / 2;mean.copyTo(bgr[0], mask);mean.copyTo(bgr[1], mask);mean.copyTo(bgr[2], mask);// 回填Mat eyeOut;merge(bgr, eyeOut);eyeOut.copyTo(imgOut(eyes[t]));

完整代码如下

代码语言:javascript
复制
#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;using namespace std;String filename = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_eye.xml";CascadeClassifier eye_detector;int main(int argc, char** argv) {    Mat src = imread("D:/23-01.jpg");    if (src.empty()) {        printf("could not load image...\n");        return -1;    }    if (!eye_detector.load(filename)) {        printf("could not load data file...\n");        return -1;    }    Mat imgOut = src.clone();    Mat gray;    vector<Rect> eyes;    cvtColor(src, gray, COLOR_BGR2GRAY);    equalizeHist(gray, gray);    eye_detector.detectMultiScale(gray, eyes, 1.1, 3, 0, Size(100, 100));    for (size_t t = 0; t < eyes.size(); t++) {        // 通道分离        Mat eye = src(eyes[t]);        vector<Mat>bgr(3);        split(eye, bgr);        // 基于像素模型的红眼区域检测        Mat mask = (bgr[2] > 150) & (bgr[2] > (bgr[1] + bgr[0]));        // 区域填充与提取        Mat mask_floodfill = mask.clone();        floodFill(mask_floodfill, cv::Point(0, 0), Scalar(255));        Mat mask2;        bitwise_not(mask_floodfill, mask2);        mask = (mask2 | mask);        dilate(mask, mask, Mat(), Point(-1, -1), 3, 1, 1);        if (t == 1) {            imshow("mask", mask);        }        // 修复        Mat mean = (bgr[0] + bgr[1]) / 2;        mean.copyTo(bgr[0], mask);        mean.copyTo(bgr[1], mask);        mean.copyTo(bgr[2], mask);        // 回填        Mat eyeOut;        merge(bgr, eyeOut);        eyeOut.copyTo(imgOut(eyes[t]));        rectangle(src, eyes[t], Scalar(0, 0, 255), 2, 8, 0);    }    imshow("input", src);    imshow("output", imgOut);    waitKey(0);    return 0;}

总结:

整个处理就是考察使用OpenCV图像处理的基本操作能力、以及像素操作ROI区域与MASK的巧妙运用。基于OpenCV3.1.0完成全部代码调试。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OpenCV实现照片自动红眼去除
    • 提取红色眼球区域
      • 逻辑操作与形态学处理
        • 红眼修复
          • 完整代码如下
            • 总结:
            相关产品与服务
            图像处理
            图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档