边缘检测
记录下项目中的一点东西。
1 //======================================================================================= 2 // ParkingSystem.cpp 3 // 4 //======================================================================================= 5 // 5inch HDMI LCD 800x480 6 // DPI = sqrt(800^2 + 480^2) / 5 = 186.6 像素/英寸 7 // 屏幕宽 = 800 / 186.6 = 4.28 英寸 = 10.87 CM 8 // 屏幕高 = 480 / 186.6 = 2.57 英寸 = 6.52 CM 9 // 10 /* 11 12 x(图像中物体间距离) X(实际中距离) 13 -------------------- = ------------- 14 f(焦距) D(相机到物体垂直距离) 15 16 焦距 f 取: 10 cm 17 相机到物体垂直距离 D 取: 50 cm 18 19 */ 20 21 #include <opencv2\opencv.hpp> 22 #include <iostream> 23 #include <string> 24 #include <vector> 25 #include <cmath> 26 #include <windows.h> 27 #include <process.h> 28 //#include "RaspiCamCV.h" 29 30 using namespace cv; 31 using namespace std; 32 33 const int CAMERA_WIDTH = 400; 34 const int CAMERA_HEIGHT = 400; 35 const int g_WIDTH = 400; 36 const int g_HEIGHT = 400; 37 38 // 像素阈值 39 const int THRESHOLD = 255; 40 // DPI 41 const float LCD_DPI = 186.6; 42 // 焦距(CM) 43 const int CAMERA_FOCUS = 10; 44 // 相机到物体垂直距离(CM) 45 const int CAMERA_TO_OBJECT_DISTANCE = 50; 46 47 // grobal variable 48 static cv::Mat g_srcImage, g_srcGrayImage, g_edge, g_dstImage; 49 static vector<Vec4i> g_allLines; 50 static Point point1, point2; 51 static Point VideoCenter(199, 199); 52 53 // 推荐的高低阈值比在2:1到3:1之间 54 const int CANNY_threshold1 = 30; 55 const int CANNY_threshold2 = 80; 56 57 const int HoughLines_threshold = 150; 58 59 60 void Image_Processing(); 61 void DrawLine(Mat &img, Point start, Point end); 62 void DrawHoughLines(Mat &img); 63 float findDistanceBetweenPointsI(const CvPoint p1, const CvPoint p2); 64 float CalcuteDistance(const CvPoint point1, const CvPoint point2, const CvPoint point3); 65 66 67 //main 68 //======================================================================================= 69 int main() 70 { 71 72 VideoCapture videoCapture(0); 73 videoCapture.set(CV_CAP_PROP_FRAME_WIDTH, CAMERA_WIDTH); 74 videoCapture.set(CV_CAP_PROP_FRAME_HEIGHT, CAMERA_HEIGHT); 75 76 cvNamedWindow("window1"); 77 cvMoveWindow("window1", 0, 40); 78 cvNamedWindow("window2"); 79 cvMoveWindow("window2", g_WIDTH + 1, 40); 80 81 while (1) 82 { 83 Mat cameraFrame; 84 videoCapture >> cameraFrame; 85 if (cameraFrame.empty()) 86 { 87 cerr << "ERROR: Couldn't grab the next camera frame." << endl; 88 exit(1); 89 } 90 91 // Get a copy of the camera frame that we can draw onto. 92 Mat displayedFrame; 93 cameraFrame.copyTo(displayedFrame); 94 cameraFrame.copyTo(g_srcImage); 95 96 Image_Processing(); 97 Mat finalImage(g_WIDTH,g_HEIGHT, CV_8UC3, Scalar(0, 0, 0)); 98 DrawHoughLines(finalImage); 99 100 101 // Show the camera frame on the screen. 102 imshow("window1", displayedFrame); 103 // Show the final frame on the screen. 104 imshow("window2", finalImage); 105 106 107 // IMPORTANT: Wait for atleast 20 milliseconds, so that the image can be displayed on the screen! 108 // Also checks if a key was pressed in the GUI window. Note that it should be a "char" to support Linux. 109 char keypress = waitKey(20); // This is needed if you want to see anything! 110 if (keypress == VK_ESCAPE) 111 { // Escape Key 112 // Quit the program! 113 break; 114 } 115 116 } 117 118 cvDestroyWindow("window1"); 119 cvDestroyWindow("window2"); 120 return 0; 121 } 122 123 124 // 图像预处理 125 void Image_Processing() 126 { 127 cvtColor(g_srcImage, g_srcImage, COLOR_BGR2GRAY);; 128 129 equalizeHist(g_srcImage, g_srcGrayImage); 130 131 // 先使用 3x3内核来降噪 132 blur(g_srcGrayImage, g_edge, Size(3, 3)); 133 // 运行Canny算子,边缘检测 134 Canny(g_edge, g_edge, CANNY_threshold1, CANNY_threshold2, 3); 135 136 // 霍夫线变换 137 HoughLinesP(g_edge, g_allLines, 1, CV_PI / 180, HoughLines_threshold, 50, 10); 138 139 } 140 141 // 画直线 142 void DrawLine(Mat &img, Point start, Point end) 143 { 144 int thickness = 1; 145 int lineType = 8; 146 // 红色,细 147 line(img, 148 start, 149 end, 150 Scalar(0, 0, 255), 151 thickness, 152 lineType); 153 } 154 155 // 画霍夫线变换后的直线 156 void DrawHoughLines(Mat &img) 157 { 158 Vec4i L; 159 for (size_t i = 0; i < g_allLines.size(); i++) 160 { 161 L = g_allLines[i]; 162 DrawLine(img, Point(L[0], L[1]), Point(L[2], L[3])); 163 } 164 } 165 166 float findDistanceBetweenPointsI(const CvPoint p1, const CvPoint p2) 167 { 168 // Calc the pythagoras distance. 169 int dx = (p1.x - p2.x); 170 int dy = (p1.y - p2.y); 171 return sqrt((float)(dx * dx + dy * dy)); 172 } 173 174 // 计算 point3 到由 point1和point2构成的直线距离 175 float CalcuteDistance(const CvPoint point1, const CvPoint point2, const CvPoint point3) 176 { 177 float K, D; 178 if (point2.x == point1.x) 179 { 180 return fabs(float((point3.x - point1.x))); 181 } 182 else if (point2.y == point1.y) 183 { 184 return fabs(float((point3.y - point1.y))); 185 } 186 else 187 { 188 /* 189 190 A*x + B*y + C = 0 191 d = | A*x0 + B*y0 + C | / sqrt(A^2 + B^2) 192 193 K = (y2 - y1) / (x2 - x1) 194 K*x - y + y1 - K*x1 = 0 195 196 */ 197 K = (float(point2.y - point1.y) / float(point2.x - point1.x)); 198 D = fabs(K*point3.x - point3.y + point1.y - K*point1.x) / sqrt(K*K + 1); 199 return D; 200 } 201 }