当前位置:   article > 正文

数字图像处理之目标颜色识别_颜色识别算法

颜色识别算法

实验要求

找到目标颜色所在区域

算法实现

  1. 色度空间转换
    1.1 读取图像并滤波
    1.2 根据公式将图像从rgb转换到hsv色度空间
    在这里插入图片描述

  2. 颜色分割
    2.1 利用 createTrackbar()函数建立滑动条,对颜色空间转换后的各通道进行阈值分割
    2.2 根据阈值分割的结果,判断各种颜色的对应阈值
    2.3 针对不同颜色,分别对图像进行阈值分割
    2.4 对阈值分割结果进行数学统计,判断图像的颜色并输出分类结果
    在这里插入图片描述

  3. 目标颜色检测
    3.1 对图像进行预处理,消除噪声并获取二值化图
    3.2 对二值图进行轮廓检测;
    3.3 根据任务目标选择合适的多边形描述轮廓;
    3.4 获取多边形区域后,从原图中截取该区域图像;
    3.5 对多边形区域的图像进行颜色分割,对分割结果进行统计,判断图像的颜色并输出分类结果

代码实现

#include <stdlib.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#define LINEAR_X 0

#define SIZE 3
#define PI 3.1415926
#define HMaxValue 255
#define SMaxValue 255
#define VMaxValue 255
#define oo 1e9+7
using namespace std;
using namespace cv;
int H_min=100, H_max=124, S_min=43, S_max=255, V_min=46, V_max=255;
Mat img_in;
void Gaussian(Mat input, Mat output, double sigma){
	double weight;//权重
	double sum = 0; 
	double Gaussian_Temp[SIZE][SIZE] = {0};//模板
	weight = (2*PI*sigma*sigma);  
	for(int i =0;i <SIZE;i++)  
	{  
		for(int j = 0;j < SIZE;j++)  
		{  
			int x = i - SIZE/2;
			int y = j - SIZE/2;
		    Gaussian_Temp[i][j] =exp(-(x*x+y*y)/(2.0*sigma*sigma))/weight;  
		    sum += Gaussian_Temp[i][j];  
		}  
	}  

	for(int i = 0; i < SIZE;i++)  
	{  
		for(int j = 0;j < SIZE;j++)  
		{  
		    Gaussian_Temp[i][j] = Gaussian_Temp[i][j]/sum;//归一化处理  
		    //printf("%f ",Gaussian_Temp[i][j]);  
		}  
		//printf("\n");  
	}
	
	int rows = output.rows;
	int cols = output.cols;
	int channels = input.channels();
	for(int i=0;i<rows;i++)
	{
		for(int j=0;j<cols;j++)
		{
			int sum3[3]={0};
			int sum1 = 0;
			for(int k=0;k<SIZE;k++)
				for(int t=0;t<SIZE;t++)
				{
					int x=i+k-SIZE/2;
					int y=j+t-SIZE/2;
					if(x<0||y<0||x>=rows||y>=cols)continue;
					double m=Gaussian_Temp[k][t];
					if(channels == 1)sum1+=m*input.at<uchar>(x,y);
					else if(channels == 3)
					{
						Vec3b rgb = input.at<Vec3b>(x,y);
						sum3[0]+=m*rgb[0];
						sum3[1]+=m*rgb[1];
						sum3[2]+=m*rgb[2];
						
					}
				}
			if(channels == 3){
				for(int k=0;k<3;k++){
					if(sum3[k]>255)sum3[k]=255;
					if(sum3[k]<0)sum3[k]=0;
					output.at<Vec3b>(i,j)[k]=sum3[k];
				}
			}
			else {
				if(sum1>255)sum1=255;
				if(sum1<0)sum1=0;
				output.at<uchar>(i,j)=sum1;
			}
		}
	}
}
void RBG2HSV(Mat input,Mat output){
	int rows=input.rows;
	int cols=input.cols;
	//cout<<rows<<" "<<cols<<endl;
	for(int i=0;i<rows;i++){
		for(int j=0;j<cols;j++){
			Vec3b pix=input.at<Vec3b>(i,j);//012:BGR
			float b=1.0*pix[0]/255;
			float g=1.0*pix[1]/255;
			float r=1.0*pix[2]/255;
			float maxrgb=max(r,max(g,b));
			float minrgb=min(r,min(g,b));
			float diff=maxrgb-minrgb;
			float v=maxrgb;
			float s=(diff/v);
			float h;
			if(maxrgb-minrgb<1e-5)h=0;
			else if(maxrgb==r)h=60*(g-b)/diff;
			else if(maxrgb==g)h=60*(b-r)/diff+120;
			else if(maxrgb==b)h=60*(r-g)/diff+240;
			if(h<0)h+=360;
			else if(h>359)h-=360;
			output.at<Vec3b>(i,j)[0]=(int)(h*180/360);
			output.at<Vec3b>(i,j)[1]=(int)(s*255);
			output.at<Vec3b>(i,j)[2]=(int)(v*255);

		}
	}
}
/*
画颜色统计图
*/
void Statistical(Mat input){
    int weigth=210,height=300;
    Mat output=Mat::zeros(height,weigth,CV_8UC3);
	int rows=input.rows;
	int cols=input.cols;
	int colorNum[7]={0};
	int sum=rows*cols;
	for(int i=0;i<rows;i++){
		for(int j=0;j<cols;j++){
			Vec3b pix=input.at<Vec3b>(i,j);//012:HSV
			if(pix[1]<43||pix[2]<46)continue;
			//pix[0]=pix[0]*180/255;
			int color=0;
			if((pix[0]>=0&&pix[0]<=10)||(pix[0]>=156&&pix[0]<=180))color=0;
			else if(pix[0]>=11&&pix[0]<=25)color=1;
			else if(pix[0]>=26&&pix[0]<=34)color=2;
			else if(pix[0]>=35&&pix[0]<=77)color=3;
			else if(pix[0]>=78&&pix[0]<=99)color=4;
			else if(pix[0]>=100&&pix[0]<=124)color=5;
			else if(pix[0]>=125&&pix[0]<=155)color=6;
			colorNum[color]++;
		}
	}
	
    Scalar Color[7]={Scalar(0,0,255),Scalar(0,125,255),Scalar(0,255,255),Scalar(0,255,0),Scalar(255,255,0),Scalar(255,0,0),Scalar(255,0,255)};
	 for(int i=0;i<7;i++){  
	    int h=colorNum[i]*height/sum;
	    rectangle(output,Point(i*30,height),Point((i+1)*30-1, height-h),Color[i],-1);
	 }
	 imshow("color",output);
}
void colorDetection(Mat input){
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy; 
	findContours( input, contours, hierarchy,  RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0) );
	if(contours.size()==0)return;
	int area=0,x=0,y=0,a=0,b=0,c=0,d=0;
	for(int k=0;k<contours.size();k++){
	    RotatedRect rectPoint = minAreaRect(contours[k]);
	    Point2f point[4]; 
	    //将rectPoint变量中存储的坐标值放到 point的数组中  
	    rectPoint.points(point);
		//寻找轮廓的左上角和右下角,算出长宽
	    int max_x=0,max_y=0,min_x=oo,min_y=oo;
        for (int i = 0; i < 4; i++)
        {
		    if (max_x < point[i].x)max_x=int(point[i].x+0.5);
		    if (max_y < point[i].y)max_y=int(point[i].y+0.5);
		    if (min_x > point[i].x)min_x=(int)point[i].x;
		    if (min_y > point[i].y)min_y=(int)point[i].y;
		    
        }   
        if(min_x<0)min_x=0;
    	if(min_y<0)min_y=0;
    	if(max_x>=input.cols)max_x=input.cols-1;
        if(max_y>=input.rows)max_y=input.rows-1;
        if((max_x-min_x)*(max_y-min_y)>area){
        	area=(max_x-min_x)*(max_y-min_y);
        	x=min_x;
        	y=min_y;
        	a=max_x;
        	b=max_y;
        	c=max_x-min_x;
        	d=max_y-min_y;
        }
    }
	
    if(c==0||d==0)return;
	//截取ROI区域
    Mat output=img_in(Rect(x,y,c,d));
    imshow("ROI",output);
    Mat hsv=Mat::zeros(output.size(),CV_8UC3);
    RBG2HSV(output,hsv);
	//统计截取之后的图像各种颜色的含量
    Statistical(hsv);
}
/*
颜色分割
*/
void thresholdSeq(int var,void* usrdata){
	Mat input = *(static_cast<Mat*> (usrdata));
	Mat output=Mat::zeros(input.size(),CV_8UC1);
	int rows=input.rows;
	int cols=input.cols;
	for(int i=0;i<rows;i++){
		for(int j=0;j<cols;j++){
			Vec3b pix=input.at<Vec3b>(i,j);//012:HSV
			if(pix[0]<H_min||pix[0]>H_max)continue;
			if(pix[1]<S_min||pix[1]>S_max)continue;
			if(pix[2]<V_min||pix[2]>V_max)continue;
			output.at<uchar>(i,j)=255;
		}
	}
	imshow("thresholdSeq",output);
	//目标颜色检测
	colorDetection(output);
}
int main(int argc, char **argv)
{
	//读取原始图像
	img_in=imread(argv[1],IMREAD_UNCHANGED);
	//检查是否读取图像
	if(img_in.empty()){
		cout<<"Error! Input image cannot be read...\n";
		return -1;
	}
	
	imshow("src",img_in);
	Mat frOut1=Mat::zeros(img_in.size(),CV_8UC3);
	Mat frOut2=Mat::zeros(img_in.size(),CV_8UC1);
	// 空域滤波函数
	Gaussian(img_in,frOut1,1);
	// 色度空间转换
	RBG2HSV(frOut1,frOut1); 
	//阈值分割
	namedWindow("thresholdSeq");	
	createTrackbar("H_min", "thresholdSeq", &H_min, HMaxValue, thresholdSeq,&frOut1);
	createTrackbar("H_max", "thresholdSeq", &H_max, HMaxValue, thresholdSeq,&frOut1);
	createTrackbar("S_min", "thresholdSeq", &S_min, SMaxValue, thresholdSeq,&frOut1);
	createTrackbar("S_max", "thresholdSeq", &S_max, SMaxValue, thresholdSeq,&frOut1);
	createTrackbar("V_min", "thresholdSeq", &V_min, VMaxValue, thresholdSeq,&frOut1);
	createTrackbar("V_max", "thresholdSeq", &V_max, VMaxValue, thresholdSeq,&frOut1);
	waitKey();
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239

运行结果

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/836877
推荐阅读
相关标签
  

闽ICP备14008679号