Advertisement

OpenCV学习笔记16 OpenCV图像处理模块ImgProc Module. Image Processing(九)

阅读量:

3.24 图像矩 - Image Moments

使用 moments 函数计算图像所有的矩(最高到3阶)。

使用 contourArea 函数计算轮廓面积。

使用 arcLength 函数计算轮廓或曲线长度。

复制代码
 /** @thresh_callback 函数 */

    
 void thresh_callback(int, void* )
    
 {
    
   Mat canny_output;
    
   vector<vector<Point> > contours;
    
   vector<Vec4i> hierarchy;
    
  
    
   /// 使用Canndy检测边缘
    
   Canny( src_gray, canny_output, thresh, thresh*2, 3 );
    
   /// 找到轮廓
    
   findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_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( canny_output.size(), CV_8UC3 );
    
   for( int i = 0; i< contours.size(); i++ )
    
      {
    
    Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
    
    drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
    
    circle( drawing, mc[i], 4, color, -1, 8, 0 );
    
      }
    
  
    
   /// 显示到窗口中
    
   namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
    
   imshow( "Contours", drawing );
    
  
    
   /// 通过m00计算轮廓面积并且和OpenCV函数比较
    
   printf("\t Info: Area and Contour Length \n");
    
   for( int i = 0; i< contours.size(); i++ )
    
      {
    
    printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
    
    Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
    
    drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
    
    circle( drawing, mc[i], 4, color, -1, 8, 0 );
    
      }
    
 }

moments 函数参数说明:

contour[i]_ 是一种用于表示图形形状的数据结构:它存储了栅格图像(单色、8位或浮点型 2维数组)或二维点(Point或Point2f类型)的数组(大小为1×N 或 N×1)。
false 是一个二值图像标志位变量,在其值为true时表示该图像的所有非零像素被标记为1。

contourArea 函数参数说明:

contours[i] :2维点数组,存储在 vector 或 Mat 中。

arcLength 函数参数说明:

contours[i] :2维点数组,存储在 vector 或 Mat 中。

true :曲线是否封闭的标志。

3.25 点多边形测试

使用 pointPolygonTest 函数进行点是否在轮廓中的测试。

复制代码
   /// 创建一个图形  
    
   const int r = 100;
    
   Mat src = Mat::zeros( Size( 4*r, 4*r ), CV_8UC1 );
    
  
    
   /// 绘制一系列点创建一个轮廓:
    
   vector<Point2f> vert(6);
    
  
    
   vert[0] = Point( 1.5*r, 1.34*r );
    
   vert[1] = Point( 1*r, 2*r );
    
   vert[2] = Point( 1.5*r, 2.866*r );
    
   vert[3] = Point( 2.5*r, 2.866*r );
    
   vert[4] = Point( 3*r, 2*r );
    
   vert[5] = Point( 2.5*r, 1.34*r );
    
  
    
   /// 在src内部绘制
    
   for( int j = 0; j < 6; j++ )
    
      { line( src, vert[j],  vert[(j+1)%6], Scalar( 255 ), 3, 8 ); }
    
  
    
   /// 得到轮廓
    
   vector<vector<Point> > contours; vector<Vec4i> hierarchy;
    
   Mat src_copy = src.clone();
    
  
    
   findContours( src_copy, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
    
  
    
   /// 计算到轮廓的距离
    
   Mat raw_dist( src.size(), CV_32FC1 );
    
  
    
   for( int j = 0; j < src.rows; j++ )
    
      { for( int i = 0; i < src.cols; i++ )
    
       { raw_dist.at<float>(j,i) = pointPolygonTest( contours[0], Point2f(i,j), true ); }
    
      }
    
  
    
   double minVal; double maxVal;
    
   minMaxLoc( raw_dist, &minVal, &maxVal, 0, 0, Mat() );
    
   minVal = abs(minVal); maxVal = abs(maxVal);
    
  
    
   /// 图形化的显示距离
    
   Mat drawing = Mat::zeros( src.size(), CV_8UC3 );
    
  
    
   for( int j = 0; j < src.rows; j++ )
    
      { for( int i = 0; i < src.cols; i++ )
    
       {
    
         if( raw_dist.at<float>(j,i) < 0 )
    
           { drawing.at<Vec3b>(j,i)[0] = 255 - (int) abs(raw_dist.at<float>(j,i))*255/minVal; }
    
         else if( raw_dist.at<float>(j,i) > 0 )
    
           { drawing.at<Vec3b>(j,i)[2] = 255 - (int) raw_dist.at<float>(j,i)*255/maxVal; }
    
         else
    
           { drawing.at<Vec3b>(j,i)[0] = 255; drawing.at<Vec3b>(j,i)[1] = 255; drawing.at<Vec3b>(j,i)[2] = 255; }
    
       }
    
      }

pointPolygonTest 函数参数说明:

contours[0] :输入轮廓。

Point2f(i,j) :测试点。

true :标记位用于距离测量。当设置为true时,则函数计算并返回该点至轮廓的有符号最近距离(正值表示外部区域、负值表示内部区域)。当设置为false时,则仅判断该点是否位于轮廓之内。

全部评论 (0)

还没有任何评论哟~