代码: def skinMask_hsv(image):
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
mask = (h>7)*(h<20)*(s>28)*(v>50)
skin = np.array(mask, np.uint8)*255
ratio = np.sum(skin/255)/(image.shape[0]*image.shape[1])
return skin, ratio
效果: 5.opencv自带肤色检测类AdaptiveSkinDetector 已经从opencv 3以上版本中移除,opencv 2中函数。
6.基于椭圆模型 将皮肤信息映射到YCrCb空间,则在CrCb二维空间中这些皮肤像素点近似成一个椭圆分布。因此如果我们得到了一个CrCb的椭圆,下次来一个坐标(Cr, Cb)我们只需判断它是否在椭圆内(包括边界),如果是,则可以判断其为皮肤,否则就是非皮肤像素点。
代码: def skinMask_ellipse(image):
YCrCb = cv2.cvtColor(image, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间
(y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值
skinCrCbHist = np.zeros((256,256),np.uint8)
skinCrCbHist = cv2.ellipse(skinCrCbHist, (113, 155), (23, 15), 43.0, 0.0, 360.0, (255, 255, 255), -1)
cv2.imwrite("ww.jpg", skinCrCbHist)
skin = cv2.remap(skinCrCbHist, cb.astype(np.float32), cr.astype(np.float32), interpolation=cv2.INTER_LINEAR)
ratio = np.sum(skin/255)/(image.shape[0]*image.shape[1])
return skin, ratio
效果: 椭圆模型
效果
7.直方图反向投影 反向投影可以用来做图像分割,寻找感兴趣区间。可以寻找任何的roi,这里将其用作寻找人体肤色。它会输出与输入图像大小相同的图像,每一个像素值代表了输入图像上对应点属于目标对象的概率,简言之,输出图像中像素值越高的点越可能代表想要查找的目标。直方图投影经常与camshift(追踪算法)算法一起使用。
操作步骤: (1)截取若干张不同肤色的图片,最好覆盖常见的所有肤色(如下图)
(2)对所有肤色的图片一起做色彩直方图(利用OpenCV中的calcHist函数)
(3)新建一个与待检测图片同尺寸的灰度图片,找到待检测图片中每颗像素点的颜色在色彩直方图中对应栅格的数值(即统计中出现的次数),并将该数值赋值予新建灰度图片中与该检测像素同位置的像素(利用OpenCV中的calcBackProject函数)。图像中像素亮度越高,待检测图像该位置处是肤色的概率越大。
代码: def skinMask_hist_backproject(target, roi_image):
#roi图片,就想要找的的图片
hsv = cv2.cvtColor(roi_image,cv2.COLOR_BGR2HSV)
#目标搜索图片
hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)
#计算目标直方图
roihist = cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
#归一化,参数为原图像和输出图像,归一化后值全部在2到255范围
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
#卷积连接分散的点
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
dst = cv2.filter2D(dst,-1,disc)
ret,skin = cv2.threshold(dst,50,255,0)
ratio = np.sum(skin/255)/(target.shape[0]*target.shape[1])
return skin, ratio
效果: 本文《传统图像处理之皮肤区域检测》版权归watersink所有,引用传统图像处理之皮肤区域检测需遵循CC 4.0 BY-SA版权协议。