OpenCV 检测肤色不随光照变化

信息处理 图像处理 opencv 物体识别
2022-01-16 21:15:52

我必须捕捉独立于照明的肤色。我使用了以下标准(使用 hsv 和 rgb)但它不起作用:

int h = get_hue(...);
int s = get_saturation(...);
int r = get_red_component(...);
int g = get_green_component(...);
int b = get_blue_component(...);

if ((h<38)&&(h>6)&&(s>0.23)&&(s<0.68)){
    // skin color
}
else if ((r>95) && (g>40) && (b>20) && 
         ((maximum(r,g,b)-minimum(r,g,b))>15) && 
         (abs(r-g)>15)&&(r>g)&&(r>b)){
   // also skin color
}

它在早上我的皮肤被照亮时起作用,但到了晚上它不起作用。

任何帮助将不胜感激。提前致谢。(PS——我的皮肤不是白的。)

3个回答

根据我的经验,最好的方法是将其转换为 Lab 颜色空间。L代表光,a和b是光独立的。OpenCV 支持 Lab 色标转换。

对于这种特殊情况,我建议阅读 LAB Color 模型。

关于 LAB 颜色模型,请阅读 Delta E。两种颜色之间的距离。关于色彩空间的更多细节可以在这里找到:http: //www.codeproject.com/Articles/613798/Colorspaces-and-Conversions

我从未尝试过通过 OpenCV 使用 LAB 颜色模型,因为从 RGB 转换为 LAB 并返回(需要立即执行)很麻烦。

但我在 MatLab 上探索了 Delta E 并取得了巨大成功。您必须首先选择皮肤,在视频/图片上绘制一个小的 ROI,程序将找到与您通过 ROI 选择的皮肤完全相同的色调。

另一种选择是查看纹理。在此处进行简短预览:http: //books.google.com.sg/books ?id=bRlk_WjfITIC&pg=PA598&lpg=PA598&dq=skin+thresholding+from+texture&source=bl&ots=28fE0livyh&sig=8EeQTLFCc-JB979_-ccyrhDJlqA&hl=en&sa=X&ei=aCugBg&hvedJoWJrQ =0CDUQ6AEwAQ#v=onepage&q=skin%20thresholding%20from%20texture&f=false

这基本上是在训练一个图像数据库。如果您在训练图像数据库或 ColorSpace 转换方面需要帮助,请在此处评论。有点忙,所以答案只是你可以做的建议。干杯。

尝试这个:

''' Detect human skin tone and draw a boundary around it.
Useful for gesture recognition and motion tracking.

Inspired by: http://stackoverflow.com/a/14756351/1463143

Date: 08 June 2013
'''

# Required moduls
import cv2
import numpy

# Constants for finding range of skin color in YCrCb
min_YCrCb = numpy.array([0,133,77],numpy.uint8)
max_YCrCb = numpy.array([255,173,127],numpy.uint8)

# Create a window to display the camera feed
cv2.namedWindow('Camera Output')

# Get pointer to video frames from primary device
videoFrame = cv2.VideoCapture(0)

# Process the video frames
keyPressed = -1 # -1 indicates no key pressed

while(keyPressed < 0): # any key pressed has a value >= 0

    # Grab video frame, decode it and return next video frame
    readSucsess, sourceImage = videoFrame.read()

    # Convert image to YCrCb
    imageYCrCb = cv2.cvtColor(sourceImage,cv2.COLOR_BGR2YCR_CB)

    # Find region with skin tone in YCrCb image
    skinRegion = cv2.inRange(imageYCrCb,min_YCrCb,max_YCrCb)

    # Do contour detection on skin region
    contours, hierarchy = cv2.findContours(skinRegion, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Draw the contour on the source image
    for i, c in enumerate(contours):
        area = cv2.contourArea(c)
        if area > 1000:
            cv2.drawContours(sourceImage, contours, i, (0, 255, 0), 3)

    # Display the source image
    cv2.imshow('Camera Output',sourceImage)

    # Check for user input to close program
    keyPressed = cv2.waitKey(1) # wait 1 milisecond in each iteration of while loop

# Close window and camera after exiting the while loop
cv2.destroyWindow('Camera Output')
videoFrame.release()