彩色图像中的人脸(肤色)检测

彩色图像中的人脸(肤色)检测

选了图像工程的课,老师布置了一个小Project,要求用OpenCV或者Matlab实现人脸肤色检测,具体算法参考文献“Face Detection In Corlor Images”。我觉得Python调用OpenCv可能会来得比较快些(没有Matlab基础的我哭晕),唉毕竟为了快速完成任务,虽然得到了结果,但也只停留在知其然不知其所以然的阶段。

主要用到了该文献附录A中的公式(5)~公式(10),转换为代码即可。

算法原理

此算法首先要估算和纠正基于光照补偿技术的偏色效果,纠正过的RGB 颜色成分非线性地转换到YCbCr 彩色空间。检测到的肤色像素用来作为空间转换的椭圆皮肤模型。

算法步骤

  • 肤色检测及光照补偿;
  • 人脸特征定位,包括眼睛定位,嘴部定位,人脸边界定位。

色素和皮肤模型的非线性转换

将RGB颜色空间转换到YCbCr颜色空间,然后直接使用以下公式即可。

其中( 5 )式和( 6 )式中的Ci 表示任一Cb 或Cr , Wcb=46.97, WLcb=23, WHcb=14, Wcr=38.76, WLcr=20,WHcr=10,K1=125,Kh=188。这些参数值是从HHI图像的子集的皮肤块的训练数据中估算出来的,Ymin 和Ymax 在YcbCr 彩色空间的值分别是16 和235。椭圆模型的描述如(9)式和(10)式:

其中cx=109.38,cy =152.02,θ=2.53(弧度),ecx =1.60,ecy=2.41,a=25.39,b=14.03。

OpenCV实现(使用Python)

import numpy as np
import cv2
from matplotlib import pyplot as plt

test_image = cv2.imread('test.jpg')

# RGB到YCbCr色彩空间
image_YCbCr = cv2.cvtColor(test_image, cv2.COLOR_RGB2YCrCb)

# 返回行数,列数,通道个数
shape = image_YCbCr.shape

Kl, Kh = 125, 188
Ymin, Ymax = 16, 235
Wlcb, Wlcr = 23, 20
Whcb, Whcr = 14, 10
Wcb, Wcr = 46.97, 38.76
# 椭圆模型参数
Cx, Cy = 109.38, 152.02
ecx, ecy = 1.60, 2.41
a, b = 25.39, 14.03
Theta = 2.53 / np.pi * 180
# 每行
for row in range(shape[0]):
    # 每列
    for col in range(shape[1]):
        Y = image_YCbCr[row, col, 0]
        CbY = image_YCbCr[row, col, 1]
        CrY = image_YCbCr[row, col, 2]
        if Y < Kl or Y > Kh:
            # 求Cb, Cr的均值
            if Y < Kl:
                # 公式(7)
                CbY_aver = 108 + (Kl - Y) * (118 - 108) / (Kl - Ymin)
                # 公式(8)
                CrY_aver = 154 - (Kl - Y) * (154 - 144) / (Kl - Ymin)
                # 公式(6)
                WcbY = Wlcb + (Y - Ymin) * (Wcb - Wlcb) / (Kl - Ymin)
                WcrY = Wlcr + (Y - Ymin) * (Wcr - Wlcr) / (Kl - Ymin)
            elif Y > Kh:
                # 公式(7)
                CbY_aver = 108 + (Y - Kh) * (118 - 108) / (Ymax - Kh)
                # 公式(8)
                CrY_aver = 154 + (Y - Kh) * (154 - 132) / (Ymax - Kh)
                # 公式(6)
                WcbY = Whcb + (Ymax - Y) * (Wcb - Whcb) / (Ymax - Kh)
                WcrY = Whcr + (Ymax - Y) * (Wcr - Whcr) / (Ymax - Kh)
            # 求Cb(Kh), Cr(Kh)的均值
            CbKh_aver = 108 + (Kh - Kh) * (118 - 108) / (Ymax - Kh)
            CrKh_aver = 154 + (Kh - Kh) * (154 - 132) / (Ymax - Kh)
            # 公式(5)
            Cb = (CbY - CbY_aver) * Wcb / WcbY + CbKh_aver
            Cr = (CrY - CrY_aver) * Wcr / WcrY + CrKh_aver
        else:
            # 公式(5)
            Cb = CbY
            Cr = CrY
        # Cb,Cr代入椭圆模型
        cosTheta = np.cos(Theta)
        sinTehta = np.sin(Theta)
        matrixA = np.array([[cosTheta, sinTehta], [-sinTehta, cosTheta]], dtype=np.double)
        matrixB = np.array([[Cb - Cx], [Cr - Cy]], dtype=np.double)
        # 矩阵相乘
        matrixC = np.dot(matrixA, matrixB)
        x = matrixC[0, 0]
        y = matrixC[1, 0]
        ellipse = (x - ecx) ** 2 / a ** 2 + (y - ecy) ** 2 / b ** 2
        if ellipse <= 1:
            # 白
            image_YCbCr[row, col] = [255, 255, 255]
            # 黑
        else:
            image_YCbCr[row, col] = [0, 0, 0]
# 绘图
original = plt.imread('test.jpg')
plt.subplot(121)
plt.imshow(original)
plt.title('Original')
plt.subplot(122)
plt.imshow(image_YCbCr)
plt.title('New')
plt.show()

看下几个样例处理得咋样。

猜你喜欢

转载自www.linuxidc.com/Linux/2017-06/145211.htm