大家有没有碰到过用照相机拍出来照片会出现红眼,是不是感觉有点邪恶,那么这是为什么呢?
在光线昏暗或者晚上,瞳孔往往由于光线不足而扩大。随着照相机闪光灯的闪烁,瞳孔没有来得及反应(缩小),因此而导致一束强光线射到视网膜又反射到照相机的镜头上。在眼球的背面有一层膜叫脉络膜,里面充满了血液,所以反射出来的颜色就是红色的。
大多数照相机都有一个设置,闪光灯会在拍照之前闪几下让瞳孔有时间快速调节到合适的大小。
这里有更好的方式就是通过图像处理来去除红眼现象。
这里采用标准的OpenCV Haar 检测器(haarcascade_eye.xml)来实现人眼检测。
要让事情简单一点,最好图像只是一幅肖像或者眼睛的特写。
代码如下:
import cv2
import numpy as np
#read image
img = cv2.imread("testImg1.jpg") # pass the name of image to be read
outImage = img.copy()
# Load HAAR cascade
eyesCascade = cv2.CascadeClassifier("haarcascade_eye.xml")
#------------ Detect Eyes ------------#
# eyeRects contain bounding rectangle of all detected eyes
eyeRects = eyesCascade.detectMultiScale(img , 1.1, 5 )
接下来需要找到导致红眼现象的瞳孔区域。
简单起见,可以认为红色通道应该大于某个阈值,同样蓝色和绿色通道也是。
对每个眼睛所处矩形区域逐个处理,去除红眼。
#Iterate over all eyes to remove red eye defect
for x,y,w,h in eyeRects:
#Crop the eye region
eyeImage = img [y:y+h , x:x+w]
#split the images into 3 channels
b, g ,r = cv2.split(eyeImage)
# Add blue and green channels
bg = cv2.add(b,g)
#threshold the mask based on red color and combination ogf blue and gree color
mask = ( (r>(bg-20)) & (r>80) ).astype(np.uint8)*255
#find all contours
contours, _ = cv2. findContours(mask.copy() ,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE ) # It return contours and Hierarchy
#find contour with max Area
maxArea = 0
maxCont = None
for cont in contours:
area = cv2.contourArea(cont)
if area > maxArea:
maxArea = area
maxCont = cont
mask = mask * 0 # Reset the mask image to complete black image
# draw the biggest contour on mask
cv2.drawContours(mask , [maxCont],0 ,(255),-1 )
#Close the holes to make a smooth region
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_DILATE,(5,5)) )
mask = cv2.dilate(mask , (3,3) ,iterations=3)
这样就产生了一个完美的掩码,它包含了眼睛中只有红色的区域。既然y通道的信息丢失了,那最好的方法就是是从另外两个通道(蓝色和绿色)来还原信息。
好一点的方式就是利用蓝色和绿色通道的平均值来获得纹理,并用所有的三个通道替换它,这将使瞳孔颜色变得深暗一些。
在前面的步骤中,我们处理了眼睛区域的图像,下面是将两幅图拼接后放在一起进行比较(原始的和经过红眼校正的)。
# Stack both input and output image horizontally
result = np.hstack((img,outImage))
#Display the Result
cv2.imshow("RedEyeCorrection" , result )
cv2.waitKey() # Wait for a keyPress
cv2.destroyAllWindows()
阅读本文,你需要对Python 和 OpenCV 非常熟悉,大多数情况下代码就是最好的注释,如果有任何疑问都可以评论的方式提出来。
原文来自:
https://pytech-solution.blogspot.hk/2017/04/red-eye-correction-from-image-using.html?spref=gp