从相机检测矩形形状
Detect rectangular shapes from camera
我需要一些关于我正在进行的项目的反馈。本质上,我需要能够从来自摄像机的视频流中跟踪矩形形状。我正在使用 C++ 的 OpenCV 库来执行此操作。
首先,我应用了颜色检测(我一次只需要跟踪一种颜色)。之后,我应用了 Canny 边缘检测以获得过滤图像的轮廓。此时我应该能够确定是否有一个矩形,它在 (x,y) 平面中的位置(知道它的中心或顶点的位置毕竟不会有这么大的差异)和它的方向关于这样的飞机。
所有这些都应该在 "real-time" 中完成,因为信号来自相机,我需要能够跟踪流中显示的形状的这些特征。
这是颜色选择后输入的阈值版本(左)及其轮廓的图片,通过 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 ;
}
感谢您的帮助!
如果矩形在阈值处理后像您在示例中显示的那样定义良好,那么这是一项非常基本的任务。
- 使用findContours()得到矩形作为一组点。
- 使用minAreaRect()围绕等高线绘制矩形(确保方向保持不变。
- 确保find only rectangles以防将来出现一些噪音。
- MinAreaRect 已包含您需要的所有信息:
(x,y), (width, height), theta
。记得在你因为角度怪异而发疯之前检查一下this。
实时工作应该没问题。如果你的代码效率低下,但它没有,只需每 2 或 3 帧进行一次处理。
我需要一些关于我正在进行的项目的反馈。本质上,我需要能够从来自摄像机的视频流中跟踪矩形形状。我正在使用 C++ 的 OpenCV 库来执行此操作。 首先,我应用了颜色检测(我一次只需要跟踪一种颜色)。之后,我应用了 Canny 边缘检测以获得过滤图像的轮廓。此时我应该能够确定是否有一个矩形,它在 (x,y) 平面中的位置(知道它的中心或顶点的位置毕竟不会有这么大的差异)和它的方向关于这样的飞机。 所有这些都应该在 "real-time" 中完成,因为信号来自相机,我需要能够跟踪流中显示的形状的这些特征。
这是颜色选择后输入的阈值版本(左)及其轮廓的图片,通过 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 ;
}
感谢您的帮助!
如果矩形在阈值处理后像您在示例中显示的那样定义良好,那么这是一项非常基本的任务。
- 使用findContours()得到矩形作为一组点。
- 使用minAreaRect()围绕等高线绘制矩形(确保方向保持不变。
- 确保find only rectangles以防将来出现一些噪音。
- MinAreaRect 已包含您需要的所有信息:
(x,y), (width, height), theta
。记得在你因为角度怪异而发疯之前检查一下this。
实时工作应该没问题。如果你的代码效率低下,但它没有,只需每 2 或 3 帧进行一次处理。