在本教程中,我们将学习如何完全自动消除照片中的红眼。

仅仅考虑消除红眼的问题,就会带回我小时候的记忆。小时候拥有一台傻瓜相机“ Hotshot”。它可能是我们家庭中唯一的便携式电子设备,使用了数十年。我妈妈把相机和她的黄金首饰锁在一个保险箱中。摄影是为非常特殊的场合而保留的,因为胶卷很贵。有时要过几个月才能拍摄出我们拍摄的照片。自然,当我们晚上拍摄的照片产生红眼效果时,它总是让我心碎。满脸鲜血的微笑的人使我想起了德古拉!

在本科期间的某个时候,我想出了一种使用照片编辑工具手动消除红眼的方法。学习基本原理给我带来了很多快乐,它的简单性让我感到惊讶!我要花几年的时间才能弄清楚如何完全自动地做到这一点。

构建一个适用于各种图像的健壮的红眼消除应用程序超出了本文的范围。但是,我们将学习基本原理并构建概念证明应用程序。

是什么导致闪光灯摄影中出现红眼效应?

当您在黑暗的房间里时,您的瞳孔会变大(放大),以便让更多的光线进入,以帮助您更好地看到。大多数相机上的闪光灯都非常靠近镜头。当您在闪光灯开启的情况下拍照时,闪光灯发出的光线会通过扩大的瞳孔到达眼球后部,然后再通过瞳孔射入相机的镜头。眼球的背面称为眼底。它是红色的,因为眼底有充足的血液供应。

眼底图像显示在左侧。检查眼底可以揭示一个人的健康状况。您甚至可以获取智能手机应用程序,以帮助您查看带有附件的眼底。

这些天大多数相机闪光灯会闪烁几秒钟,这会使瞳孔收缩,从而减少了红眼的可能性。

如何自动删除红眼?

在本节中,我们将逐步介绍用于自动消除红眼的算法。

步骤1:眼睛检测

OpenCV眼睛检测

第一步是自动检测眼睛。我们使用标准的OpenCV Haar检测器(haarcascade_eye.xml)来寻找眼睛。有时先运行面部检测器,然后再检测面部区域内的眼睛是有意义的。为了简单起见,我们直接在图像上运行眼睛检测器。当输入图像为人像拍摄或眼睛特写时,可以跳过脸部检测器。

您还可以说明训练自己的HAAR对象检测器。

我在下面共享用于眼睛检测器的代码。

C++


// Read image
Mat img = imread("red_eyes.jpg",CV_LOAD_IMAGE_COLOR);// Output image
Mat imgOut = img.clone();// Load HAAR cascade
CascadeClassifier eyes_cascade("haarcascade_eye.xml");// A vector of Rect for storing bounding boxes for eyes.
std::vector<Rect> eyes;// Detect eyes.
eyesCascade.detectMultiScale( img, eyes, 1.3, 4, 0 | CASCADE_SCALE_IMAGE, Size(100, 100) );

Python


# Read image
img = cv2.imread("red_eyes.jpg", cv2.IMREAD_COLOR)# Output image
imgOut = img.copy()# Load HAAR cascade
eyesCascade = cv2.CascadeClassifier("haarcascade_eye.xml")# Detect eyes
eyes = eyesCascade.detectMultiScale(img,scaleFactor=1.3, minNeighbors=4, minSize=(100, 100))

步骤2:遮住红眼

接下来,我们需要找到受红眼影响的瞳孔部分。找到红色的方法有很多。需要注意的一件事是我们的颜色不仅是红色,还是鲜红色!您可以根据色相和亮度将图像转换为HSV颜色空间和阈值。在本文中,我们使用了一种更简单的启发式方法。我们说他的红色通道应该大于阈值,也应该大于绿色和蓝色通道的总和。出于概念验证系统的目的,试探法就足够了,但是如果您要为商业软件包构建自动防红眼功能,则需要收集数千张红眼图像才能提出更好的解决方案。

在下面的代码中,我们遍历在上一步中检测到的所有眼睛矩形。然后,我们使用命令split将彩色图像分成三个通道。最后,对于红色通道高于阈值(150)且红色通道大于绿色通道和蓝色通道之和的每个像素,我们创建一个掩码为1的蒙版。

C++


for( size_t i = 0; i &lt; eyes.size(); i++ )
{// Extract eye from the image.Mat eye = img(eyes[i]);// Split eye image into 3 channels.vector<Mat>bgr(3);split(eye,bgr);// Simple red eye detectorMat mask = (bgr[2] > 150) &amp; (bgr[2] &gt; ( bgr[1] + bgr[0] ));
}

Python

for (x, y, w, h) in eyes:# Extract eye from the image.eye = img[y:y+h, x:x+w]# Split eye image into 3 channelsb = eye[:, :, 0]g = eye[:, :, 1]r = eye[:, :, 2]# Add the green and blue channels. bg = cv2.add(b, g)# Simple red eye detectormask = (r > 150) &  (r > bg)# Convert the mask to uint8 format. mask = mask.astype(np.uint8)*255

步骤3:清理瞳孔面罩

在上一步中创建的蒙版很可能会带有孔。上图中的左图显示了使用颜色处理获得的原始蒙版。

C++

void fillHoles(Mat &amp;mask)
{Mat mask_floodfill = mask.clone();floodFill(mask_floodfill, cv::Point(0,0), Scalar(255));Mat mask2;bitwise_not(mask_floodfill, mask2);mask = (mask2 | mask);}

Python

def fillHoles(mask):maskFloodfill = mask.copy()h, w = maskFloodfill.shape[:2]maskTemp = np.zeros((h+2, w+2), np.uint8)cv2.floodFill(maskFloodfill, maskTemp, (0, 0), 255)mask2 = cv2.bitwise_not(maskFloodfill)return mask2 | mask

另外,最好扩大遮罩,使其覆盖比所需区域稍大的区域。这是因为在边界处,颜色逐渐消失,并且在我们的原始蒙版中可能未捕获到某些红色。在上图中,右图是蒙版的放大图。我们使用下面共享的代码生成扩展的蒙版。

C++


// Clean up mask by filling holes and dilating
fillHoles(mask);
dilate(mask, mask, Mat(), Point(-1, -1), 3, 1, 1);

Python


# Clean up mask by filling holes and dilating
mask = fillHoles(mask)
mask = cv2.dilate(mask, None, anchor=(-1, -1), iterations=3, borderType=1, borderValue=1)

第4步:修复红眼

现在我们有了一个只包含每只眼睛红色区域的蒙版。接下来,我们展示如何处理此蒙版中的区域以修复红眼。

我们知道,红眼睛会使图像中的红色通道饱和。换句话说,红色通道中的所有信息均被破坏。我们如何才能找回一些信息?修复红眼时,我们无需检索红色通道中的真实基础纹理;我们只需要找到合理的纹理即可。

幸运的是,红眼效果只会破坏红色通道中的纹理;蓝色和绿色通道仍然不错。您可以在下图中看到该位置,其中显示了图像的红色,绿色和蓝色通道。

绿色和蓝色通道的组合可用于提出合理的红色通道。例如,我们可以创建一个红色通道,该通道是图像中绿色和蓝色通道的平均值。但是,这样做可能会使瞳孔略带淡淡,看起来不错,但效果不佳。注意中间图像中的紫色调。

这给我们带来了一个重要的问题。瞳孔应该是什么颜色?瞳孔是眼睛的开口,眼睛的内部完全是黑暗的。因此,瞳孔应该是无色(灰度)和深色的。代替仅替换瞳孔区域中的红色通道,我们将所有通道替换为绿色和蓝色通道的均值。这消除了紫色调。

下面的代码首先通过平均绿色和蓝色通道来创建平均通道。然后,它将所有通道的被遮罩区域内的所有像素替换为该平均通道。

C++


// Calculate the mean channel by averaging
// the green and blue channels
Mat mean = (bgr[0]+bgr[1])/2;// Copy the mean image to blue channel with mask.
mean.copyTo(bgr[0], mask);// Copy the mean image to green channel with mask.
mean.copyTo(bgr[1], mask);// Copy the mean image to red channel with mask.
mean.copyTo(bgr[2], mask);

Python

# Calculate the mean channel by averaging
# the green and blue channels. Recall, bg = cv2.add(b, g)
mean = bg / 2
mask = mask.astype(np.bool)[:, :, np.newaxis]
mean = mean[:, :, np.newaxis]# Copy the eye from the original image.
eyeOut = eye.copy()# Copy the mean image to the output image.
np.copyto(eyeOut, mean, where=mask)

步骤5:更换固定眼部区域

在上一步中,我们修复了三个渠道。最后一步是合并三个通道以创建我们的RGB图像,然后将此固定眼图区域放回原始图像中。

C++


// Merge the three channels
Mat eyeOut;
merge(bgr,eyeOut);// Copy the fixed eye to the output image.
eyeOut.copyTo(imgOut(eyes[i]));

Python


# Copy the fixed eye to the output image.
imgOut[y:y+h, x:x+w, :] = eyeOut

自动去除红眼结果

我们首先在示例图像上显示结果。

请注意,从瞳孔区域删除所有颜色会使图像看起来很漂亮,因为眼睛中心的点是完全白色的。还要注意,在瞳孔的边界上,红色逐渐减弱,但是由于进行了扩张操作,我们仍然捕获了该区域。

接下来,我们在眼睛的特写照片上显示结果。如果我们使用了面部检测器,它将不会检测到面部,并且自动眼睛检测器将无法工作。

相关源码下载地址:关注“图像算法”微信公众号,回复红眼,即可获取

如何使用OpenCV的去除自动红眼相关推荐

  1. OpenCV实现照片自动红眼去除

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 OpenCV实现照片自动红眼去除 使用闪光照相机拍照,在光线条件不 ...

  2. opencv去除照片红眼

    opencv去除照片红眼 #include <stdint.h> #include <opencv2/opencv.hpp> #include "windows.h& ...

  3. learn opencv-使用OpenCV的自动红眼删除

    参考:https://github.com/spmallick/learnopencv 使用OpenCV的自动红眼删除(C ++ / Python) 在本教程中,我们将学习如何完全自动地从照片中删除红 ...

  4. 【机器视觉学习笔记】python安装OpenCV并设置自动补全及代码提示

    目录 安装 测试 设置自动补全及代码提示 平台:Windows 10 20H2 Python 3.8.12 (default, Oct 12 2021, 03:01:40) [MSC v.1916 6 ...

  5. WPS 2019 去除自动升级 和 广告、及优化的点

    搜狗输入法 里面的快捷键会影响wps的快捷键功能,需要关掉"搜狗输入法"里面的快捷键 1. 2.去除自动升级功能 3.去除 广告 WPS 2019 流程图(断网): 思维导图: 流 ...

  6. 百度UEditor富文本编辑器去除自动追加span标签

    #消息模板实时翻译 1.消息模板支持实时翻译,并且将消息模板中的主题.消息.短信.邮件修改为消息富文本编辑器,对主题和短信的富文本编辑器工具进行隐藏. 2.替换规则:    同步拼接编码和label, ...

  7. python opencv vscode 增加自动补全 auto completement

    python opencv vscode 增加自动补全 auto completement 现状 解决方法 参考 现状 vscode中使用opencv时,无法自动补全. 解决方法 自己生成 pyi 文 ...

  8. opencv 打印文字_如何使用OpenCV+Python去除手机拍摄文本底色

    点击上方蓝字关注我们 微信公众号:OpenCV学堂 关注获取更多计算机视觉与深度学习知识 起因 最近经常被要求手机拍摄考试卷,但是拍摄完之后,跟实际的黑白考试卷有很大的色差,打印出来之后背景就变成了灰 ...

  9. 自动红眼移除算法 附c++完整代码

    说起红眼算法,这个话题非常古老了. 百度百科上的描述: "红眼"一般是指在人物摄影时,当闪光灯照射到人眼的时候,瞳孔放大而产生的视网膜泛红现象. 由于红眼现象的程度是根据拍摄对象色 ...

最新文章

  1. 某程序员吐槽自己之前的外包同事能力不行,经常给同事挖坑,却面过了头条!只因为会刷题!头条招人这么不靠谱?...
  2. POJ2406简单KMP
  3. 信息化十七载 ERP重塑双良战略与核心价值
  4. Linux 文件系统初探
  5. word List40
  6. UI设计实用素材|闪屏模板
  7. 别怨自己命不好,先看看“厚德载物”你有几德?
  8. Redis常见的5种不同的数据类型详解
  9. 项目关键路径与项目最长路径有可能不同
  10. 对抗神经网络(Adversarial Nets)的介绍[1]
  11. Spring MVC整合FreeMarker
  12. mysql查看sa密码_查询mssql 密码
  13. html中空格符号以及空格字符实体的总结
  14. Python从入门到PY交易,基础语法,散记(一)
  15. ipad pro + zotero + 坚果云 + PDF Expert 搭建多平台文献管理(自用备忘)
  16. C++多线程,线程函数传参显示没有重载函数接受4个参数
  17. vue+elemnt ul 图片上传隐藏按钮+图片回显
  18. 局域网即时通讯软件怎么部署
  19. yandex如何挑选关键词?
  20. Jmeter录制脚本(二)-----使用代理录制web脚本

热门文章

  1. 雅虎与阿里巴巴决裂 对自己很不利
  2. 二维码符号体系已经到来
  3. 准备软硬件openGauss安装环境
  4. Qt项目背景图片无法显示
  5. 会计 金融管理 计算机网络技术,天津海运职业学院专业排名,招生专业目录(10篇)...
  6. 把word文档转换成swf格式
  7. 从三国的人物身上我们能学到些啥?
  8. mathml_MathML简介–数学标记语言
  9. 优盘里面的文件夹变0字节也打不开文件的解决方法
  10. Android中的launchMode