将OpenCV 用于识别彩色LED颜色
将OpenCV 用于识别彩色LED颜色时,可以通过分色计算各通道非饱和像素的HSV值,能可靠识别各LED的颜色。
使用python编程,识别一个1024*480的BGR图像时,耗时约50毫秒。
可以大概识别LED的圆心座标、可以准确识别LED的色彩。记住,在识别前,要先对三通道彩色图进行模糊化处理。
最后统计ROI区域的H值总和,以及区域内非零像素的数量,求有效平均即可。
原始图像:
识别出来的图像
共检测出12个亮的LED; 本次计算耗时: 55 ms.
结果: ok ;
LED编号: 1 ; 期望颜色: YG, 实际颜色 : YG;期望状态:
亮, 实际状态: 亮;位于坐标 (509,383)
结果: ok ;
LED编号: 2 ; 期望颜色: YG, 实际颜色 : YG;期望状态:
亮, 实际状态: 亮;位于坐标 (342,375)
结果: ok ;
LED编号: 3 ; 期望颜色: R, 实际颜色 : R;期望状态:
亮, 实际状态: 亮;位于坐标 (451,315)
结果: ok ;
LED编号: 4 ; 期望颜色: O, 实际颜色 : O;期望状态:
亮, 实际状态: 亮;位于坐标 (259,309)
结果: ok ;
LED编号: 5 ; 期望颜色: O, 实际颜色 : O;期望状态:
亮, 实际状态: 亮;位于坐标 (514,275)
结果: ok ;
LED编号: 6 ; 期望颜色: B, 实际颜色 : B;期望状态:
亮, 实际状态: 亮;位于坐标 (351,268)
结果: ok ;
LED编号: 7 ; 期望颜色: R, 实际颜色 : R;期望状态:
亮, 实际状态: 亮;位于坐标 (436,212)
结果: ok ;
LED编号: 8 ; 期望颜色: O, 实际颜色 : O;期望状态:
亮, 实际状态: 亮;位于坐标 (264,201)
结果: ok ;
LED编号: 9 ; 期望颜色: B, 实际颜色 : B;期望状态:
亮, 实际状态: 亮;位于坐标 (563,149)
结果: ok ;
LED编号: 10 ; 期望颜色: W, 实际颜色 : W;期望状态:
亮, 实际状态: 亮;位于坐标 (351,145)
结果: ok ;
LED编号: 11 ; 期望颜色: G, 实际颜色 : G;期望状态:
亮, 实际状态: 亮;位于坐标 (438,82)
结果: ok ;
LED编号: 12 ; 期望颜色: W, 实际颜色 : W;期望状态:
亮, 实际状态: 亮;位于坐标 (287,68)
结果: ok ;
LED编号: 13 ; 期望颜色: W, 实际颜色 : 灭;期望状态:
灭, 实际状态: 灭;位于坐标 (1287,68)
========
七.使用OpenCv进行图像颜色识别
接着上一篇的图像灰度处理后,接下来对灰度图像进行颜色识别,本人的方法比较简单,有其他
好方法的可以提出来,大家共同进步。
目的:
将所有一副灰度图像中像素点灰度大于128的变为白色(设置为255),小于的128的变为黑色(设置为0) 。
然后统计出黑白像素点的个数。
下面是代码:
#include
#include
#include
#include
int main(int argc, char* argv[])
{
CvScalar pixel;
int i = 0, j = 0;
int numw = 0, numb = 0;
if(argc != 2)
{
printf("Usage:./test xxx.jpg\n");
return 1;
}
IplImage* img = cvLoadImage(argv[1],
CV_LOAD_IMAGE_ANYCOLOR|CV_LOAD_IMAGE_ANYDEPTH);
if(NULL == img)
{
printf("Load Image Fail!\n");
return 2;
}
//访问图像每一个像素点
for(i=0; iheight; i++)
{
for(j=0; jwidth; j++)
{
pixel = cvGet2D(img, i, j);
if(pixel.val[0] > 128)
{
pixel.val[0] = 255;//8位单通道图像在pixel.val[0]中存储像素
++numw;//统计白点个数
}
else
{
pixel.val[0] = 0;
++numb;//统计黑点个数
}
cvSet2D(img, i, j, pixel);
}
}
printf("Image Height:%d, Width:%d\n", img->height, img->width);
printf("White num:%d, Black num:%d\n", numw, numb);
cvSaveImage("Handle.jpg", img, 0);
cvReleaseImage(&img);
return 0;
}
这样处理后的图像相当于把灰度图像颜色加深一个层次,方便了后续的图像处理。
========
颜色特征(OpenCV)
对于颜色的研究还真不太好搞,因为我们在处理图片的时候通常第一件事就是将图片灰度化,这样什么所
谓的色彩信息便全部丢失,但是有的时候,当灰度图效果不佳时,可以采用不同色彩的不同通道来突出
ROI(region of interest),这里先简绍下常见的色彩空间和几个实例。
颜色空间按照基本结构可以分两大类:基色颜色空间(RGB)和色、亮分离颜色空间(CIE系列),其常见
的有如下几个(经过本人总结整理,很多没有研究透彻,这里只做基本介绍):
颜色空间
描述
特点
RGB
三原色光模式,采用加法混色法,它是描述各种“光”通过何种比例来产生颜色。
面向硬件的颜色空间,RGB颜色空间适合于显示系统,却并不适合于图像处理
CIE YUV
是通过亮度,色差来描述颜色的颜色空间。亮度信号经常被称作Y,色度信号是由两个互相独立的信号组成
CIE Lab
用于计算机色调调整和彩色校正。它独立于设备的彩色模型实现。这一方法用来把设备映射到模型及模型
本身的彩色分布质量变化
Lab颜色空间可以直接通过使用颜色空间内的几何距离来做不同颜色之间的比较分析,所以可以有效地、
方便地用在测量较小的色差上。可是尽管非线性变换空间可以消除其各个颜色分量之间存在的相关性,可
用于数字图像处理,但因为是非线性变换,所以计算量比较大,并且颜色空间同样存在奇异点的问题。
CIE
第一次基于人眼对于色彩感知度量建立色彩空间的尝试,它是几乎所有其它色彩空间的基础
国际照明委员会(CIE)
CMYK
印刷四分色模式,使用减法混色法,因为它描述的是需要使用何种油墨,通过光的反射显示出颜色。它是
在一种白色介质(画板,页面等)上使用油墨来体现图像。CMYK描述的是青,品红,黄和黑四种油墨的数值
。根据不同的油墨,介质,和印刷特性,存在多种CMYK色彩空间。(可以通过色点扩张或者转换各种油墨
数值从而得到不同的外观).
HSB(HSV,HSI,HSL)
使用色相(X轴)、饱和度(Y轴)和明度(Z轴)表示颜色的方法,HSV(色相hue,饱和度saturation,明度
value),也称HSB (B指brightness),是艺术家们常用的,因为与加法减法混色的术语相比,使用色相,饱
和度等概念描述色彩更自然直观
亮度(明度)分量与图像的彩色信息无关,所以对彩色处理只要考虑其它两个分量即可;②H与S分量与人
眼感受颜色的方式很接近。可是,HSI颜色空间存在奇异点,在距离奇异点较近处,如果R、G、B分量有微
小地变化就可能会导致H分量的巨大波动,致使系统不稳定。另一方面,HSI变换与RGB变换都是非线性变
换,耗时多,无法满足机器手进行采摘工作的实时性需要
RG Chromaticity
是用于计算机视觉的色彩空间,它可以显示光线的颜色,如红、黄、绿等,但是不能显示它的亮度如暗与
亮
YIQ
属于NTSC系统。这里Y是指颜色的明视度,即亮度。其实Y就是图像灰度值,I和Q都指的是指色调,即描述
图像色彩与饱和度的属性。
RGB和YIQ的对应关系用下面的方程式表示:
Y = 0.299R + 0.587G + 0.114B
I = 0.596R - 0.275G - 0.321B
Q = 0.212R - 0.523G + 0.311B
当研究对象是依据人的眼睛进行分类识别时候的,由于计算机表示颜色的方式通常是面向硬件的RGB色彩空
间,所以可以尝试使用与人眼更相近的色彩空间对烟叶颜色进行分析,这里考虑四个颜色空间, RGB, HSV,
HLS, Lab其各自属性如上表所述。
用不同的色彩空间描述一图片的效果如下图所示,由此可见,不同的空间描述侧重点不同。例如直观的看
HSV更偏重于RGB中最大量的显示,而HLS侧重于各个颜色的均值,Lab则更加倾向于色差区分:
RGB
颜色特征(OpenCV)
HSV
颜色特征(OpenCV)
HLS
颜色特征(OpenCV)
Lab
颜色特征(OpenCV)
说道EGB我想起来一件事,在openCV中采用的是BGR色彩格式与matlab的RGB有所不同,大家一定要注意注
意再注意,第一次搞的我郁闷了好半天。
不知道相关程序放在哪好,CSDN,CodeSoSo,pudn 还是SourceForge上会比较方便,以后再说吧。。。
to be continued。。。
上述空间与RGB转换方式如下所示HSV((1)~(3)):
颜色特征(OpenCV)
颜色特征(OpenCV)
颜色特征(OpenCV)
HLS((4)~(8)):
颜色特征(OpenCV)
颜色特征(OpenCV)
Lab((9)~(13)):
颜色特征(OpenCV)
颜色特征(OpenCV)
总结:颜色特征并不如别的特征(纹理与形状)用的那么多而且计算较为复杂,甚至有非线性计算部分,
不如只含有一层通道的灰度图计算的简单,且获得彩色信息本就比较复杂(考虑到工业相机,而不是简单
的数码相机,有机会专门写个工业相机文章,记得第一次搞相机的接口程序时候,搞的头都大了!),如
果不采用专门的相机会导致色彩的失真,还不如仅用灰度图来的划算。
用颜色的特征还需对色彩知识有一定的理解,所以通常在两种情况下会用色彩特征1)特征太少2)色彩是
区分的非常重要指标3)图像较为清晰,色彩较为准确(是拜耳算法获得的颜色信息就要仔细考虑了,否
则一用就跪了可能)4)你不是色盲或者最后一种情况,你在搞科研堆文章创新点。
接下里会进一步评价各个空间使用时候的注意事项与效果,由于需要长期测试,得花点时间才能有所感悟
...
to be continued。。。
========
OpenCV颜色识别
彩色模型
HSV模型
RGB转HSV
颜色识别的应用
彩色模型
数字图像处理中常用的采用模型是RGB(红,绿,蓝)模型和HSV(色调,饱和度,亮度),RGB广泛应用
于彩色监视器和彩色视频摄像机,我们平时的图片一般都是RGB模型。而HSV模型更符合人描述和解释颜色
的方式,HSV的彩色描述对人来说是自然且非常直观的。
HSV模型
HSV模型中颜色的参数分别是:色调(H:hue),饱和度(S:saturation),亮度(V:value)。由A.
R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。
色调(H:hue):用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿
色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度(S:saturation):取值范围为0.0~1.0,值越大,颜色越饱和。
亮度(V:value):取值范围为0(黑色)~255(白色)。
RGB转HSV
设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数。设 max 等价于
r, g 和 b 中的最大者。设 min 等于这些值中的最小者。要找到在 HSV 空间中的 (h, s, v) 值,这里
的 h ∈ [0, 360)是角度的色相角,而 s, v ∈ [0,1] 是饱和度和亮度,计算为:
max=max(R,G,B)
min=min(R,G,B)
if R = max, H = (G-B)/(max-min)
if G = max, H = 2 + (B-R)/(max-min)
if B = max, H = 4 + (R-G)/(max-min)
H = H * 60
if H < 0, H = H + 360
V=max(R,G,B)
S=(max-min)/max
OpenCV下有个函数可以直接将RGB模型转换为HSV模型,注意的是OpenCV中H∈ [0, 180), S ∈ [0,
255], V ∈ [0, 255]。我们知道H分量基本能表示一个物体的颜色,但是S和V的取值也要在一定范围内
,因为S代表的是H所表示的那个颜色和白色的混合程度,也就说S越小,颜色越发白,也就是越浅;V代表
的是H所表示的那个颜色和黑色的混合程度,也就说V越小,颜色越发黑。经过实验,识别蓝色的取值是 H
在100到140,S和V都在90到255之间。一些基本的颜色H的取值可以如下设置:
Orange 0-22
Yellow 22- 38
Green 38-75
Blue 75-130
Violet 130-160
Red 160-179
OpenCV实现
首先我们读取一张图片或从视频读取一帧图像,用下面的函数转为HSV模型。
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV);
然后我们对彩色图像做直方图均衡化
//因为我们读取的是彩色图,直方图均衡化需要在HSV空间做
split(imgHSV, hsvSplit);
equalizeHist(hsvSplit[2],hsvSplit[2]);
merge(hsvSplit,imgHSV);
接着就是进行颜色检测,我们用void inRange(InputArray src, InputArray lowerb, InputArray
upperb, OutputArray dst);函数进行颜色检测,这个函数的作用就是检测src图像的每一个像素是不是在
lowerb和upperb之间,如果是,这个像素就设置为255,并保存在dst图像中,否则为0。
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV),
imgThresholded); //Threshold the image
通过上面的函数我们就可以得到目标颜色的二值图像,接着我们先对二值图像进行开操作,删除一些零零
星星的噪点,再使用闭操作,连接一些连通域,也就是删除一些目标区域的白色的洞。
//开操作 (去除一些噪点)
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
//闭操作 (连接一些连通域)
morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);
整个代码实现
#include
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
VideoCapture cap(0); //capture the video from web cam
if ( !cap.isOpened() ) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
int iLowH = 100;
int iHighH = 140;
int iLowS = 90;
int iHighS = 255;
int iLowV = 90;
int iHighV = 255;
//Create trackbars in "Control" window
cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
cvCreateTrackbar("HighH", "Control", &iHighH, 179);
cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
cvCreateTrackbar("HighS", "Control", &iHighS, 255);
cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
cvCreateTrackbar("HighV", "Control", &iHighV, 255);
while (true)
{
Mat imgOriginal;
bool bSuccess = cap.read(imgOriginal); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
Mat imgHSV;
vector hsvSplit;
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to
HSV
//因为我们读取的是彩色图,直方图均衡化需要在HSV空间做
split(imgHSV, hsvSplit);
equalizeHist(hsvSplit[2],hsvSplit[2]);
merge(hsvSplit,imgHSV);
Mat imgThresholded;
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV),
imgThresholded); //Threshold the image
//开操作 (去除一些噪点)
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
//闭操作 (连接一些连通域)
morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);
imshow("Thresholded Image", imgThresholded); //show the thresholded image
imshow("Original", imgOriginal); //show the original image
char key = (char) waitKey(300);
if(key == 27)
break;
}
return 0;
}
实验结果图:
这里写图片描述
颜色识别的应用
经典的颜色识别的经典应用就是车牌定位了,因为中国的车牌无非就是蓝色和黄色,还有就是交通标志定
位也是个应用。比如下面两张图片,有很明显的颜色区分。
这里写图片描述
========
opencv进行药片识别,在区分颜色方面的一点小小问题
opencv 目前在做一个设计,就是在一堆药片里面区分出不同颜色的药片以及破损的药片。
我的思路:
1.摄像头读取实时画面 (已实现)
2.对画面颜色进行区分,比如设定一个阈值,只保留白色药片,再设一个阈值,只保留红色药片
(未实现)
3.分别对图片进行处理,灰度,二值,检测轮廓,cvFindContours得出个数和面积,通过平均面积和轮廓区域面积进行比较,得出破损和重叠的药片。(已经实现)
4.得到了不同颜色药片的区域了,用cvDrawContours用不同颜色的画线描绘出来。(已经实现)
现在的难题就是第2点,网上找了很多,就是没有代码可以参考,
我认为应该先遍历整张图的rgb像素值,然后设定,比如图像中有白色,红色药片,黑色作为背景。 将图像复制为2份, 先得出了每个位置的rgb值,红色rgb为(255,0,0) 黑色为(0,0,0) 那我可以设定 当 200 这样图中只有红黑,然后通过上述3,4步得到结果。
现在就卡在了这一步写程序上面,
因为非专业原因,所以颜色识别的要求会很低,比如只会有 红, 白, 绿这些非常明显颜色的药片,在纯黑为背景下!
========
OpenCV2 颜色识别
在这个例子中,我们开始选定一种颜色,并设置一个阈值
然后把图片中和所选颜色的差别在阈值中的点标定出来
在这个例子中,主要要注意这两点:
1. OpenCV与QT的结合,包括Mat 与 QImage 的转换
2. 我们使用了类来实现此功能,创建了一个单例模式的类
首先我们创建一个简单的图形界面,使用的是QT
创建处理图像用的类
#ifndef COLORDETECTOR_H_
#define COLORDETECTOR_H_
#include
#include
#include
class ColorDetector{
private:
int minDist;
cv::Vec3b target;
cv::Mat result;
cv::Mat image;
ColorDetector();
static ColorDetector *singleton;
public:
static ColorDetector * getInstance();
static void destory();
void setColorDistanceThreshold(int);
int getColorDistanceThreshold() const;
void setTargetColor(unsigned char, unsigned char, unsigned char);
void setTargetColor(cv::Vec3b);
cv::Vec3b getTargetColor() const;
void process();
int getDistance(const cv::Vec3b&) const;
cv::Mat getResult() const;
bool setInputImage(std::string);
cv::Mat getInputImage() const;
};
#endif /* COLORDETECTOR_H_ */
将其构造函数声明为private,提供静态的接口来获得ColorDetector对象
void setColorDistanceThreshold(int) 用于设置阈值
void setTargetColor(unsigned char, unsigned char, unsigned char)
void setTargetColor(cv::Vec3b) 用于设置颜色
bool setInputImage(std::string) 用于载入待处理图像
cv::Mat getResult() const 用于返回处理结果,结果用一副图像表示
其具体实现如下
#include "ColorDetector.h"
ColorDetector* ColorDetector::singleton = 0;
ColorDetector::ColorDetector():minDist(100){
target[0] = target[1] = target[2] = 0;
}
ColorDetector* ColorDetector::getInstance(){
if(singleton == 0){
singleton = new ColorDetector;
}
return singleton;
}
void ColorDetector::destory(){
if(singleton!=0){
delete singleton;
}
singleton = 0;
}
void ColorDetector::setColorDistanceThreshold(int distance){
if(distance < 0){
distance = 0;
}
minDist = distance;
}
int ColorDetector::getColorDistanceThreshold() const{
return minDist;
}
void ColorDetector::setTargetColor(unsigned char red,
unsigned char green, unsigned char blue){
target[2] = red;
target[1] = green;
target[0] = blue;
}
void ColorDetector::setTargetColor(cv::Vec3b color){
target = color;
}
cv::Vec3b ColorDetector::getTargetColor() const{
return target;
}
int ColorDetector::getDistance(const cv::Vec3b& color) const{
return abs(color[0]-target[0])+abs(color[1]-target[1])+abs(color[2]-target[2]);
}
void ColorDetector::process(){
result.create(image.rows, image.cols, CV_8U);
cv::Mat_::const_iterator it = image.begin();
cv::Mat_::const_iterator itend = image.end();
cv::Mat_::iterator itout = result.begin();
for(; it!=itend; ++it, ++itout){
if(getDistance(*it) < minDist){
*itout = 255;
}else{
*itout = 0;
}
}
}
cv::Mat ColorDetector::getResult() const{
return result;
}
bool ColorDetector::setInputImage(std::string filename){
image = cv::imread(filename);
if(!image.data){
return false;
}
return true;
}
cv::Mat ColorDetector::getInputImage() const{
return image;
}
在前面文章中,讲了遍历像素点的方法,这里用迭代器实现
然后是图像界面中的处理函数
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
#include "colordetector.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
QImage qimage;
cv::Mat image;
private slots:
void openImage();
void dealImage();
void colorSelect();
void changeDis(int);
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->openImage,SIGNAL(clicked()),this,SLOT(openImage()));
connect(ui->dealImage,SIGNAL(clicked()),this,SLOT(dealImage()));
connect(ui->colorButton,SIGNAL(clicked()),this,SLOT(colorSelect()));
connect(ui->verticalSlider,SIGNAL(valueChanged(int)),this,SLOT(changeDis(int)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::openImage(){
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), ".",
tr("Image Files (*.png *.jpg *.jpeg *.bmp)"));
ColorDetector::getInstance()->setInputImage(fileName.toAscii().data());
cv::namedWindow("image");
cv::imshow("image",ColorDetector::getInstance()->getInputImage());
dealImage();
}
void Widget::dealImage(){
ColorDetector::getInstance()->process();
cv::cvtColor(ColorDetector::getInstance()->getResult(),image,CV_GRAY2RGB);
qimage = QImage((const unsigned char*)(image.data),image.cols,image.rows,QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(qimage).scaledToHeight(300));
//ui->label->resize(ui->label->pixmap()->size());
}
void Widget::colorSelect(){
QColor color = QColorDialog::getColor(Qt::green,this);
if(color.isValid()){
ColorDetector::getInstance()->setTargetColor(
color.red(),color.green(),color.blue());
}
dealImage();
}
void Widget::changeDis(int value){
ColorDetector::getInstance()->setColorDistanceThreshold(value);
dealImage();
}
在QT项目的pro文件中要加入如下几句
INCLUDEPATH += D:\OpenCV\include
LIBS += -LD:\OpenCV\lib \
-lopencv_core230 \
-lopencv_highgui230 \
-lopencv_imgproc230
看看最后效果
不同颜色,不同阈值的比较效果
========
opencv-根据颜色进行目标检测
#include
#include
// 该接口来至 冰风2009手势识别
// 进行肤色检测
void SkinDetect(IplImage* src,IplImage* dst)
{
// 创建图像头
IplImage* hsv = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);//用于存图像的一个中间变量,是用来分通道用的,分成hsv通道
IplImage* tmpH1 = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);//通道的中间变量,用于肤色检测的中间变量
IplImage* tmpS1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* tmpH2 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* tmpS3 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* tmpH3 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* tmpS2 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* H = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* S = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* V = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* src_tmp1=cvCreateImage(cvGetSize(src),8,3);
// 高斯模糊
cvSmooth(src,src_tmp1,CV_GAUSSIAN,3,3); //高斯模糊
// hue色度,saturation饱和度,value纯度
cvCvtColor(src_tmp1, hsv, CV_BGR2HSV );//颜色转换
cvCvtPixToPlane(hsv,H,S,V,0);//分为3个通道
/*********************肤色检测部分**************/
cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(20.0,0.0,0,0),tmpH1);
cvInRangeS(S,cvScalar(75.0,0.0,0,0),cvScalar(200.0,0.0,0,0),tmpS1);
cvAnd(tmpH1,tmpS1,tmpH1,0);
// Red Hue with Low Saturation
// Hue 0 to 26 degree and Sat 20 to 90
cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(13.0,0.0,0,0),tmpH2);
cvInRangeS(S,cvScalar(20.0,0.0,0,0),cvScalar(90.0,0.0,0,0),tmpS2);
cvAnd(tmpH2,tmpS2,tmpH2,0);
// Red Hue to Pink with Low Saturation
// Hue 340 to 360 degree and Sat 15 to 90
cvInRangeS(H,cvScalar(170.0,0.0,0,0),cvScalar(180.0,0.0,0,0),tmpH3);
cvInRangeS(S,cvScalar(15.0,0.0,0,0),cvScalar(90.,0.0,0,0),tmpS3);
cvAnd(tmpH3,tmpS3,tmpH3,0);
// Combine the Hue and Sat detections
cvOr(tmpH3,tmpH2,tmpH2,0);
cvOr(tmpH1,tmpH2,tmpH1,0);
cvCopy(tmpH1,dst);
cvReleaseImage(&hsv);
cvReleaseImage(&tmpH1);
cvReleaseImage(&tmpS1);
cvReleaseImage(&tmpH2);
cvReleaseImage(&tmpS2);
cvReleaseImage(&tmpH3);
cvReleaseImage(&tmpS3);
cvReleaseImage(&H);
cvReleaseImage(&S);
cvReleaseImage(&V);
cvReleaseImage(&src_tmp1);
}
int main(int argc, char* argv[])
{
IplImage *src=cvLoadImage("hand.jpg", CV_LOAD_IMAGE_COLOR);
//
cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
cvShowImage("src", src);
//
cvNamedWindow("flip", CV_WINDOW_AUTOSIZE);
IplImage *dsc = cvCreateImage(cvGetSize(src), src->depth, 1);
// 以x轴翻转
SkinDetect(src, dsc);
// cvFlip(src, dsc, 1);
cvShowImage("flip", dsc);
cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseImage(&src);
printf("Hello World!/n");
return 0;
}
========
如何使用Opencv对图像进行颜色特征提取
如何使用Opencv对图像进行颜色特征提取1如何使用Opencv对图像进行颜色特征提取2如何使用Opencv对图像进行颜色特征提取3如何使用Opencv对图像进行颜色特征提取4如何使用Opencv对图像进行颜色特征提取5如何使用Opencv对图像进行颜色特征提取6如何使用Opencv对图像进行颜色特征提取7
这是一张24色卡,有24种颜色在里面,该色卡通常用于测试摄像头camera色偏,如手机,平板电脑摄像头。实际测试可能位置会有偏移,这对于计算机视觉识别带来不便,一种方式克服的方法就是根据颜色特征计算位置坐标,进而进行图像分析。本文基于OpenCV计算机视觉库,开发简单程序用于识别图片颜色特征。本文先以提取红色方块进行示范。
如何使用Opencv对图像进行颜色特征提取
方法/步骤
1
打开小画家,将色卡打开,点击吸管工具,移动鼠标到红色块上方,松开鼠标,此时,吸管工具已经提取了红色色块信息。然后点击右方的“编辑颜色”,弹出颜色选择对话框,此时,右下角有刚才习惯的红绿蓝颜色信息,如红152,绿18,蓝15。这个就是颜色对应的RGB色彩值。
2
创建VC控制台工程,加入所需头文件和库文件。注意要事先将opencv 头文件和库文件添加到工程属性中,作者使用opencv2.4+VC2010示范。
#include
#include
#include
#include
#include
#include
#pragma comment (lib,"opencv_core244d.lib")
#pragma comment (lib,"opencv_highgui244d.lib")
#pragma comment (lib,"opencv_imgproc244d.lib")
3
定义一个颜色常量target,默认值即为刚才吸管工具提取的红色色块的RGB值分量,和一个计算与颜色标准值色差的函数,暂定为色差在10以内即为相近颜色。这里cv::Vec3b 变量对应一个数组值, Vec3b[0] 对应blue,Vec3b[1]对应green,Vec3b[2]对应Red,即BGR。
4
接着添加以下代码,目的为读取源图片,根据图片大小做一定的缩放,然后定义同样大小的一个灰度图,用于存贮计算结果值。核心算法如下,遍历源图片,色差(与红色色块比较)低于30的即为需要提取的颜色值,将此像素位置记录并写入到灰度图中,以黑色显示,否则设置为白色。然后将处理前后图片显示出来。
5
实际商业应用中也是可以如法炮制的,比如下图的药片,大小,颜色不统一,如何提取识别黄色小药片在何处或计算其数量呢。
笔者尝试使用吸管工具提取其BGR值为(22,184,245),将色差由10调整为30,可以正确检测此药片。如图。
6
提取后的二值化图片如果再处理一次,比如做轮廓检测,或计算面积或辨别三角形或四边形或多边形,可以确定具体位置,或者能够做更细致的 筛选,
========