本笔记重点记录OpenCV中的颜色转换和利用色彩空间的特性进行皮肤检测

颜色转换

实现原理

之所以要引入色调/饱和度/亮度的色彩空间概念,是因为人们喜欢凭直觉分辨各种颜色,而它与这种方式吻合。实际上,人类更喜欢用色彩、彩度、亮度等直观的属性来描述颜色,而大多 数直觉色彩空间正是基于这三个属性。

  • 色调(hue)表示主色,我们使用的颜色名称(例如绿色、 黄色和红色)就对应了不同的色调值;
  • 饱和度(saturation)表示颜色的鲜艳程度,柔和的颜色饱 和度较低,而彩虹的颜色饱和度就很高
  • 亮度(brightness)是一个主观的属性,表示某种 颜色的光亮程度。

其他直觉色彩空间使用颜色明度(value)或颜色亮度(lightness)的概念描述 有关颜色的强度。

利用这些颜色概念,能尽可能地模拟人类对颜色的直观感知。因此,它们没有标准的定义。 根据文献资料,色调、饱和度和亮度都有多种不同的定义和计算公式。OpenCV 建议的两种直觉 色彩空间的实现是 HSV 和 HLS 色彩空间,它们的转换公式略有不同,但是结果非常相似。

亮度成分可能是最容易解释的。在 OpenCV 对 HSV 的实现中,它被定义为三个 BGR 成分中 的最大值,以非常简化的方式实现了亮度的概念。为了让定义更符合人类视觉系统,应该使用均 匀感知的色彩空间 Lab和 Luv的 L 通道。举个例子,L 通道已经考虑到了,在强度相同的 情况下,人们会觉得绿色比蓝色等颜色的亮度更高。

OpenCV 用一个公式来计算饱和度,该公式基于 BGR 组件的最小值和最大值:

其原理是:灰度颜色包含的 R、G、B 的成分是相等的,相当于一种极不饱和的颜色,因此 它的饱和度是 0(饱和度是一个 0~1.0 的值)。对于 8 位图像,饱和度被调节成一个 0~255 的值, 并且作为灰度图像显示的时候,较亮区域对应的颜色具有较高的饱和度。

利用opencv把RGB图片像HSV颜色空间转变(CV_BGR2HSV)的时候,

H通道的值范围为: 0-180

S: 0-255

V:0-255

实现代码


  1. #include <opencv2/core/core.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <opencv2/imgproc/imgproc.hpp>
  4. #include <iostream>
  5. #include <vector>
  6. int main()
  7. {
  8. // 读入图像
  9. cv::Mat image= cv::imread("boldt.jpg");
  10. if (!image.data)
  11. return 0;
  12. // 原始图像
  13. cv::namedWindow("Original image");
  14. cv::imshow("Original image",image);
  15. // 转换成HSV色彩空间
  16. cv::Mat hsv;
  17. cv::cvtColor(image, hsv, CV_BGR2HSV);
  18. // 把三个通道分割进三幅图像中
  19. std::vector<cv::Mat> channels;
  20. cv::split(hsv,channels);
  21. // channels[0] 色调
  22. // channels[1] 饱和度
  23. // channels[2] 亮度
  24. // 亮度
  25. cv::namedWindow("Value");
  26. cv::imshow("Value",channels[2]);
  27. // display 饱和度
  28. cv::namedWindow("Saturation");
  29. cv::imshow("Saturation",channels[1]);
  30. // display 色调
  31. cv::namedWindow("Hue");
  32. cv::imshow("Hue",channels[0]);
  33. cv::waitKey();
  34. }

实现效果

皮肤检测

8 位版本的色调在 0~180,饱和度在 0~255

实现原理

在对特定物体做初步检测时,颜色信息非常有用。例如辅助驾驶程序中的路标检测功能,就要凭借标准路标的颜色快速识别可能是路标的信息。另一个例子是肤色检测,检测到的皮肤区域 可作为图像中有人存在的标志。手势识别就经常使用肤色检测确定手的位置。

肤色检测领域的大量研究已经表明,来自不同人种的人群的皮肤颜色,可以在色调、饱和度、色彩空间中很好地归类。

实现代码


  1. #include <opencv2/core/core.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <opencv2/imgproc/imgproc.hpp>
  4. #include <iostream>
  5. #include <vector>
  6. void detectHScolor(const cv::Mat& image, // input image
  7. double minHue, double maxHue, // Hue interval
  8. double minSat, double maxSat, // saturation interval
  9. cv::Mat& mask) { // output mask
  10. // convert into HSV space
  11. cv::Mat hsv;
  12. cv::cvtColor(image, hsv, CV_BGR2HSV);
  13. // split the 3 channels into 3 images
  14. std::vector<cv::Mat> channels;
  15. cv::split(hsv, channels);
  16. // channels[0] is the Hue
  17. // channels[1] is the Saturation
  18. // channels[2] is the Value
  19. // Hue masking
  20. cv::Mat mask1; // below maxHue
  21. cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
  22. cv::Mat mask2; // over minHue
  23. cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);
  24. cv::Mat hueMask; // hue mask
  25. if (minHue < maxHue)
  26. hueMask = mask1 & mask2;
  27. else // if interval crosses the zero-degree axis
  28. hueMask = mask1 | mask2;
  29. // Saturation masking
  30. // below maxSat
  31. cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);
  32. // over minSat
  33. cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);
  34. cv::Mat satMask; // saturation mask
  35. satMask = mask1 & mask2;
  36. // combined mask
  37. mask = hueMask&satMask;
  38. }
  39. int main()
  40. {
  41. // 读入图像
  42. cv::Mat image= cv::imread("girl.jpg");
  43. if (!image.data)
  44. return 0;
  45. // show original image
  46. cv::namedWindow("Original image");
  47. cv::imshow("Original image",image);
  48. // detect skin tone
  49. cv::Mat mask;
  50. detectHScolor(image,
  51. 160, 10, // hue from 320 degrees to 20 degrees
  52. 25, 166, // saturation from ~0.1 to 0.65
  53. mask);
  54. // show masked image
  55. cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0));
  56. image.copyTo(detected, mask);
  57. cv::imshow("Detection result",detected);
  58. cv::waitKey();
  59. }

实现效果

可改进的地方

在检测时没有考虑颜色的亮度。在实际应用中,排除较高亮度的颜色可以降低把明亮的淡红色误认为皮肤的可能性。所以要想对皮肤颜色进行可靠和准确的检测, 还需要更加精确的分析。对不同的图像进行检测,也很难保证效果都好,因为摄影时影响彩色再 现的因素有很多,如白平衡和光照条件等。

OpenCV颜色转换和皮肤检测的更多相关文章

  1. OpenCV探索之路(二十七):皮肤检测技术

    好久没写博客了,因为最近都忙着赶项目和打比赛==| 好吧,今天我打算写一篇关于使用opencv做皮肤检测的技术总结.那首先列一些现在主流的皮肤检测的方法都有哪些: RGB color space Yc ...

  2. OpenCv皮肤检测-HSV分离

    HSV皮肤检测 // 进行肤色检测 void SkinDetect(IplImage* src, IplImage* dst) { // 创建图像头 IplImage* hsv = cvCreateI ...

  3. 使用opencv进行简单的手势检测[by Python]

    代码参考于:https://github.com/rainyear/lolita/issues/8 简单的手势识别,基本思路是基于皮肤检测,皮肤的颜色在HSV颜色空间下与周围环境的区分度更高,从RGB ...

  4. OpenCV 学习笔记 07 目标检测与识别

    目标检测与识别是计算机视觉中最常见的挑战之一.属于高级主题. 本章节将扩展目标检测的概念,首先探讨人脸识别技术,然后将该技术应用到显示生活中的各种目标检测. 1 目标检测与识别技术 为了与OpenCV ...

  5. OpenCV实战:人脸关键点检测(FaceMark)

    Summary:利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection) Author:    Amusi Date:       2018-03-20 ...

  6. cvSmooth函数 和 OpenCV自带的人脸检测

    记录cvSmooth函数的用法和 OpenCV自带的人脸检测. (1)cvSmooth函数 void cvSmooth( const CvArr* src, CvArr* dst,int smooth ...

  7. iOS中RGB颜色转换

    iOS中RGB常用的色值,同时可将对颜色的设置定义成宏,方便开发应用,如: // RGB颜色转换(16进制->10进制) #define UIColorFromRGB(rgbValue) [UI ...

  8. UIColor各种颜色转换

    1.Hex值颜色转换 #import <UIKit/UIKit.h> @interface UIColor (Extension) // 根据无符号的32位整数转换为对应的RGB颜色 + ...

  9. js颜色转换

    很久之前面试遇到过一个题.写个颜色转换的方法. function RGB2Color(r,g,b) { return '#' + byte2Hex(r) + byte2Hex(g) + byte2He ...

随机推荐

  1. codeforces 547E Mike and Friends

    codeforces 547E Mike and Friends 题意 题解 代码 #include<bits/stdc++.h> using namespace std; #define ...

  2. 多线程操作C++ STL vector出现概率coredump问题及尽量避免锁的双缓冲队列

    多线程操作全局变量,必须考虑同步问题,否则可能出现数据不一致, 甚至触发coredump. 前段时间, 遇到一个多线程操作了全局的vector的问题,  程序崩了.场景是这样的:某全局配置参数保存在一 ...

  3. 自定义input[type="checkbox"]的样式

    对复选框自定义样式,我们以前一直用的脚本来实现,不过现在可以使用新的伪类 :checkbox 来实现. 如果直接对复选框设置样式,那么这个伪类并不实用,因为没有多少样式能够对复选框起作用.不过,倒是可 ...

  4. 基于easyui开发Web版Activiti流程定制器详解(四)——页面结构(下)

    题外话: 这两天周末在家陪老婆和儿子没上来更新请大家见谅!上一篇介绍了调色板和画布区的页面结构,这篇讲解一下属性区的结构也是定制器最重要的一个页面. 属性区整体页面结构如图:  在这个区域可以定义工作 ...

  5. 关于前端惰性加载(jquery_lazyload)的使用和原理分析

    1.前言 有时我们会有这样的需求,当网页有很多张图片的时候,我们不希望一次性就把图片加载完,而是希望当浏览器滑动到指定位置的时候再加载,这样可以节省带宽,它也能帮助减轻服务器负载.那么这种需求就需要利 ...

  6. Android Studio3.0 配置AndroidAnnotation注解框架

    前言android学习了一段时间后,想要开发一款App,但是一些复杂的代码写多了实在麻烦,就到网上找了找简便的方法,于是在众多的注解开发框架中,找到了Android Annotation这个框架,这里 ...

  7. bn两个参数的计算以及layer norm、instance norm、group norm

    bn一般就在conv之后并且后面再接relu 1.如果输入feature map channel是6,bn的gamma beta个数是多少个? 6个. 2.bn的缺点: BN会受到batchsize大 ...

  8. Python3的动态加载模块简单实例

    import os import sys import time import myconfig b = ['123'] a = os.path.abspath(myconfig.__file__) ...

  9. ThinkPHP5.1中数据查询使用field方法数组参数起别名时遇到的问题

    首先数据库基本查询是没有问题的 <?php namespace app\index\controller; use think\Db; class Demo5 { //1.单条查询 public ...

  10. angularjs animation

    http://augus.github.io/ngAnimate/ http://www.nganimate.org/angularjs/ng-repeat/move http://codepen.i ...