OpenCV描述直觉色彩空间有HSV和HLS两种色彩空间,它们的转换公式略有不同,但是结果非常类似。
在HSV中,
亮度被定义为三个RGB成分中的最大值。为了让定义更符合人类视觉系统,应该是用L*a*b或L*u*v色彩空间的L通道
饱和度的计算公式为:
色调通常用0~360度来表示,红色是0度。
而HSB色彩空间通常用一个圆锥体来表示,圆锥体内部每个点代表一种特定的颜色。角度位置表示的是颜色的色调,到中轴线的距离表示饱和度,高度表示亮度。
肤色检测使用颜色信息进行j检测
为了让颜色来检测目标,首先需要收集一个存储有大量图像样本的数据库,每个样本中包含从不同观察条件下捕捉到的目标,作为定义分类器的参数。不同人中的肤色,可以在色调-饱和度色彩空间中很好地归类。
效果:
代码:
#include <iostream>
#include "opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
void detectHScolor(const cv::Mat& image, double minHue, double maxHue, double minSat, double maxSat, cv::Mat& mask)
{
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_RGB2HSV);
std::vector<cv::Mat> channels;
cv::split(image, channels);
//色调掩码
cv::Mat mask1;
cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
cv::Mat mask2;
cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);
cv::Mat hueMask;
if (minHue < maxHue)
hueMask = mask1&mask2;
else
hueMask = mask1 | mask2;
//饱和度掩码
cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);
cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);
cv::Mat satMask;
satMask = mask1&mask2;
mask = hueMask&satMask;
}
int main()
{
cv::Mat image = cv::imread("girl.jpg");
cv::imshow("原图", image);
cv::Mat mask;
detectHScolor(image, 130, 240, 100, 255, mask);
cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0));
image.copyTo(detected, mask);
cv::imshow("肤色检测图", detected);
cv::waitKey();
}