opencv转换颜色表示法

来源:互联网 发布:java available的用法 编辑:程序博客网 时间:2024/05/16 13:38


     利用RGB色彩空间计算颜色之间的差距, 并不是衡量两个颜色相似度的最好方式。 实际上RGB并不是感知均匀的色彩空间。 就是说, 两种具有一定差距的颜色可能看起来非常接近, 而另外两种具有同样差距的颜色看起来却差别很大。为解决这个问题, 引入了一些具有感知均匀特性的颜色表示法。 CIEL*a*b*就是一种这样的颜色模型。 把图像转换到这种表示法后, 我们就可以真正地使用图像像素与目标颜色之间的欧几里德距离, 来度量颜色之间的视觉相似度。

  使用OpenCV函数cv::cvtColor可以很容易地转换图像的色彩空间。

  cv::cvtColor(image, converted, CV_BGR2Lab);


#if !defined COLORDETECTOR
#define COLORDETECTOR
#pragma once
//在文件头加入“#pragma once”,能够保证头文件被编译一次,它用来防止某个头文件被多次“include”
//#if !defined, #define, #endif 用来防止某个宏被多次定义

#include "iostream"
#include "math.h"
#include "stdio.h"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
using namespace cv;
using namespace std;

class ColorDetector
{
public:
//创建算法类的实例,定义一个构造函数
ColorDetector():minDist(230){
target[0]=target[1]=target[2]=0;
}

//////////////////////////////////////////////////////////////////////////////
//设置彩色距离阈值
void setColorDistanceThreshold(int distance){
if (distance<0){
minDist=0;
}
else
{
minDist=distance;
}
}
//获取阈值
int getColorDistanceThreshold() const{

return minDist;
}
////////////////////////////////////////////////////////////////////////////////////
//设置目标值
void setTargetColor(unsigned char red,
unsigned char green,
unsigned char blue){
target[2]=red;
target[1]=green;
target[0]=blue;
Mat tem(1,1,CV_8UC3);//临时矩阵
tem.at<Vec3b>(0,0)=Vec3b(target[0],target[1],target[2]);//给临时矩阵赋值
//BGR->Lab
cvtColor(tem,tem,CV_BGR2Lab);
target=tem.at<Vec3b>(0,0);
}
Vec3b getTargetColor()const{
return target;
}
/////////////////////////////////////////////////////////////////////////////////////
//计算两个颜色的距离
int getDistance(const Vec3b &color){
return getColorDistance(color,target);
}
int getColorDistance(const Vec3b &color1,const Vec3b &color2){
return static_cast<int>(norm<int,3>(Vec3i(color1[0]-color2[0],color1[0]-color2[0],color1[0]-color2[0])));
//Vec3i()三个向量的整形数组,norm<int,3>()欧几里得范数
}
////////////////////////////////////////////////////////////////////////////////////

//计算其他像元值与目标值得大小,并获得处理结果
Mat process1(const Mat&image);
Mat process2(const Mat &image);
protected:

private:
int minDist;
Vec3b target;
Mat result;
Mat converted_image;

};

Mat ColorDetector::process1(const Mat&image){
Mat result(image.size(),CV_8UC1,Scalar(0));
cvtColor(image,converted_image,CV_BGR2Lab);

Mat_<Vec3b>::const_iterator it=converted_image.begin<Vec3b>();
Mat_<Vec3b>::const_iterator itend=converted_image.end<Vec3b>();
Mat_<uchar>::iterator itout=result.begin<uchar>();
//对每个像素进行处理
for (;it!=itend;++itout,++it){
if (getDistance(*it)<=minDist)
{
*itout=255;
}
else{
*itout=0;
}
}
return result;
}

Mat ColorDetector::process2(const Mat &image){
Mat output;
absdiff(image,Scalar(target),output);
//把计算结果分为三个通道
vector<Mat> img;
split(output,img);
//三个通道图像相加
output=img[0]+img[2]+img[1];
threshold(output, //输入图像
output, //输出图像
minDist, //阈值
255, //最大值
THRESH_BINARY_INV);//阈值化模式
return output;
}

#endif;




#include "ColorDetector.h"


//鼠标点击获取图像的像素值(包括彩色与黑白图像)//
void onMouse(int event,int x, int y,int flags,void *param){
Mat *image=reinterpret_cast<Mat*>(param);
switch(event){
case CV_EVENT_FLAG_LBUTTON:
if (image->type()==CV_8UC1){ //gray image
cout<<"at("<<y<<","<<x<<") value is: "<<static_cast<int>(image->at<uchar>((Point(x,y))))<<endl;

else if(image->type()==CV_8UC3)//rgb(color) image
{
//cout<<"at("<<y<<","<<x<<") value is: "<<"( "<<(image->at<Vec3b>(y,x)[0])<<", "<<(image->at<Vec3b>(y,x)[1])<<", "<<(image->at<Vec3b>(y,x)[2])<<")"<<endl;
cout<<"at("<<y<<","<<x<<") value is: "<<"( "<<static_cast<int>(image->at<Vec3b>(y,x)[0])<<", "<<static_cast<int>(image->at<Vec3b>(y,x)[1])<<", "<<static_cast<int>(image->at<Vec3b>(y,x)[2])<<")"<<endl;


}
break;
}
}



void main(){
ColorDetector cdetect;
Mat image=imread("C:\\Users\\Administrator\\Desktop\\experiment\\3.png",CV_LOAD_IMAGE_COLOR);
//imshow("result",image);
cdetect.setTargetColor(230,180,130);
cdetect.setColorDistanceThreshold(160);
Mat result;
result=cdetect.process1(image);
imshow("result",result);


    setMouseCallback("result",onMouse,reinterpret_cast<void*>(&result));

waitKey(0);
}

处理图像:



处理后结果:





原创粉丝点击