【opencv】hough圓變換
霍夫梯度法原理如下:首先對影象應用canny邊緣檢測,然後對邊緣影象中每一個非0點,考慮其區域性梯度,通過sobel計算。利用得到的梯度,由斜率指定的直線上的每一個點都在累加器中被累加,同時,標記邊緣影象中每一個非0畫素的位置。然後從累加器中這些點中選擇候選的中心,這些中心都大於給定閾值並且大於其所有近鄰。這些候選的中心按照累加值降序排列,以便於最支援畫素的中心首先出現。接下來對每一箇中心,考慮所有的非0畫素。這些畫素按照其與中心的距離排序。從到最大半徑的最小距離算起,選擇非0畫素最支援的一條半徑。如果一箇中心受到邊緣影象非0畫素最充分的支援,並且到前期被選擇的中心有足夠的距離,它將會被保留。這個實現可以使演算法執行起來更快,能夠幫助解決三維累加器中其他稀疏分佈問題。
void HoughCircles(
InputArray image,//輸入影象8位
OutputArray circles,//陣列或儲存器
int method, //CV_HOUGH_GRADIENT 目前只有梯度法
double dp, //累加器影象解析度 ≥1
double minDist,//不同圓之間最小距離
double param1=100, //canny上限閾值,下限閾值=上限閾值/2cvCanny( img, edges, MAX(canny_threshold/2,1), canny_threshold, 3 );</span>
double param2=100,//累加器閾值
int minRadius=0, //最小圓半徑
int maxRadius=0 //最大圓半徑
);
cvCircle(
CvArr* img, //輸入影象
CvPoint center, //圓心
int radius,//半徑
CvScalar color, //顏色
int thickness CV_DEFAULT(1),//粗細
int line_type CV_DEFAULT(8),
int shift CV_DEFAULT(0)//0
);
樣圖:圓直徑依次為 80,90,100,110,120
未經平滑處理結果:cvcircle繪製時,半徑與圓心損失精度
經平滑處理結果:cvcircle繪製時,半徑與圓心損失精度
using namespace cv; int main() { IplImage* img = cvLoadImage("correct_Img_1.jpg",0);//轉為灰度圖 cvSmooth( img, img, CV_GAUSSIAN, 5, 5);//平滑處理 vector<Vec3f> circles; HoughCircles( (Mat)img, circles, CV_HOUGH_GRADIENT, 1.5 ,10, 80, 110, 35 ,65);//hough圓變換 //img = cvLoadImage("correct_Img_1.jpg",1); for (int i = 0; i < circles.size(); i++) { CvPoint center;//圓心 center.x = circles[i][0]; center.y = circles[i][1]; int radius = circles[i][2];//半徑 cvCircle( img, center, radius, Scalar(0,255,0), 1, 8, 0);//繪製圓 cvCircle( img, center, 3, Scalar(0,255,0), 3, 8, 0);//繪製圓心 std::cout<<"圓心為:"<<circles[i][0]<<","<<circles[i][1]<<" 直徑為:"<<2*circles[i][2]<<"\n";//為了保證精度,以原值輸出 } cvSaveImage("out.jpg",img); cvNamedWindow("hough圓檢測",1); cvShowImage("hough圓檢測",img); cvWaitKey(0); cvReleaseImage(&img); cvDestroyWindow("hough圓檢測"); return 0; }