【问题标题】:Detect rectangular shapes from camera从相机检测矩形
【发布时间】:2017-03-12 09:09:22
【问题描述】:

我需要一些关于我正在进行的项目的反馈。本质上,我需要能够从来自相机的视频流中跟踪矩形形状。我正在使用 C++ 的 OpenCV 库来执行此操作。 首先,我应用了颜色检测(我一次只需要跟踪一种颜色)。之后我应用了 Canny 边缘检测以获得过滤后图像的轮廓。此时我应该能够确定是否存在矩形,它在(x,y)平面中的位置(知道它的中心或顶点的位置毕竟不会有那么大的差异)和它的方向关于这样的飞机。 所有这些都应该“实时”完成,因为信号来自相机,我需要能够跟踪流中显示的形状的这些特征。

这是通过 Canny 边缘检测算法检测到的颜色选择(左)及其轮廓后输入的阈值版本的图片

这是任何人需要的代码:

#include <sstream>
#include <string>
#include <iostream>
#include <opencv/highgui.h>
#include <opencv/cv.h>

#define HIGH_CANNY_THRESH  255
#define CANNY_KERNEL_SIZE  3
#define       FRAME_WIDTH  640
#define      FRAME_HEIGHT  480

#define    DISPLAY_IMAGES  true

using namespace std;
using namespace cv;

void createTrackbarsForHSVSel();
void morphOps(Mat &thresh);

int LOW_H  = 0;
int HIGH_H = 255;
int LOW_S  = 0;
int HIGH_S = 255;
int LOW_V  = 0;
int HIGH_V = 255;

int LOW_THRESHOLD  = 0;
int HIGH_THRESHOLD = 100;

int     CORNER_THRESH = 200;
int MAX_CORNER_THRESH = 255;

int main(int argc, char* argv[])
{

   Mat src, hsvSpace, threshold, edges;

   vector<vector<Point> > contours;   // Vectors for the contours storage
   vector<Vec4i> hierarchy;

   createTrackbarsForHSVSel();   // create trackbars for the HSV palette
   createTrackbar("Min Threshold", "Trackbars", &LOW_THRESHOLD , HIGH_THRESHOLD);
   createTrackbar("Max Threshold", "Trackbars", &HIGH_THRESHOLD, HIGH_THRESHOLD);

   VideoCapture capture;
   capture.open(0);

   printf("Starting to capture from camera0:\nisOpened = %d\n", capture.isOpened());

   capture.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH);
   capture.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT);

   while(1)   // loop exectues as long as the user doesn't press ESC, q or Q
   {
      capture.read(src);   // read from camera
      cvtColor(src, hsvSpace, CV_BGR2HSV);   // RGB to HSV color space transformation
      // create a binary such that 1s are between Scalar(min_, min_, min_) and Scalar(max_, max_, max_)
      inRange(hsvSpace, Scalar(LOW_H, LOW_S, LOW_V), Scalar(HIGH_H, HIGH_S, HIGH_V), threshold);
      morphOps(threshold);   // morphological operations: they allow to close the 'hole' and delete the 'dots'

      // threshold now contains the binary that only displays one colour (if the trackbars are set correctly)

      // Apply Gaussian blurring and Canny edge algorithm for the edge detection
      GaussianBlur(threshold, threshold, Size(3,3), 0, 0);   // Kernel = 3x3, Sigmas are calculated automatically (see 'getGaussianKernel()')
      Canny(threshold, edges, LOW_THRESHOLD, HIGH_THRESHOLD);

      /*
         Algorithm that approximates the edges of the figure to a rectangle.
         After that it needs to be able to calculate the rectangle position and orientation
         (will something like RotatedRect be useful?)
      */

      #if DISPLAY_IMAGES == true
         // Show images
         imshow("Camera feed", src);
         imshow("Thresholded", threshold);
         imshow("Edges", edges);
      #endif

      if((char)waitKey(30) == 'q')
         break;
   }

   return 0;
}

void createTrackbarsForHSVSel()
{
   namedWindow("Trackbars", CV_WINDOW_AUTOSIZE);

   createTrackbar("Low  hue", "Trackbars", &LOW_H , HIGH_H );
   createTrackbar("High hue", "Trackbars", &HIGH_H, HIGH_H );
   createTrackbar("Low  sat", "Trackbars", &LOW_S , HIGH_S );
   createTrackbar("High sat", "Trackbars", &HIGH_S, HIGH_S );
   createTrackbar("Low  val", "Trackbars", &LOW_V , HIGH_V );
   createTrackbar("High val", "Trackbars", &HIGH_V, HIGH_V );

   return;
}

void morphOps(Mat &thresh)
{
    // create structuring element that will be used to "dilate" and "erode" image.
    // the element chosen here is a 3px by 3px rectangle.
        // As a rule of thumb you want to dilate with larger element to make sure the object is nicely visible

    erode (thresh,thresh,getStructuringElement( MORPH_RECT, Size(3,3)));
        dilate(thresh,thresh,getStructuringElement( MORPH_RECT, Size(3,3)));

    dilate(thresh,thresh,getStructuringElement( MORPH_RECT, Size(3,3)));
    erode (thresh,thresh,getStructuringElement( MORPH_RECT, Size(3,3)));

    return ;    
}

感谢您的帮助!

【问题讨论】:

  • 你考虑过霍夫变换吗?我用于检测圆形,但理论上适用于所有形状
  • 是的,相交的霍夫线可能会产生矩形/正方形
  • 问题到底出在哪里?因为我不确定。

标签: c++ opencv rectangles rect


【解决方案1】:

如果在阈值处理后矩形的定义与示例中显示的一样好,那么这是一项非常基本的任务。

  1. 使用findContours() 将矩形作为一组点。
  2. 使用minAreaRect() 围绕轮廓绘制矩形(确保方向保持不变。
  3. 一定要find only rectangles,以防将来有噪音。
  4. MinAreaRect 已经包含您需要的所有信息:(x,y), (width, height), theta。记得在您因角度奇怪而发疯之前查看this

应该实时工作没问题。如果您的代码效率低下而没有,只需每 2 或 3 帧进行一次处理即可。

【讨论】:

  • 在 Canny 算法之后,我使用了 findContours,然后我创建了一个实现 minAreaRect 算法的函数。工作得很好,很顺利,现在我只需要调整一些东西让它变得更好。非常感谢!
  • 不客气。如果它解决了您的问题,请考虑接受答案。祝你好运!
猜你喜欢
  • 1970-01-01
  • 2010-09-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多