工程在这:github,这一部分工作是统一上传的,所以和别的工程放在同一个repository里了,见谅
由于要在树莓派上运行直线检测的代码,opencv提供的霍夫直线的效率不能够满足博主的需求,用了三天时间写了一个注重效率的直线检测。
因为场景中这个图片其实是非常简单的,羽毛球场地,绿地加白边,做完边缘检测之后就十分的简洁了,一般封装好的直线检测函数都是设计来应对各种复杂环境的,这样自然而然效率就跟不上了。
看图猜算法,不知道你猜出来没有。其实就是在图片中采样,第一张图的红线就是采样点,如果有白点就做个标记。然后检查每两个白点,直接去原图中对两个白点连线位置上的数据进行采样,如果采集到了大量白点,就认为是识别的直线啦。
然后我写的这个算法检测时间只有霍夫直线的百分之二到百分之十左右。工程中运用了自行定义了动态的数组,这个方法是受浙大老师翁恺的启发。
上传的仍然是vs工程,函数都封装在了base.h和base.cpp中。以下是base.h的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
#ifndef _OLI_H #define _OLI_H_ #include <iostream> #include <opencv2/opencv.hpp> #include <cmath> #include <cstdlib> #include <cstdio> //50 #define BLOCK_SIZE_POINT 50 //10 #define BLOCK_SIZE_LINE 10 //合并点时,坐标相差TH_SAME以下时认为是同一个点,不做操作,3 #define TH_SAME 3 //合并点时,坐标相差TH_CLOSE以下时认为是相邻点,与原点去平均值后存入,15 #define TH_CLOSE 15 //TIME_X和TIME_Y是扫描次数,8*6 #define TIME_X 8 #define TIME_Y 6 //检查是否构成直线时,检查区域的次数,5 #define LINE_CHECK_TIME 5 //判断是否构成直线式,若两点的x和y差均小于TH_SKIP_LINE,判断不构成直线,10 #define TH_SKIP_LINE 10 //20 #define SCAN_RANGE 20 //检查区域的范围(必须小于SCAN_RANGE的两倍,否则可能越界访问),5 #define TH_CHECK_AREA 5 using namespace cv; using namespace std; typedef struct __MyPoint{ int x; int y; }myPoint; typedef struct __MyLine{ int x; int y; double slope; }myLine; typedef struct __MyPoints{ myPoint *array; int size; int max; }myPoints; typedef struct __MyLines{ myLine *array; int size; int max; }myLines; myPoints initPoints(); void freeArray(myPoints *points); int getArraySize(myPoints *points); myPoint getPoint(myPoints *points,int index); void setPoint(myPoints *points,int index,myPoint point); int getArrayMax(myPoints *points); void expandArray(myPoints *points); void addPoint(myPoints *points,myPoint point); void displayPoints(myPoints *points); myLines initLines(); void freeArray(myLines *lines); int getArraySize(myLines *lines); myLine getLine(myLines *lines,int index); void setLine(myLines *lines,int index,myLine line); int getArrayMax(myLines *lines); void expandArray(myLines *lines); void addLine(myLines *lines,myLine line); void displayLines(myLines *lines); myPoint initPoint(int x,int y); myLine initLine(int x,int y,double slope); void displayPoint(myPoint); void displayLine(myLine); int isOnLine(myPoint point,myLine line,int threshold); myLine getLineFromTwoPoints(myPoint,myPoint); int isOnExistLines(myPoint point,myLines *lines); int isLine(myPoints *points,int *flag,int i,int j,Mat mat); int checkArea(Mat mat,int x,int y,double slope); void displayMatchPoints(Mat mat,myPoints *points); void displayMatchLines(Mat mat,myLines *lines); void initFlag(int* flag,int size); void removePoint(int* flag,int index); void recoverPoint(int* flag,int index); int isFlag(int* flag,int index); void displayFlag(int*flag,int size); void getPointsFromMat(Mat mat,myPoints *points); myLines frame(Mat mat,myPoints *points); #endif |