使用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ù)要求是二值圖像,二值圖像的來(lái)源大致有兩種,第一種用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)
我就廢話不多說(shuō)了,大家還是直接看代碼吧!
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如何操作docker redis過(guò)程解析
這篇文章主要介紹了Python如何操作docker redis過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
pycharm運(yùn)行和調(diào)試不顯示結(jié)果的解決方法
今天小編就為大家分享一篇pycharm運(yùn)行和調(diào)試不顯示結(jié)果的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
說(shuō)說(shuō)如何遍歷Python列表的方法示例
這篇文章主要介紹了如何遍歷Python列表的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
Python爬蟲(chóng)使用bs4方法實(shí)現(xiàn)數(shù)據(jù)解析
這篇文章主要介紹了Python爬蟲(chóng)使用bs4方法實(shí)現(xiàn)數(shù)據(jù)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
一個(gè)超級(jí)簡(jiǎn)單的python web程序
這篇文章主要介紹了一個(gè)超級(jí)簡(jiǎn)單的python web程序,需要的朋友可以參考下2014-09-09
python報(bào)錯(cuò): ''list'' object has no attribute ''shape''的解決
這篇文章主要介紹了python報(bào)錯(cuò): 'list' object has no attribute 'shape'的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
Pandas數(shù)據(jù)分析之pandas數(shù)據(jù)透視表和交叉表
這篇文章主要介紹了Pandas數(shù)據(jù)分析之pandas數(shù)據(jù)透視表和交叉表,pandas對(duì)數(shù)據(jù)框也可以像excel一樣進(jìn)行數(shù)據(jù)透視表整合之類的操作。主要是針對(duì)分類數(shù)據(jù)進(jìn)行操作,還可以計(jì)算數(shù)值型數(shù)據(jù),去滿足復(fù)雜的分類數(shù)據(jù)整理的邏輯2022-08-08
通過(guò)celery異步處理一個(gè)查詢?nèi)蝿?wù)的完整代碼
今天小編就為大家分享一篇通過(guò)celery異步處理一個(gè)查詢?nèi)蝿?wù)的完整代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11

