使用opencv识别图像红色区域,并输出红色区域中心点坐标

适用小白,大佬勿喷

个人配置:vs2013 ; opencv 3.0 ;

直接上效果图

注意:右下角的水印把中心点挡住了,要仔细看才能看到

下面是代码:

#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);

//红色范围,范围参考的网上。可以自己调

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);//高斯滤波,除噪点

vector<vector<Point> > contours;//contours的类型,双重的vector

vector<Vec4i> hierarchy;//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));

/// 计算矩

vector<Moments> mu(contours.size());

for (int i = 0; i < contours.size(); i++)

{

mu[i] = moments(contours[i], false);

}

/// 计算矩中心:

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());//绘制轮廓函数

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)<1)

{

cvSeqRemove(contour, 0); //删除宽高比例小于设定值的轮廓

continue;

}

if(tmparea > 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.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, //最小分辨率,应当>=1

//pImg8u->height/15, //该参数是让算法能明显区分的两个不同圆之间的最小距离

//80, //用于Canny的边缘阀值上限,下限被置为上限的一半

//65, //累加器的阀值

//25, //最小圆半径

//50 //最大圆半径

//);

}

cvShowImage( "contour", dst );

}

以上这篇使用opencv识别图像红色区域,并输出红色区域中心点坐标就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

以上是 使用opencv识别图像红色区域,并输出红色区域中心点坐标 的全部内容, 来源链接: utcz.com/z/352837.html

回到顶部