上篇博客:霍夫變換(直線檢測、圓檢測)中談到關於霍夫變換的原理,但是沒有談到具體實現;

具體的實現如下圖:

如下圖,假定在一個8*8的平面像素中有一條直線,並且從左上角(1,8)像素點開始分別計算θ為0°、45°、90°、135°、180°時的ρ,圖中可以看出ρ分別為1、(9√2)/2、8、(7√2)/2、-1,並給這5個值分別記一票,同理計算像素點(3,6)點θ為0°、45°、90°、135°、180°時的ρ,再給計算出來的5個ρ值分別記一票,此時就會發現ρ = (9√2)/2的這個值已經記了兩票了,以此類推,遍歷完整個8*8的像素空間的時候ρ = (9√2)/2就記了5票, 別的ρ值的票數均小於5票,所以得到該直線在這個8*8的像素坐標中的極坐標方程為 (9√2)/2=x*Cos45°+y*Sin45°,到此該直線方程就求出來了。(PS:但實際中θ的取值不會跨度這么大,一般是PI/180)。

這個網站說明的非常清楚:霍夫線變換¶
最重要的一句:這就是霍夫線變換要做的. 它追蹤圖像中每個點對應曲線間的交點. 如果交於一點的曲線的數量超過了 閾值, 那么可以認為這個交點所代表的參數對
在原圖像中為一條直線.
下面看看閾值對圖像檢測的影響
//-----------------------------------【頭文件包含部分】---------------------------------------
// 描述:包含程序所依賴的頭文件
//----------------------------------------------------------------------------------------------
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
//-----------------------------------【命名空間聲明部分】--------------------------------------
// 描述:包含程序所使用的命名空間
//-----------------------------------------------------------------------------------------------
using namespace std;
using namespace cv;
//-----------------------------------【全局變量聲明部分】--------------------------------------
// 描述:全局變量聲明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage, g_midImage;//原始圖、中間圖和效果圖
vector<Vec4i> g_lines;//定義一個矢量結構g_lines用於存放得到的線段矢量集合
//變量接收的TrackBar位置參數
int g_nthreshold = 100;
//-----------------------------------【全局函數聲明部分】--------------------------------------
// 描述:全局函數聲明
//-----------------------------------------------------------------------------------------------
static void on_HoughLines(int, void*);//回調函數
static void ShowHelpText();
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main()
{
//改變console字體顏色
system("color 3F");
ShowHelpText();
//載入原始圖和Mat變量定義
Mat g_srcImage = imread("E:\\VS2015Opencv\\vs2015\\project\\picture\\07.jpg"); //該目錄下應該有一張名為07.jpg的素材圖
//顯示原始圖
imshow("【原始圖】", g_srcImage);
//創建滾動條
namedWindow("【效果圖】", 1);
createTrackbar("值", "【效果圖】", &g_nthreshold, 200, on_HoughLines);
//進行邊緣檢測和轉化為灰度圖
Canny(g_srcImage, g_midImage, 50, 200, 3);//進行一次canny邊緣檢測
cvtColor(g_midImage, g_dstImage, CV_GRAY2BGR);//轉化邊緣檢測后的圖為灰度圖
//調用一次回調函數,調用一次HoughLinesP函數
on_HoughLines(g_nthreshold, 0);
HoughLinesP(g_midImage, g_lines, 1, CV_PI / 180, 80, 50, 10);
//顯示效果圖
imshow("【效果圖】", g_dstImage);
waitKey(0);
return 0;
}
//-----------------------------------【on_HoughLines( )函數】--------------------------------
// 描述:【頂帽運算/黑帽運算】窗口的回調函數
//----------------------------------------------------------------------------------------------
static void on_HoughLines(int, void*)
{
//定義局部變量儲存全局變量
Mat dstImage = g_dstImage.clone();
Mat midImage = g_midImage.clone();
//調用HoughLinesP函數
vector<Vec4i> mylines;
HoughLinesP(midImage, mylines, 1, CV_PI / 180, g_nthreshold + 1, 50, 10);
//循環遍歷繪制每一條線段
for (size_t i = 0; i < mylines.size(); i++)
{
Vec4i l = mylines[i];
line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23, 180, 55), 1, CV_AA);
}
//顯示圖像
imshow("【效果圖】", dstImage);
}
//-----------------------------------【ShowHelpText( )函數】----------------------------------
// 描述:輸出一些幫助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//輸出一些幫助信息
printf("\n\n\n\t請調整滾動條觀察圖像效果~\n\n");
printf("\n\n\t\t\t\t\t\t\t\t by_ly"
);
}



從平面坐標到極坐標轉換三個參數C(x0,y0,r),
是圓心
假設平面坐標的任意一個圓上的點,轉換到極坐標中:
處有最大值,霍夫變換正是利用這個原理實現圓的檢測。
參考這個網站:霍夫圓變換¶
