1、本程序是用于汽车颜色识别的出版,还有很多问题。
2、目前采用的是色差法,在RGB空间计算直方图后统计出现次数较多的点,与颜色模板进行匹配;
3、颜色模板设置有些问题,造成识别效果低,有待改善。。
// color recognition.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include "cv.h"
#include<math.h>
using namespace cv;
using namespace std;
Rect r; //存储车牌位置
CvPoint origin;
IplImage* image=NULL;
int mark = 0; //选择ROI标志
// 颜色模板
国家标准规定:一般有10种颜色:
// 黑、白、红、绿、蓝、黄、 灰 , 棕、紫 粉
#define BLACK 0
#define WHITE 1
#define RED 2
#define GREEN 3
#define BLUE 4
#define YELLOW 5
#define GRAY 6
#define BROWN 7
#define PURPLE 8
#define PINK 9
int colorVelue[10][3] = {{0,0,0}, //黑
{255,255,255}, //白
{255,0,0}, //红
{0,128,0}, //绿
{0,0,255}, //蓝
{255,255,0}, //黄
// {128,128,128}, //灰
{165,42,42}, //棕像素值的范围
{128,0,128}, //紫,像素值的范围
{0,0,0}};//{255,192,203}}; //粉
void on_mouse( int event, int x, int y, int flags, void* zhang)
{
if( !image )
return;
CvPoint pt;
if( event == CV_EVENT_LBUTTONDOWN)//开始点击选择跟踪物体
{
origin = cvPoint(x,y);
r = cvRect(x,y,0,0);//坐标
r.x = MIN(x,origin.x);
r.y = MIN(y,origin.y);
r.width = r.x + CV_IABS(x - origin.x);
r.height = r.y + CV_IABS(y - origin.y);
r.x = MAX(r.x, 0);
r.y = MAX( r.y, 0);
r.width = MIN( r.width, image->width );
r.height = MIN( r.height, image->height );
r.width -= r.x;
r.height -= r.y;
}
if( event == CV_EVENT_LBUTTONUP )
{
pt = cvPoint(x,y);
mark=-1;
r.width = pt.x - r.x;
r.height = pt.y - r.y;
}
}
/*************************************************************************
* 函数名称:
* Color_difference()
* 参数:
* IplImage* car - 输入原图像
* Rect r - 源图像中划出的颜色识别区域
* 返回值:
* int* type - 指向颜色类型值,返回类型参数
* 说明:
* 该函数用来对图像进行颜色匹配识别。
************************************************************************/
int Color_difference_HSV( cv::Mat car, Rect r,int* type)
{
//复制ROI区域图像
cv::Mat roiImage = cvCreateImage(cvSize(r.width, r.height), 8, 3 );
car(r).copyTo(roiImage);
//
/*cv::imshow("roi", roiImage);
cv::waitKey(0); */
//
int hdims = 5; // 划分直方图bins的个数,越多越精确
float hranges_arr[] = {0,180};//像素值的范围
float* hranges = hranges_arr;//用于初始化CvHistogram类
IplImage* roi = &roiImage.operator IplImage();
IplImage* hsv = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 3);//用于存图像的一个中间变量,是用来分通道用的,分成hsv通道
IplImage* tmpH1 = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);//通道的中间变量,用于肤色检测的中间变量
IplImage* tmpS1 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* tmpH2 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* tmpS2 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* tmpH3 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* tmpS3 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* H = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* S = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* V = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* src_tmp1=cvCreateImage(cvGetSize(roi),8,3);
//CvHistogram *hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); //分配建立直方图空间
//IplImage* mask = cvCreateImage( cvGetSize(hsv), 8, 1 );//分配掩膜图像空间
//IplImage* hue = cvCreateImage( cvGetSize(hsv), 8, 1 );
// 高斯模糊
//cvSmooth(roi,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);
// cvCalcHist( &hue, hist, 0, mask ); // 计算直方图
if (1)
{
float velue[] = {0,0,0};
float d = sqrt(pow(colorVelue[0][0]-velue[0],2)+pow(colorVelue[0][1]-velue[1],2)+pow(colorVelue[0][2]-velue[2],2));
cout<<d<<endl;
*type = RED;
}
cvNamedWindow( "hsv", 1 );
cvShowImage("hsv",roi);
//cvWaitKey(0);
cvReleaseImage(&hsv);
cvDestroyWindow("hsv");
cvReleaseImage(&tmpH1);
cvReleaseImage(&tmpS1);
cvReleaseImage(&tmpH2);
cvReleaseImage(&tmpS2);
cvReleaseImage(&tmpH3);
cvReleaseImage(&tmpS3);
cvReleaseImage(&H);
cvReleaseImage(&S);
cvReleaseImage(&V);
cvReleaseImage(&src_tmp1);
return *type;
}
int Color_difference_RGB( cv::Mat car, Rect r,int* type)
{
//复制ROI区域图像
cv::Mat roiImage = cvCreateImage(cvSize(r.width, r.height), 8, 3 );
car(r).copyTo(roiImage);
//
/*cv::imshow("roi", roiImage);
cv::waitKey(0); */
IplImage* roi = &roiImage.operator IplImage();
IplImage* R = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* G = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);
IplImage* B = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);
// 高斯模糊
//cvSmooth(roi,roi,CV_GAUSSIAN,3,3); //高斯模糊 ,作用????
cvCvtPixToPlane(roi,B,G,R,0);//分为3个通道,OpenCV中不管是Windows中Load的还是摄像头取得的都是BGR顺序排列的
cvShowImage("R",R);
cvShowImage("G",G);
cvShowImage("B",B);
//为这四幅图创建对应的直方图结构。
int hist_size = 100;
int hist_height = 100;
float range[] = {0,255};
float* ranges[]={range};
CvHistogram* r_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
CvHistogram* g_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
CvHistogram* b_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
//计算直方图,创建用于显示直方图的图像
cvCalcHist( &R, r_hist, 0, 0 );
cvCalcHist( &G, g_hist, 0, 0 );
cvCalcHist( &B, b_hist, 0, 0 );
cvNormalizeHist(r_hist,1.0);
cvNormalizeHist(g_hist,1.0);
cvNormalizeHist(b_hist,1.0);
//开始显示,这里对直方图进行了标准化处理,不然的话无法观察到明显的变化。
int scale = 256/hist_size;
IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale,hist_height*3),8,3);
cvZero(hist_image);
float bmax_value = 0,rmax_value=0,gmax_value=0;
float min_value;
int rmin_idx, rmax_idx,gmin_idx, gmax_idx,bmin_idx,bmax_idx;
float rmax=0,gmax=0,bmax=0; //保存最高峰值
float ridx=0,gidx=0,bidx=0; //保存最高峰值的元素值
cvGetMinMaxHistValue(r_hist, 0,&rmax_value,0,&rmax_idx);
cvGetMinMaxHistValue(g_hist, 0,&gmax_value,0,0);
cvGetMinMaxHistValue(b_hist, 0,&bmax_value,0,0);
//cout<<"R最大值"<<(1-rmax_value)*255<<" "<<rmax_idx<<",G最大值"<<(1-gmax_value)*255<<",B最大值"<<(1-bmax_value)*255<<endl;
for(int i=0;i<hist_size;i++)
{
float bin_val = cvQueryHistValue_1D(r_hist,i);
int intensity = cvRound(bin_val*hist_height/rmax_value);
cvRectangle(hist_image,cvPoint(i*scale,hist_height),cvPoint((i+1)*scale - 1, hist_height - intensity),CV_RGB(255,0,0));
float k = (i+1)*255.f/hist_size;
if (rmax<bin_val)
{
rmax = bin_val;
ridx = k;
}
}
cout<<rmax<<" "<<ridx<<endl;
for(int i=0;i<hist_size;i++)
{
float bin_val = cvQueryHistValue_1D(g_hist,i);
int intensity = cvRound(bin_val*hist_height/gmax_value);
cvRectangle(hist_image,cvPoint(i*scale,2*hist_height),cvPoint((i+1)*scale - 1, 2*hist_height - intensity),CV_RGB(0,255,0));
float k = i*255.f/hist_size;
if (gmax<bin_val)
{
gmax = bin_val;
gidx = k;
}
}
cout<<gmax<<" "<<gidx<<endl;
for(int i=0;i<hist_size;i++)
{
float bin_val = cvQueryHistValue_1D(b_hist,i);
int intensity = cvRound(bin_val*hist_height/bmax_value);
cvRectangle(hist_image,cvPoint(i*scale,3*hist_height),cvPoint((i+1)*scale - 1, 3*hist_height - intensity),CV_RGB(0,0,255));
float k = i*255.f/hist_size;
if (bmax<bin_val)
{
bmax = bin_val;
bidx = k;
}
}
cout<<bmax<<" "<<bidx<<endl;
cvShowImage("ZHIFANGTUr",hist_image);
//颜色匹配
float velue[] = {ridx,gidx,bidx};
float dmin = 100000; //保存最小的距离
int colorIdx = 0;
for(int i=0 ; i < 10; i++)
{
float d = sqrt(pow(colorVelue[i][0]-velue[0],2)+pow(colorVelue[i][1]-velue[1],2)+pow(colorVelue[i][2]-velue[2],2));
if (dmin > d)
{
dmin = d;
colorIdx = i;
}
}
cout<<"colorIdx:"<<colorIdx<<endl;
*type = colorIdx;
cvNamedWindow( "hsv", 1 );
cvShowImage("hsv",roi);
cvWaitKey(0);
//cvReleaseImage(&hsv);
cvDestroyWindow("hsv");
cvReleaseImage(&R);
cvReleaseImage(&G);
cvReleaseImage(&B);
//cvReleaseImage(&src_tmp1);
cout<<"the colorof thiscar is:"<<colorIdx <<endl;
return *type;
}
int main(int argc, _TCHAR* argv[])
{
cvNamedWindow( "color recognition", 1 );//建立视频窗口
IplImage* src = cvLoadImage("Img267346543.jpg");
//读图像//
image = cvCreateImage( cvGetSize(src), 8, 3 );
cvCopy(src,image);
cvSetMouseCallback( "color recognition", on_mouse); // 设置鼠标回调函数
cvShowImage( "color recognition", image );//显示视频和直方图
车牌区域选择函数//
for (int i=0;i<4;i++)
{
if (mark)
{
cout<<"区域坐标:"<<"x:"<<r.x<<", y:"<<r.y<<", width:"<<r.width<<", height:"<<r.height<<endl;
cout<<"ok"<<endl;
}
cvWaitKey(1000);
cvRectangle(image,cvPoint(r.x,r.y),cvPoint(r.x+r.width,r.y+r.height),cvScalar(255,0,255) ,2, 8, 0);
cvShowImage( "color recognition", image );
}
cvShowImage( "color recognition", image );
cout<<"selection is ok"<<endl;
// cvWaitKey(0);
车牌区域选择函数//
if (1)
{
int i;
int j;
j = Color_difference_RGB(src,r,&i);
cout<<"the colorof thiscar is:"<< j<<endl;
}
cvReleaseImage(&image);
cvDestroyWindow("CamShiftDemo");
return 0;
}
//int main( int argc, char** argv )
//{
// IplImage * src;
// if (!(src = cvLoadImage("D:\\program Files\\matlab projects\\Lib行人数据库\\样本提取图像\\跑步姿势\\无标题.png")))
// {
// cout << "没有找到源文件" << endl;
// return -1;
// }
//
// IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );
// IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 );
// IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 );
// IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 );
// IplImage* planes[] = { h_plane, s_plane };
//
// /** H 分量划分为16个等级,S分量划分为8个等级 */
// int h_bins = 16, s_bins = 8;
// int hist_size[] = {h_bins, s_bins};
//
// /** H 分量的变化范围 */
// float h_ranges[] = { 0, 180 };
//
// /** S 分量的变化范围*/
// float s_ranges[] = { 0, 255 };
// float* ranges[] = { h_ranges, s_ranges };
//
// /** 输入图像转换到HSV颜色空间 */
// cvCvtColor( src, hsv, CV_BGR2HSV );
// cvNamedWindow( "hsv", 1 );
// cvShowImage( "hsv", hsv );
//
// cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );
// cvNamedWindow( "h_plane", 1 );
// cvShowImage( "h_plane", h_plane );
// cvNamedWindow( "s_plane", 1 );
// cvShowImage( "s_plane", s_plane );
// cvNamedWindow( "v_plane", 1 );
// cvShowImage( "v_plane", v_plane );
//
// /** 创建直方图,二维, 每个维度上均分 */
// CvHistogram * hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );
// /** 根据H,S两个平面数据统计直方图 */
// cvCalcHist( planes, hist, 0, 0 );
//
// /** 获取直方图统计的最大值,用于动态显示直方图 */
// float max_value;
// cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 );
//
//
// /** 设置直方图显示图像 */
// int height = 240;
// int width = (h_bins*s_bins*6);
// IplImage* hist_img = cvCreateImage( cvSize(width,height), 8, 3 );
// cvZero( hist_img );
//
// /** 用来进行HSV到RGB颜色转换的临时单位图像 */
// IplImage * hsv_color = cvCreateImage(cvSize(1,1),8,3);
// IplImage * rgb_color = cvCreateImage(cvSize(1,1),8,3);
// int bin_w = width / (h_bins * s_bins);
// for(int h = 0; h < h_bins; h++)
// {
// for(int s = 0; s < s_bins; s++)
// {
// int i = h*s_bins + s;
// /** 获得直方图中的统计次数,计算显示在图像中的高度 */
// float bin_val = cvQueryHistValue_2D( hist, h, s );
// int intensity = cvRound(bin_val*height/max_value);
//
// /** 获得当前直方图代表的颜色,转换成RGB用于绘制 */
// cvSet2D(hsv_color,0,0,cvScalar(h*180.f / h_bins,s*255.f/s_bins,255,0));
// cvCvtColor(hsv_color,rgb_color,CV_HSV2BGR);
// CvScalar color = cvGet2D(rgb_color,0,0);
//
// cvRectangle( hist_img, cvPoint(i*bin_w,height),
// cvPoint((i+1)*bin_w,height - intensity),
// color, -1, 8, 0 );
// }
// }
//
// cvNamedWindow( "Source", 1 );
// cvShowImage( "Source", src );
//
// cvNamedWindow("H-S Histogram", 1 );
// cvShowImage( "H-S Histogram", hist_img );
//
// cvWaitKey(0);
//}