opencv 簡單的實現霍夫變換(改進版)
阿新 • • 發佈:2018-11-11
//霍夫變換 輸入單通道二值影象 檢測直線數量 void HoughLines(Mat &img,int n) { int i,j; //行列 int row = img.rows; int col = img.cols; //極徑最大值為 對角線+寬 int max_r = col + cvCeil (sqrt(double(row*row+col*col))); //累加器 三角函式 int *line_cnt[180]; double sin_[180],cos_[180],rad_ = CV_PI/180; for(i = 0; i < 180; i++) { //初始化累加器為0 line_cnt[i] = new int[max_r](); //初始化三角函式 sin_[i] = sin(i*rad_); cos_[i] = cos(i*rad_); } //極徑 極角 int r = 0; int theta = 0; //遍歷影象 判斷並進行累加 uchar *p; for( i = 0; i < row; i++) { p = img.ptr<uchar>(i); for ( j = 0; j < col; j++) { if(p[j] != 0) { for( theta =0; theta < 180 ; theta++) { //極座標 直線方程 r =cvRound(j*cos_[theta]+i*sin_[theta]); //偏移 無負值 r = r + col; line_cnt[theta][r]++; } } } } //存放取出最長的n條直線 int *line_n[3]; line_n[0] = new int[n]();//極角 line_n[1] = new int[n]();//極徑 line_n[2] = new int[n]();//共點數量 int tt = 0,rr = 0,cnt = 0; for(theta = 0; theta < 180; theta++) { for( r = 0; r < max_r; r++) { //最少共點 < 這條直線的共點 則替換 並嘗試進行冒泡 if(line_n[2][n-1] < line_cnt[theta][r]) { line_n[0][n-1] = theta; //累計的時候偏移過 這裡再偏移回來 line_n[1][n-1] = r - col; line_n[2][n-1] = line_cnt[theta][r]; //氣泡排序 for(i = n - 1;i > 0; i--) { //如果大於 則交換 if(line_n[2][i] > line_n[2][i-1]) { tt = line_n[0][i]; rr = line_n[1][i]; cnt = line_n[2][i]; line_n[0][i] = line_n[0][i-1]; line_n[1][i] = line_n[1][i-1]; line_n[2][i] = line_n[2][i-1]; line_n[0][i-1] = tt; line_n[1][i-1] = rr; line_n[2][i-1] =cnt; } else break; } } } } //為了畫綠線 單通道轉換為三通道 cvtColor(img, img, CV_GRAY2BGR); //畫出線段 for(i = 0; i < n; i++ ) { Point pt1, pt2; double a = cos_[line_n[0][i]], b = sin_[line_n[0][i]]; double x0 = a* line_n[1][i], y0 = b* line_n[1][i]; pt1.x = cvRound(x0 + max_r*(-b)); pt1.y = cvRound(y0 + max_r*(a)); pt2.x = cvRound(x0 - max_r*(-b)); pt2.y = cvRound(y0 - max_r*(a)); //綠線 line(img, pt1, pt2, Scalar(0,255,0), 1, CV_AA); } //-------------------釋放記憶體------------------------ for(i = 0; i < 180; i++) { delete []line_cnt[i]; } delete []line_n[0]; delete []line_n[1]; delete []line_n[2]; }