识别图像红色区域,并输出红色区域中心点坐标
并输出红色区域中心点坐标
使用使用opencv识别图像红色区域
主要介绍了使用opencv识别图像红色区域,并输出红色区域中心点坐标,具有很好的参考价值,希望对大家有所
帮助。一起跟随小编过来看看吧
适用小白,大佬勿喷
个人配置: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 = ((rg) ? (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
(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 <= 360) && (S >= 17 && S <= 100) && (V>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
 
 vector 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 mu(contours.size());
 
 for (int i = 0; i < contours.size(); i++)
 
 {
  mu[i] = moments(contours[i], false);
 }
 
 /// 计算矩中心:
 
 vector 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"<imageData + image->widthStep * j + i) != 0){
       center.x += i;
       center.y += j;
       countOfPoint++;
      }
     }
    }
 
    center.x /= countOfPoint;
    center.y /= countOfPoint;
    cout<<"重心坐标为x:"<=1
  //pImg8u->height/15,  //该参数是让算法能明显区分的两个不同圆之间的最小距离
  //80,  //用于Canny的边缘阀值上限,下限被置为上限的一半
  //65,  //累加器的阀值
  //25,   //最小圆半径 
  //50   //最大圆半径
  //);
 }
 
 cvShowImage( "contour", dst );
 }
以上这篇使用opencv识别图像红色区域,并输出红色区域中心点坐标就是小编分享给大家的全部内容了,希望能给大家一个参
考,也希望大家多多支持我们。