OpenCV 之 边缘检测

2  基于边缘

  前一篇 <OpenCV 之 边缘检测> 中,介绍了三种常用的边缘检测算子: Sobel, Laplace 和 Canny 算子。

  实际上,边缘检测的结果是一个个的点,并不能作为图像分割的结果,必须采用进一步的处理,将边缘点沿着图像的边界连接起来,形成边缘链。

2.1  轮廓函数

  OpenCV 中,可在图像的边缘检测之后,使用 findContours 寻找到轮廓,该函数参数如下:

  image 一般为二值化图像,可由 compare, inRange, threshold , adaptiveThreshold, Canny 等函数来获得;

  hierarchy 为可选的参数,如果不选择该参数,则可得到 findContours 函数的第二种形式;


// 形式一
void findContours ( 
    InputOutputArray      image,       // 输入图像
    OutputArrayOfArrays   contours,    // 检测到的轮廓
    OutputArray           hierarchy,   // 可选的输出向量
    int       mode,            // 轮廓获取模式 (RETR_EXTERNAL, RETR_LIST, RETR_CCOMP,RETR_TREE, RETR_FLOODFILL)
    int       method,          // 轮廓近似算法 (CHAIN_APPROX_NONE, CHAIN_APPROX_SIMPLE, CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS)
    Point     offset = Point() // 轮廓偏移量
)
// 形式二
void findContours ( 
  InputOutputArray   image, 
  OutputArrayOfArrays contours,   int    mode,   int    method,   Point   offset = Point() )

  drawContours 函数参数如下:


void drawContours ( 
    InputOutputArray     image,         // 目标图像
    InputArrayOfArrays   contours,      // 所有的输入轮廓
    int               contourIdx,      //
    const Scalar &     color,           //  轮廓颜色
    int          thickness = 1,         //  轮廓线厚度
    int          lineType = LINE_8,     //
    InputArray   hierarchy = noArray(), //
    int          maxLevel = INT_MAX,    //
    Point        offset = Point()       //     
)     

2.2  例程

  代码摘自 OpenCV 例程,略有修改


#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

using namespace cv;
using namespace std;

Mat src,src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

void thresh_callback(int, void* );

int main( int, char** argv )
{
  // 读图
  src = imread("Pillnitz.jpg", IMREAD_COLOR); 
  if (src.empty())
      return -1;

  // 转化为灰度图
  cvtColor(src, src_gray, COLOR_BGR2GRAY );
  blur(src_gray, src_gray, Size(3,3) );
  
  // 显示
  namedWindow("Source", WINDOW_AUTOSIZE );
  imshow( "Source", src );

  // 滑动条
  createTrackbar("Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );

  // 回调函数
  thresh_callback( 0, 0 );

  waitKey(0);
}

// 回调函数
void thresh_callback(int, void* )
{
  Mat canny_output;
  vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;
  
  // canny 边缘检测
  Canny(src_gray, canny_output, thresh, thresh*2, 3);
  
  // 寻找轮廓
  findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );

  Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3);
  
  // 画出轮廓
  for( size_t i = 0; i< contours.size(); i++ ) {
      Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
      drawContours( drawing, contours, (int)i, color, 2, 8, hierarchy, 0, Point() );
  }

  namedWindow( "Contours", WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );
}

猜你喜欢

转载自blog.csdn.net/max2009verygood/article/details/79176123