我正在尝试制作一个形状检测程序,在RC飞机上飞行时检测地面上的形状。问题是程序不是很准确。它会偶尔找到一个形状,但不是一贯的。我尝试过HSV过滤和Canny阈值处理,但它们似乎没有像我使用它们那样工作。有没有办法改善或完全取消我的方法?
我已经包含了我一直在测试的东西的图像。
此窗口上应勾勒出形状 - >
在此窗口中可以看到阈值图像 - >
我一直在搞乱的代码就在这里
//include section
#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
//finds the angles for shape detection Status: Good to go
double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 );
//This is for color filtering Status: Doesn't Work Yet
IplImage* GetThresholdedImage(IplImage* imgHSV);
// flag definitions 1: HSV color filtering; 2: Canny Edge Detect; 3: HSV Filter with canny filtering;
////Change these values to get what you need
int flag = 1;
//These values change the HSV filtering values.
int Hue_Min = 112;
int Hue_Max = 251;
int Saturation_Min = 0;
int Saturation_Max = 256;
int Value_Min = 38;
int Value_Max = 218;
int main()
{
//Make the windows
cvNamedWindow("Thresholded",CV_WINDOW_NORMAL);
cvNamedWindow("Tracked",CV_WINDOW_NORMAL);
cvNamedWindow("Original",CV_WINDOW_NORMAL);
//Gets stuff from camera
CvCapture* capture = cvCaptureFromCAM(0);
//This variable will hold all the frames. It will hold only one frame on each iteration of the loop.
IplImage* frame;
while(1)
{
//Gets Frame from camera
std::cout << "frame capture\n";
frame = cvQueryFrame(capture);
std::cout << "Check\n";
//puts the original image in the window
cvShowImage("Original",frame);
std::cout << "declare imgGrayScale\n";
IplImage* imgGrayScale;
std::cout << "check\n";
//Use the Pyramid thing rob has been working on here
//
//cvSmooth( frame, frame, CV_GAUSSIAN, 5, 5 );
if(flag ==1){
//Filter unwanted colors out
std::cout << "HSV Flag Active\n";
std::cout << "HSV Color Filter\n";
imgGrayScale = GetThresholdedImage(frame);
std::cout << "Check\n";
}
if(flag ==2)
{
std::cout << "Grayscale HSV Flag Active\n";
//Making a single channel matrix so that edge detection can work properly
std::cout << "Grayscale Image\n";
imgGrayScale = cvCreateImage(cvGetSize(frame), 8, 1);
cvCvtColor(frame,imgGrayScale,CV_BGR2GRAY);
std::cout << "Check\n";
// This thresholds the grayscale image to be tested on
std::cout << "Canny Threshold Image\n";
//cvThreshold(imgGrayScale,imgGrayScale,100,255,CV_THRESH_BINARY | CV_THRESH_OTSU);
cvCanny( imgGrayScale, imgGrayScale, 100, 100, 3 );
std::cout << "Check\n";
}
if(flag == 3)
{
std::cout << "HSV Canny Flag Active\n";
std::cout << "HSV Color Filter\n";
imgGrayScale = GetThresholdedImage(frame);
std::cout << "Check\n";
std::cout << "Canny Threshold Image\n";
//cvThreshold(imgGrayScale,imgGrayScale,100,255,CV_THRESH_BINARY | CV_THRESH_OTSU);
cvCanny( imgGrayScale, imgGrayScale, 100, 100, 3 );
std::cout << "Check\n";
}
std::cout << "Contour Allocation\n";
CvSeq* contours; //hold the pointer to a contour in the memory block
CvSeq* result; //hold sequence of points of a contour
CvMemStorage *storage = cvCreateMemStorage(0); //storage area for all contours
std::cout << "Check\n";
std::cout << "Find Contours\n";
//finding all contours in the image
cvFindContours(imgGrayScale, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
std::cout << "Check\n";
while(contours){
//obtain a sequence of points of contour, pointed by the variable 'contour'
result = cvApproxPoly(contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0);
//Triangle Detection
//if there are 3 vertices in the contour(It should be a triangle)
if(result->total==3 )
{
//iterating through each point
CvPoint *pt[3];
for(int i=0;i<3;i++){
pt[i] = (CvPoint*)cvGetSeqElem(result, i);
}
//This If Statement ensures that the edges are sufficiently large enough to be detected
if(abs(pt[1]->x - pt[0]->x)>10 && abs(pt[1]->x - pt[2]->x)>10 && abs(pt[2]->x - pt[0]->x)>10){
//////////drawing lines around the triangle
cvLine(frame, *pt[0], *pt[1], cvScalar(255,0,0),4);
cvLine(frame, *pt[1], *pt[2], cvScalar(255,0,0),4);
cvLine(frame, *pt[2], *pt[0], cvScalar(255,0,0),4);
std::cout << "\nTriangle\n";
}
}
//Rectangle detection
//if there are 4 vertices in the contour(It should be a quadrilateral)
else if(result->total==4 )
{
//iterating through each point
CvPoint *pt[4];
for(int i=0;i<4;i++){
pt[i] = (CvPoint*)cvGetSeqElem(result, i);
}
//finding angles
double firstAngle = acos(angle( pt[0],pt[2],pt[1] ));
double secondAngle = acos(angle(pt[1],pt[3],pt[2]));
double thirdAngle = acos(angle(pt[1],pt[3],pt[2]));
double fourthAngle = acos(angle(pt[0],pt[2],pt[3]));
//This If Statement Ensures that the edges are sufficiently large
if(abs(pt[1]->x - pt[0]->x)>10 && abs(pt[1]->x - pt[2]->x)>10 && abs(pt[2]->x - pt[3]->x)>10 && abs(pt[3]->x - pt[0]->x)>10){
//This if statement checks the angles to see if its a rectangle or not (90 angles with 10% uncertainty)
if(firstAngle <= 1.884 && firstAngle >= 1.308 && secondAngle <= 1.884 && secondAngle >= 1.308 && thirdAngle <= 1.884 && thirdAngle >= 1.308 && fourthAngle <= 1.884 && fourthAngle >= 1.308 )
{
//drawing lines around the quadrilateral
cvLine(frame, *pt[0], *pt[1], cvScalar(0,255,0),4);
cvLine(frame, *pt[1], *pt[2], cvScalar(0,255,0),4);
cvLine(frame, *pt[2], *pt[3], cvScalar(0,255,0),4);
cvLine(frame, *pt[3], *pt[0], cvScalar(0,255,0),4);
std::cout << "\nsquare\n" ;
//cout << firstAngle; //Uncomment this to get the angles that its detecting.
}
}
}
contours = contours->h_next;
}
//Put the images in the frame
cvShowImage("Tracked",frame);
cvShowImage("Thresholded",imgGrayScale);
char c = cvWaitKey(33);
if(c==27)
{
//cleaning up
cvDestroyAllWindows();
cvReleaseImage(&frame);
cvReleaseImage(&imgGrayScale);
cvReleaseMemStorage(&storage);
break;
}
//for(int i=1;i<100000000/5;i++);
cvReleaseImage(&imgGrayScale);
cvReleaseMemStorage(&storage);
}
return 0;
}
IplImage* GetThresholdedImage(IplImage* imgHSV){
IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U,1);
cvInRangeS(imgHSV, cvScalar(Hue_Min,Saturation_Min,Value_Min), cvScalar(Hue_Max,Saturation_Max,Value_Max), imgThresh);
return imgThresh;
}
double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
{
double dx1 = pt1->x - pt0->x;
double dy1 = pt1->y - pt0->y;
double dx2 = pt2->x - pt0->x;
double dy2 = pt2->y - pt0->y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
答案 0 :(得分:1)
通常,为了提取同质区域,已知MSER(最大稳定的极值区域)效果很好,它在OCR中被广泛使用,并且您显示的图像似乎也具有相同的属性,均匀的颜色区域然后是字母在他们里面。还有一个openCV实现可供它使用。
http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions