cvCanny函式中, 高低閾值自適應計算方法
阿新 • • 發佈:2019-02-13
OpenCV的Canny演算法實現函式的引數中, 需要輸入高低閾值, 如果高低閾值輸入不對, 通常等不到理想的邊緣效果.
網上有人仿Matlab, 實現了自適應高低閾值, 程式碼如下:
看看cvCanny函式的程式碼:
我們也可以自己求出用Sobel運算元求出水平和垂直方向的強度, 然後求出高低閾值, 然後再呼叫cvCanny, 但是這樣子就重複了Sobel運算元的計算了.
參考:
http://read.pudn.com/downloads171/sourcecode/graph/texture_mapping/791537/StraightLineFinder/StraightLineFinder/StraightLineFinder.cpp__.htm
http://blog.chinaunix.net/uid-14231482-id-2826875.html
http://blog.csdn.net/sunlylorn/article/details/8015825
網上有人仿Matlab, 實現了自適應高低閾值, 程式碼如下:
至於為什麼這樣來求出高低閾值, 自己也不是很理解. 其中CvMat *dx和CvMat *dy分別是用兩個Sobel運算元計算水平和垂直兩個方向的梯度強度得到的.void HYAdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high) { CvSize size = cvGetSize(dx); IplImage* imge = cvCreateImage(size, IPL_DEPTH_32F, 1); // 計算邊緣的強度, 並存於影象中 int i, j; short* _dx = 0; short* _dy = 0; float* _image = 0; float maxv = 0; for(i = 0; i < size.height; ++i) { _dx = (short*)(dx->data.ptr + dx->step * i); _dy = (short*)(dy->data.ptr + dy->step * i); _image = (float *)(imge->imageData + imge->widthStep * i); for(j = 0; j < size.width; ++j) { _image[j] = (float)(abs(_dx[j]) + abs(_dy[j])); maxv = maxv < _image[j] ? _image[j]: maxv; } } int hist_size = 255; float range_0[] = {0, 256}; float* ranges[] = {range_0}; // 計算直方圖 range_0[1] = maxv; // 最大值 hist_size = (int)(hist_size > maxv ? maxv : hist_size); CvHistogram* hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1); cvCalcHist(&imge, hist, 0, 0); double dPercentOfPixelsNotEdges = 0.97; int total = (int)(size.height * size.width * dPercentOfPixelsNotEdges); float sum=0; int icount = hist->mat.dim[0].size; float *h = (float*)cvPtr1D(hist->bins, 0); for(i = 0; i < icount; ++i) { sum += h[i]; if(sum > total) break; } // 計算高低門限 *high = (i + 1) * maxv / hist_size ; *low = *high * 0.4 ; cvReleaseImage(&imge); cvReleaseHist(&hist); }
看看cvCanny函式的程式碼:
重編一下OpenCV的程式碼, cvCanny函式的兩個高低閾值就可以實現自適應了....... //梯度 dx = cvCreateMat( size.height, size.width, CV_16SC1 ); dy = cvCreateMat( size.height, size.width, CV_16SC1 ); cvSobel( src, dx, 1, 0, aperture_size ); cvSobel( src, dy, 0, 1, aperture_size ); // 我們可以在這裡自適應計算高低閾值 if(low_thresh == -1 && high_thresh == -1) { HYAdaptiveFindThreshold(dx, dy, &low_thresh, &high_thresh); } ......
我們也可以自己求出用Sobel運算元求出水平和垂直方向的強度, 然後求出高低閾值, 然後再呼叫cvCanny, 但是這樣子就重複了Sobel運算元的計算了.
參考:
http://read.pudn.com/downloads171/sourcecode/graph/texture_mapping/791537/StraightLineFinder/StraightLineFinder/StraightLineFinder.cpp__.htm
http://blog.chinaunix.net/uid-14231482-id-2826875.html
http://blog.csdn.net/sunlylorn/article/details/8015825