《实用OpenCV》<五> 图像滤波(4)

本文介绍OpenCV中的goodFeaturesToTrack()函数用于拐角检测,并通过实例展示了如何使用circle()函数在图像中绘制拐角位置。此外,文章还探讨了图像腐蚀、膨胀、开启和关闭等形态学操作,以及如何使用这些操作来移除图像噪声。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拐角

       OpenCV的goodFeaturesToTrack()函数实现了一个稳健的拐角检测器。使用了Shi和Tomasi提出的兴趣点检测算法。更多关于该函数的内部原理可以从此文档页面找到http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=goodfeaturestotrack#goodfeaturestotrack.

      该函数接受如下输入:

         •   灰度图像

         •   一个储存拐角坐标Point2d的标准向量

         •   返回的拐角最大数量。如果算法检测到多于此数量的拐角,则仅仅返回最合适的拐角。

         •   质量等级:认可拐角的质量最小值。拐角的质量是指图像在某一像素的亮度梯度矩阵的最小特征值或者(如果使用的是Harris拐角检测器)图像在该像素对Harris函数的反馈值。可以查阅文档看看cornerHarris()和cornerMinEigenVal()的详细信息。

         •   返回的两拐角位置间的最小欧式距离。

         •   一个标签来指示是否使用Harris拐角检测还是最小特征值检测(默认是最小特征值)。

         •   如果使用Harris拐角检测,此参数则为了调整Harris检测器(查阅cornerHarris()的文档来了解此参数的使用)

例5-6 检测图像拐角

// Program to detect corners in an image
// Author: Samarth Manoj Brahmbhatt, University of Pennyslvania
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdlib.h>
using namespace std;
using namespace cv;
Mat image, image_gray;
int max_corners = 20;
void on_slider(int, void *) {
   if(image_gray.empty()) return;
      max_corners = max(1, max_corners);
      setTrackbarPos("Max no. of corners", "Corners", max_corners);
      float quality = 0.01;
      int min_distance = 10;
      vector<Point2d> corners;
      goodFeaturesToTrack(image_gray, corners, max_corners, quality, min_distance);
      // Draw the corners as little circles
      Mat image_corners = image.clone();
      for(int i = 0; i < corners.size(); i++) {
         circle(image_corners, corners[i], 4, CV_RGB(255, 0, 0), -1);
      }
    imshow("Corners", image_corners);
}
int main() {
   image = imread("building.jpg");
   cvtColor(image, image_gray, CV_RGB2GRAY);
   namedWindow("Corners");
   on_slider(0, 0);
   createTrackbar("Max. no. of corners", "Corners", &max_corners, 250, on_slider);
   while(char(waitKey(1)) != 'q') {}
     return 0;
}

这个程序里,我们通过滑块来改变可返回的拐角最大数量,观察如何使用circle()函数来在拐角位置绘制红色小填充圆形。程序输出显示如图5-11

图 5-11 不同max_corners值下的拐角


图像腐蚀和膨胀  

        腐蚀和膨胀是图像的两个基本形态学操作。顾名思义,形态学操作是基于图像的形式和结构的。  腐蚀是通过在一个图像上遍历使用一个矩形核。反馈值是核元素和核所在像素的叉积最大值。因为所有核元素都一样,所以应用此核代表替换每个像素值为该像素周围矩形区域的最小值。你可以想象这样会引起图像里黑色区域会“侵蚀”到白色区域(因为白色像素值比黑色的要高)。膨胀也一样,区别是反馈值是叉积的最大值。会引起白色区域侵蚀到黑色区域。核的大小会决定腐蚀或膨胀的量。

通过形态学的图像开启和关闭移除噪声      

         开启是通过先腐蚀图像后接着膨胀。这会有一个移除图像上微小的白色区域的效果。关闭是先膨胀再腐蚀,会有相反的效果。这两个操作经常用来移除图像里的噪声。开启移除微小白色像素而关闭移除微小黑色“洞口”。OpenCV的morphologyEX()可以用来高级的形态学操作像图像上开启和关闭。例5-8 对象检测代码

// Program to display a video from attached default camera device and detect colored blobs using simple
// R G and B thresholding
// Author: Samarth Manoj Brahmbhatt, University of Pennsylvania
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
Mat frame, frame_thresholded;
int rgb_slider = 0, low_slider = 30, high_slider = 100;
int low_r = 30, low_g = 30, low_b = 30, high_r = 100, high_g = 100, high_b = 100;
void on_rgb_trackbar(int, void *) {
  switch(rgb_slider) {
   case 0:
      setTrackbarPos("Low threshold", "Segmentation", low_r);
      setTrackbarPos("High threshold", "Segmentation", high_r);
   break;
   case 1:
      setTrackbarPos("Low threshold", "Segmentation", low_g);
      setTrackbarPos("High threshold", "Segmentation", high_g);
   break;
   case 2:
      setTrackbarPos("Low threshold", "Segmentation", low_b);
      setTrackbarPos("High threshold", "Segmentation", high_b);
   break;
  }
}
void on_low_thresh_trackbar(int, void *) {
  switch(rgb_slider) {
   case 0:
      low_r = min(high_slider - 1, low_slider);
      setTrackbarPos("Low threshold", "Segmentation", low_r);
   break;
   case 1:
      low_g = min(high_slider - 1, low_slider);
      setTrackbarPos("Low threshold", "Segmentation", low_g);
   break;
   case 2:
      low_b = min(high_slider - 1, low_slider);
      setTrackbarPos("Low threshold", "Segmentation", low_b);
   break;
  }
}
void on_high_thresh_trackbar(int, void *) {
  switch(rgb_slider) {
   case 0:
      high_r = max(low_slider + 1, high_slider);
      setTrackbarPos("High threshold", "Segmentation", high_r);
   break;
   case 1:
      high_g = max(low_slider + 1, high_slider);
      setTrackbarPos("High threshold", "Segmentation", high_g);
   break;
   case 2:
      high_b = max(low_slider + 1, high_slider);
      setTrackbarPos("High threshold", "Segmentation", high_b);
   break;
  }
}

int main()
{
   // Create a VideoCapture object to read from video file
   // 0 is the ID of the built-in laptop camera, change if you want to use other camera
   VideoCapture cap(0);
   //check if the file was opened properly
   if(!cap.isOpened())
   {
      cout << "Capture could not be opened succesfully" << endl;
      return -1;
    }
   namedWindow("Video");
   namedWindow("Segmentation");
   createTrackbar("0. R\n1. G\n2.B", "Segmentation", &rgb_slider, 2, on_rgb_trackbar);
   createTrackbar("Low threshold", "Segmentation", &low_slider, 255, on_low_thresh_trackbar);
   createTrackbar("High threshold", "Segmentation", &high_slider, 255, on_high_thresh_trackbar);
   while(char(waitKey(1)) != 'q' && cap.isOpened())
   {
      cap >> frame;
      // Check if the video is over
      if(frame.empty())
      {
        cout << "Video over" << endl;
        break;
   }
   inRange(frame, Scalar(low_b, low_g, low_r), Scalar(high_b, high_g, high_r),
   frame_thresholded);
   Mat str_el = getStructuringElement(MORPH_RECT, Size(3, 3));
   morphologyEx(frame_thresholded, frame_thresholded, MORPH_OPEN, str_el);
   morphologyEx(frame_thresholded, frame_thresholded, MORPH_CLOSE, str_el);
   imshow("Video", frame);
   imshow("Segmentation", frame_thresholded);
}
return 0;


图 5-13 通过开启和关闭移除小块噪声像素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值