MATLAB中肤⾊分割算法_Python应⽤:100⾏代码实现⼈体 肤⾊检测
源 / cnblogs
概述:本⽂中的⼈体肤⾊检测功能采⽤ OpenCV 库实现。OpenCV是⼀个基于BSD许可(开源)发⾏的跨平台计算机视觉库,可以运⾏在Linux、Windows、Android和Mac OS操作系统上. 它轻量级⽽且⾼效——由⼀系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语⾔的接⼝,实现了图像处理和计算机视觉⽅⾯的很多通⽤算法。 本⽂主要使⽤了OpenCV的图像⾊域转换, 颜⾊通道分割, ⾼斯滤波, OSTU⾃动阈值等功能.
参考资料
河北体育学院学报
OpenCV探索之路:⽪肤检测技术
学习OpenCV—肤⾊检测
准备⼯作
安装 Python-OpenCV 库
pip install opencv-python -i mirrors.ustc.edu/pypi/web/simple
利⽤ -i 为pip指令镜像源, 这⾥使⽤电⼦科技⼤学的源, 速度⽐官⽅源更快.
安装 Numpy 科学计算库
pip install numpy -i mirrors.ustc.edu/pypi/web/simple
图像的基本操作
import numpy as np
4m3import cv2
imname = "6358772.jpg"
# 读⼊图像
'''环球游报
使⽤函数 cv2.imread() 读⼊图像。这幅图像应该在此程序的⼯作路径,或者给函数提供完整路径.
警告:就算图像的路径是错的,OpenCV 也不会提醒你的,但是当你使⽤命令print(img)时得到的结果是None。
'''
img = cv2.imread(imname, cv2.IMREAD_COLOR)
'''
imread函数的第⼀个参数是要打开的图像的名称(带路径)
c701第⼆个参数是告诉函数应该如何读取这幅图⽚. 其中
cv2.IMREAD_COLOR 表⽰读⼊⼀副彩⾊图像, alpha 通道被忽略, 默认值
cv2.IMREAD_ANYCOLOR 表⽰读⼊⼀副彩⾊图像
cv2.IMREAD_GRAYSCALE 表⽰读⼊⼀副灰度图像
lgks200
cv2.IMREAD_UNCHANGED 表⽰读⼊⼀幅图像,并且包括图像的 alpha 通道
'''
# 显⽰图像
'''
使⽤函数 cv2.imshow() 显⽰图像。窗⼝会⾃动调整为图像⼤⼩。第⼀个参数是窗⼝的名字,
其次才是我们的图像。你可以创建多个窗⼝,只要你喜欢,但是必须给他们不同的名字.
'''
cv2.imshow("image", img) # "image" 参数为图像显⽰窗⼝的标题, img是待显⽰的图像数据
cv2.waitKey(0) #等待键盘输⼊,参数表⽰等待时间,单位毫秒.0表⽰⽆限期等待
cv2.destroyAllWindows() # 销毁所有cv创建的窗⼝
# 也可以销毁指定窗⼝:
#cv2.destroyWindow("image") # 删除窗⼝标题为"image"的窗⼝
齿轮磨损修复# 保存图像
'''
使⽤函数 cv2.imwrite() 来保存⼀个图像。⾸先需要⼀个⽂件名,之后才是你要保存的图像。
保存的图⽚的格式由后缀名决定.
'''
#cv2.imwrite(imname + "01.png", img)
cv2.imwrite(imname + "01.jpg", img)
运⾏截图
⽪肤检测算法
基于YCrCb颜⾊空间的Cr分量+Otsu法阈值分割算法 YCrCb 即 YUV ,其中 Y 表⽰明亮度 Luminance 或 Luma , 也就是灰阶值. ⽽ U 和 V 表⽰的则是⾊度 Chrominance 或 Chroma ,作⽤是描述影像⾊彩及饱和度, ⽤于指定像素的颜⾊. 亮度 是透过RGB输
⼊信号来建⽴的, ⽅法是将RGB信号的特定部分叠加到⼀起. ⾊度 则定义了颜⾊的两个⽅⾯─⾊调与饱和度,分别⽤ Cr 和 Cb 来表⽰. 其中, Cr 反映了RGB输⼊信号红⾊部分与RGB信号亮度值之间的差异. ⽽ Cb 反映的是RGB输⼊信号蓝⾊部分与RGB信号亮度值之间的差异. 该⽅法的原理也很简单:
将RGB图像转换到 YCrCb 颜⾊空间,提取 Cr 分量图像
对 Cr 分量进⾏⾼斯滤波
对Cr做⾃⼆值化阈值分割处理 OSTU 法
关于⾼斯滤波
使⽤低通滤波器可以达到图像模糊的⽬的。这对与去除噪⾳很有帮助。其实就是去除图像中的⾼频成分(⽐如:噪⾳,边界)。所以边界也会被模糊⼀点。(当然,也有⼀些模糊技术不会模糊掉边界)。OpenCV 提供了四种模糊技术。⾼斯滤波就是其中⼀种。实现的函数是
cv2.GaussianBlur()。我们需要指定⾼斯滤波器的宽和⾼(必须是奇数)。以及⾼斯函数沿 X,Y ⽅向的标准差。如果我们只指定了 X ⽅向的的标准差,Y ⽅向也会取相同值。如果两个标准差都是 0,那么
函数会根据核函数的⼤⼩⾃⼰计算。⾼斯滤波可以有效的从图像中去除⾼斯噪⾳。如果你愿意的话,你也可以使⽤函数 GaussianKernel() ⾃⼰构建⼀个⾼斯滤波器。
# 肤⾊检测之⼀: YCrCb之Cr分量 + OTSU⼆值化
img = cv2.imread(imname, cv2.IMREAD_COLOR)
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb) # 把图像转换到YUV⾊域
(y, cr, cb) = cv2.split(ycrcb) # 图像分割, 分别获取y, cr, br通道图像
# ⾼斯滤波, cr 是待滤波的源图像数据, (5,5)是值窗⼝⼤⼩, 0 是指根据窗⼝⼤⼩来计算⾼斯函数标准差
cr1 = cv2.GaussianBlur(cr, (5, 5), 0) # 对cr通道分量进⾏⾼斯滤波
# 根据OTSU算法求图像阈值, 对图像进⾏⼆值化
_, skin1 = cv2.threshold(cr1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow("image CR", cr1)
cv2.imshow("Skin Cr+OSTU", skin1 )
检测效果
基于YCrCb颜⾊空间Cr, Cb范围筛选法
这个⽅法跟法⼀其实⼤同⼩异,只是颜⾊空间不同⽽已。据资料显⽰,正常黄种⼈的Cr分量⼤约在140⾄175之间,Cb分量⼤约在100⾄120之间。⼤家可以根据⾃⼰项⽬需求放⼤或缩⼩这两个分量的范围,会有不同的效果。
# 肤⾊检测之⼆: YCrCb中 140<=Cr<=175 100<=Cb<=120
img = cv2.imread(imname, cv2.IMREAD_COLOR)
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb) # 把图像转换到YUV⾊域
(y, cr, cb) = cv2.split(ycrcb) # 图像分割, 分别获取y, cr, br通道分量图像
skin2 = np.zeros(cr.shape, dtype=np.uint8) # 根据源图像的⼤⼩创建⼀个全0的矩阵,⽤于保存图像数据(x, y) = cr.shape # 获取源图像数据的长和宽
# 遍历图像, 判断Cr和Br通道的数值, 如果在指定范围中, 则置把新图像的点设为255,否则设为0
for i in range(0, x):
for j in range(0, y):
if (cr[i][j] > 140) and (cr[i][j] < 175) and (cb[i][j] > 100) and (cb[i][j] < 120):
skin2[i][j] = 255
else:
skin2[i][j] = 0
cv2.imshow(imname, img)
cv2.imshow(imname + " Skin2 Cr+Cb", skin2)
检测效果