歡迎您光臨本站 註冊首頁

使用opencv識別影象紅色區域,並輸出紅色區域中心點座標

←手機掃碼閱讀     月球人 @ 2020-06-12 , reply:0

適用小白,大佬勿噴

個人配置:vs2013 ; opencv 3.0 ;

直接上效果圖

注意:右下角的水印把中心點擋住了,要仔細看才能看到

下面是程式碼:

  #include#include#include#include#define PI 3.1415926     using namespace cv;  using namespace std;     void RGB2HSV(double red, double green, double blue, double& hue, double& saturation, double& intensity)  {  	   	double r, g, b;  	double h, s, i;     	double sum;  	double minRGB, maxRGB;  	double theta;     	r = red / 255.0;  	g = green / 255.0;  	b = blue / 255.0;     	minRGB = ((rb) ? (maxRGB) : (b);     	sum = r + g + b;  	i = sum / 3.0;     	if (i<0.001 || maxRGB - minRGB<0.001)  	{  		h = 0.0;  		s = 0.0;  	}  	else  	{  		s = 1.0 - 3.0*minRGB / sum;  		theta = sqrt((r - g)*(r - g) + (r - b)*(g - b));  		theta = acos((r - g + r - b)*0.5 / theta);  		if (b <= g)  			h = theta;  		else  			h = 2 * PI - theta;  		if (s <= 0.01)  			h = 0;  	}     	hue = (int)(h * 180 / PI);  	saturation = (int)(s * 100);  	intensity = (int)(i * 100);  }     Mat picture_red(Mat input)  {  	  	Mat frame;  	Mat srcImg = input;  	frame = srcImg;  	waitKey(1);  	int width = srcImg.cols;  	int height = srcImg.rows;     	int x, y;  	double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;  	Mat vec_rgb = Mat::zeros(srcImg.size(), CV_8UC1);  	for (x = 0; x < height; x++)  	{  		for (y = 0; y < width; y++)  		{  			B = srcImg.at(x, y)[0];  			G = srcImg.at(x, y)[1];  			R = srcImg.at(x, y)[2];  			RGB2HSV(R, G, B, H, S, V);  			//紅色範圍,範圍參考的網上。可以自己調  			if ((H >= 312 && H = 17 && S 18 && V < 100))  				vec_rgb.at(x, y) = 255;  			/*cout << H << "," << S << "," << V << endl;*/  		}  	}  	/*imshow("hsv", vec_rgb);*/  	return vec_rgb;  	     }     void O_x1y1(Mat in, double *x1, double *y1, double *x2, double *y2)     {  	Mat matSrc = in;  	/*Mat matSrc = imread("qwer9.png", 0);*/     	GaussianBlur(matSrc, matSrc, Size(5, 5), 0);//高斯濾波,除噪點     	vector contours;//contours的型別,雙重的vector     	vectorhierarchy;//Vec4i是指每一個vector元素中有四個int型資料。     	//閾值     	threshold(matSrc, matSrc, 100, 255, THRESH_BINARY);//影象二值化     	//尋找輪廓,這裡注意,findContours的輸入引數要求是二值影象,二值影象的來源大致有兩種,第一種用threshold,第二種用canny     	findContours(matSrc.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));     	/// 計算矩     	vectormu(contours.size());     	for (int i = 0; i < contours.size(); i++)     	{  		mu[i] = moments(contours[i], false);  	}     	/// 計算矩中心:     	vectormc(contours.size());     	for (int i = 0; i < contours.size(); i++)     	{  		mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);  	}     	/// 繪製輪廓     	Mat drawing = Mat::zeros(matSrc.size(), CV_8UC1);     	for (int i = 0; i < contours.size(); i++)     	{  		Scalar color = Scalar(255);     		//drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());//繪製輪廓函式     		circle(drawing, mc[i], 4, color, -1, 8, 0);  		  	}  	*x1 = mc[0].x;  	*y1 = mc[0].y;  	*x2 = mc[contours.size()-1].x;  	*y2 = mc[contours.size() - 1].y;  	  	imshow("outImage", drawing);  }     int main()  {  	  	double xx1, yy1, xx2, yy2;  	double x1, y1, x2, y2;     	Mat matSrc = imread("qwer4.png");     	Mat middle = picture_red(matSrc);  	O_x1y1(middle, &xx1, &yy1, &xx2, &yy2);  	x1 = xx1;  	y1 = yy1;  	x2 = xx2;  	y2 = yy2;     	imshow("原圖", matSrc);  	imshow("red", picture_red(matSrc));     	cout << "紅點:" << x1 << ", " << y1 << "; " << "紅點1:" << x2 << ", " << y2 << endl;  	waitKey();     	return 0;  }

 

如有不足,望指點!

補充知識:opencv 識別網球 ,或者綠色的小球 輸出重心座標

我就廢話不多說了,大家還是直接看程式碼吧!

  void image_process(IplImage *image)   {   int iLowH =26;    int iHighH = 69;    int iLowS = 42;     int iHighS = 206;     int iLowV = 0;    int iHighV = 198;    CvMemStorage* storage2 = cvCreateMemStorage();    CvSeq* contour3 = NULL;    CvMoments moments;     CvMat *region;     CvPoint pt1,pt2;    double m00 = 0, m10, m01, mu20, mu11, mu02, inv_m00;     double a, b, c;     int xc, yc;        CvMemStorage* storage = cvCreateMemStorage();   	CvSeq * circles=NULL;       // Circle cir[6];    CvPoint P0;    CvPoint CenterPoint;    // cvNamedWindow("win1");   	//cvShowImage("win1",image);  	//cvNamedWindow("image",CV_WINDOW_AUTOSIZE);//用於顯示影象的視窗  	//cvNamedWindow("hsv",CV_WINDOW_AUTOSIZE);	  	//cvNamedWindow("saturation",CV_WINDOW_AUTOSIZE);  	//cvNamedWindow("value",CV_WINDOW_AUTOSIZE);  	//cvNamedWindow("pImg8u",1);  	IplImage *hsv=cvCreateImage(cvGetSize(image),8,3);//給hsv色系的影象申請空間  	IplImage *hue=cvCreateImage(cvGetSize(image),8,1); //色調  	IplImage *saturation=cvCreateImage(cvGetSize(image),8,1);//飽和度  	IplImage *value=cvCreateImage(cvGetSize(image),8,1);//亮度  	IplImage *imgThresholded=cvCreateImage(cvGetSize(hue),8,1);   	cvNamedWindow("yuan",1);  	cvCvtColor(image,hsv,CV_BGR2HSV);//將RGB色系轉為HSV色系  	cvShowImage("yuan",image);  	//cvShowImage("hsv",hsv);  	cvSplit(hsv, hue, 0, 0, 0 );//分離三個通道  	cvSplit(hsv, 0, saturation, 0, 0 );  	cvSplit(hsv, 0, 0, value, 0 );  	int value_1=0;  	   	cvInRangeS(  	  hsv,   	  cvScalar(iLowH, iLowS, iLowV),   	  cvScalar(iHighH, iHighS, iHighV),  	  imgThresholded  	  );   	 cvNamedWindow("imgThresholded",1);  	 cvShowImage("imgThresholded",imgThresholded);     	 IplImage*pContourImg= cvCreateImage( cvGetSize(image), 8, 1 );   	cvCopy(imgThresholded,pContourImg);  	 cvNamedWindow("pContourImg",1);  	 cvShowImage("pContourImg",pContourImg);  	 IplImage* dst = cvCreateImage( cvGetSize(image), 8, 3 );   	CvMemStorage* storage3 = cvCreateMemStorage(0);   	CvSeq* contour = 0;   	// 提取輪廓     int contour_num = cvFindContours(pContourImg, storage3, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);     cvZero(dst);    // 清空陣列     CvSeq *_contour = contour;      double maxarea = 100;     double minarea = 10;     int m = 0;     for( ; contour != 0; contour = contour->h_next )      {           double tmparea = fabs(cvContourArea(contour));       if(tmparea < minarea)         {          cvSeqRemove(contour, 0); // 刪除面積小於設定值的輪廓         continue;       }        CvRect aRect = cvBoundingRect( contour, 0 );        if ((aRect.width/aRect.height)maxarea)        {          maxarea = tmparea;       }        m++;       // 建立一個色彩值     //  CvScalar color = CV_RGB( 0, 0, 255 );         /*  max_level 繪製輪廓的最大等級。如果等級為0,繪製單獨的輪廓。如果為1,繪製輪廓及在其後的相同的級別下輪廓       如果值為2,所有的輪廓。如果等級為2,繪製所有同級輪廓及所有低一級輪廓,諸此種種       如果值為負數,函式不繪製同級輪廓,但會升序繪製直到級別為abs(max_level)-1的子輪廓 */      //  cvDrawContours(dst, contour, color, color, 0, 1, 8);  //繪製外部和內部的輪廓     }      contour = _contour;     int count = 0; double tmparea=0;    for(; contour != 0; contour = contour->h_next)     {        count++;        tmparea = fabs(cvContourArea(contour));       if (tmparea >= maxarea)        {          CvScalar color = CV_RGB( 0, 255, 0);         cvDrawContours(dst, contour, color, color, -1, 1, 8);   			cout<<"222"<<endl;  			cout<<"面積為"<<tmparea<<endl;  			cout<<endl;  			CvRect aRect = cvBoundingRect( contour, 0 );   			//找重心  			{  				CvPoint2D32f center = cvPoint2D32f(0, 0);  				int countOfPoint = 0;  				for(int i = aRect.x; i < aRect.x + aRect.width; ++i){  					for(int j = aRect.y; j < aRect.y + aRect.height; ++j){  						if(*(image->imageData + image->widthStep * j + i) != 0){  							center.x += i;  							center.y += j;  							countOfPoint++;  						}  					}  				}     				center.x /= countOfPoint;  				center.y /= countOfPoint;  				cout<<"重心座標為x:"<<center.x<<endl;       		cout<<"重心座標為y:"<<center.yheight/15,  //該引數是讓演演算法能明顯區分的兩個不同圓之間的最小距離  		//80,  //用於Canny的邊緣閥值上限,下限被置為上限的一半  		//65,  //累加器的閥值  		//25,   //最小圓半徑   		//50   //最大圓半徑  		//);   }     	cvShowImage( "contour", dst );  	}

  


[月球人 ] 使用opencv識別影象紅色區域,並輸出紅色區域中心點座標已經有298次圍觀

http://coctec.com/docs/program/show-post-238224.html