使用opencv識(shí)別圖像紅色區(qū)域,并輸出紅色區(qū)域中心點(diǎn)坐標(biāo)
適用小白,大佬勿噴
個(gè)人配置:vs2013 ; opencv 3.0 ;
直接上效果圖
注意:右下角的水印把中心點(diǎn)擋住了,要仔細(xì)看才能看到
下面是代碼:
#include <iostream> #include<opencv2\opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #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 = ((r<g) ? (r) : (g)); minRGB = (minRGB<b) ? (minRGB) : (b); maxRGB = ((r>g) ? (r) : (g)); maxRGB = (maxRGB>b) ? (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<Vec3b>(x, y)[0]; G = srcImg.at<Vec3b>(x, y)[1]; R = srcImg.at<Vec3b>(x, y)[2]; RGB2HSV(R, G, B, H, S, V); //紅色范圍,范圍參考的網(wǎng)上??梢宰约赫{(diào) if ((H >= 312 && H <= 360) && (S >= 17 && S <= 100) && (V>18 && V < 100)) vec_rgb.at<uchar>(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);//高斯濾波,除噪點(diǎn) vector<vector<Point> > contours;//contours的類型,雙重的vector vector<Vec4i> hierarchy;//Vec4i是指每一個(gè)vector元素中有四個(gè)int型數(shù)據(jù)。 //閾值 threshold(matSrc, matSrc, 100, 255, THRESH_BINARY);//圖像二值化 //尋找輪廓,這里注意,findContours的輸入?yún)?shù)要求是二值圖像,二值圖像的來源大致有兩種,第一種用threshold,第二種用canny findContours(matSrc.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); /// 計(jì)算矩 vector<Moments> mu(contours.size()); for (int i = 0; i < contours.size(); i++) { mu[i] = moments(contours[i], false); } /// 計(jì)算矩中心: vector<Point2f> mc(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());//繪制輪廓函數(shù) 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 << "紅點(diǎn):" << x1 << ", " << y1 << "; " << "紅點(diǎn)1:" << x2 << ", " << y2 << endl; waitKey(); return 0; }
如有不足,望指點(diǎn)!
補(bǔ)充知識(shí):opencv 識(shí)別網(wǎng)球 ,或者綠色的小球 輸出重心坐標(biāo)
我就廢話不多說了,大家還是直接看代碼吧!
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色系的圖像申請(qǐng)空間 IplImage *hue=cvCreateImage(cvGetSize(image),8,1); //色調(diào) 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色系轉(zhuǎn)為HSV色系 cvShowImage("yuan",image); //cvShowImage("hsv",hsv); cvSplit(hsv, hue, 0, 0, 0 );//分離三個(gè)通道 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); // 清空數(shù)組 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); // 刪除面積小于設(shè)定值的輪廓 continue; } CvRect aRect = cvBoundingRect( contour, 0 ); if ((aRect.width/aRect.height)<1) { cvSeqRemove(contour, 0); //刪除寬高比例小于設(shè)定值的輪廓 continue; } if(tmparea > maxarea) { maxarea = tmparea; } m++; // 創(chuàng)建一個(gè)色彩值 // CvScalar color = CV_RGB( 0, 0, 255 ); /* max_level 繪制輪廓的最大等級(jí)。如果等級(jí)為0,繪制單獨(dú)的輪廓。如果為1,繪制輪廓及在其后的相同的級(jí)別下輪廓 如果值為2,所有的輪廓。如果等級(jí)為2,繪制所有同級(jí)輪廓及所有低一級(jí)輪廓,諸此種種 如果值為負(fù)數(shù),函數(shù)不繪制同級(jí)輪廓,但會(huì)升序繪制直到級(jí)別為abs(max_level)-1的子輪廓 */ // cvDrawContours(dst, contour, color, color, 0, 1, 8); //繪制外部和內(nèi)部的輪廓 } 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<<"重心坐標(biāo)為x:"<<center.x<<endl; cout<<"重心坐標(biāo)為y:"<<center.y<<endl; cvCircle(dst, cvPoint(center.x, center.y), 5, cvScalar(0, 255), 2); } } // //Threshold the image // cvErode(imgThresholded,imgThresholded); // cvErode(imgThresholded,imgThresholded); //cvErode(imgThresholded,imgThresholded); //cvErode(imgThresholded,imgThresholded); //IplImage* pImg8u=cvCloneImage(imgThresholded); //cvCanny(pImg8u, pImg8u,40, 50, 5); //cvShowImage("pImg8u",pImg8u); //circles=cvHoughCircles(pImg8u,storage,CV_HOUGH_GRADIENT, //2, //最小分辨率,應(yīng)當(dāng)>=1 //pImg8u->height/15, //該參數(shù)是讓算法能明顯區(qū)分的兩個(gè)不同圓之間的最小距離 //80, //用于Canny的邊緣閥值上限,下限被置為上限的一半 //65, //累加器的閥值 //25, //最小圓半徑 //50 //最大圓半徑 //); } cvShowImage( "contour", dst ); }
以上這篇使用opencv識(shí)別圖像紅色區(qū)域,并輸出紅色區(qū)域中心點(diǎn)坐標(biāo)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python標(biāo)準(zhǔn)庫06之子進(jìn)程 (subprocess包) 詳解
本篇文章主要介紹了Python標(biāo)準(zhǔn)庫06之子進(jìn)程 (subprocess包) 詳解,具有一定的參考價(jià)值,有興趣的同學(xué)可以了解一下。2016-12-12python開發(fā)準(zhǔn)備工作之配置虛擬環(huán)境(非常重要)
這篇文章主要介紹了python開發(fā)準(zhǔn)備工作之配置虛擬環(huán)境(非常重要),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02Python 尋找局部最高點(diǎn)的實(shí)現(xiàn)
今天小編就為大家分享一篇Python 尋找局部最高點(diǎn)的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12OpenCV圖像識(shí)別之姿態(tài)估計(jì)Pose?Estimation學(xué)習(xí)
這篇文章主要為大家介紹了OpenCV圖像識(shí)別之姿態(tài)估計(jì)Pose?Estimation學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Python?matplotlib調(diào)整坐標(biāo)軸位置、標(biāo)簽位置和標(biāo)簽方向以及X軸刻度標(biāo)簽位置
我們?cè)谟胢atplotlib繪制圖的時(shí)候總是有各種需求,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib調(diào)整坐標(biāo)軸位置、標(biāo)簽位置和標(biāo)簽方向以及X軸刻度標(biāo)簽位置的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04Python實(shí)現(xiàn)短網(wǎng)址ShortUrl的Hash運(yùn)算實(shí)例講解
這篇文章主要介紹了Python實(shí)現(xiàn)短網(wǎng)址ShortUrl的Hash運(yùn)算,較為詳細(xì)的分析了Python短網(wǎng)址運(yùn)算的算法原理與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-08-08