1. 程式人生 > >影象處理(八)——霍夫變換

影象處理(八)——霍夫變換

霍夫變換是一種特徵檢測(feature extraction),被廣泛應用在影象分析(image analysis)、電腦視覺(computer vision)以及數位影像處理(digital image processing)。
霍夫變換是用來辨別找出物件中的特徵,例如:線條。他的演算法流程大致如下,給定一個物件、要辨別的形狀的種類,演算法會在引數空間(parameter space)中執行投票來決定物體的形狀,而這是由累加空間(accumulator space)裡的區域性最大值(local maximum)來決定。

而本次實驗我要做的就是使用霍夫變換進行影象圓的檢測。

霍夫變換的過程可以分為以下幾步:

  1. 對輸入影象進行邊緣檢測,獲取邊界點,即前景點。
  2. 假如影象中存在圓形,那麼其輪廓必定屬於前景點(此時請忽略邊緣提取的準確性)。
  3. 同霍夫變換檢測直線一樣,將圓形的一般性方程換一種方式表示,進行座標變換。由x-y座標系轉換到a-b座標系。寫成如下形式(a-x)²+(b-y)²=r²。那麼x-y座標系中圓形邊界上的一點對應到a-b座標系中即為一個圓。
  4. 那x-y座標系中一個圓形邊界上有很多個點,對應到a-b座標系中就會有很多個圓。由於原影象中這些點都在同一個圓形上,那麼轉換後a,b必定也滿足a-b座標系下的所有圓形的方程式。直觀表現為這許多點對應的圓都會相交於一個點,那麼這個交點就可能是圓心(a, b)。
  5. 統計區域性交點處圓的個數,取每一個區域性最大值,就可以獲得原影象中對應的圓形的圓心座標(a,b)。一旦在某一個r下面檢測到圓,那麼r的值也就隨之確定。

在實際實現中,只需要注意輸入的是灰度圖,以及霍夫變換中的引數問題,就可以較好地實現影象中圓的檢測。

結果如下圖:
在這裡插入圖片描述

不過我的實現中還存在一些問題,例如影象如果是不完全連通的,有時候就不能識別。
在這裡插入圖片描述
在這張圖例,第二行第二個圓就沒有識別出來,而且第二行第一個圖識別出了兩個圓。

此外,對於邊緣粗細不一樣的圖形,我的實現中會出現識別出n多個圓的情況。
在這裡插入圖片描述
可能是因為對於不同畫素的位置,而識別出了不同的圓。


程式碼自取:

#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	//【1】載入原始圖和Mat變數定義   
	Mat srcImage = imread("E:/C++/CVE7/1.jpg");  //工程目錄下應該有一張名為1.jpg的素材圖
	Mat midImage, dstImage;//臨時變數和目標圖的定義

						   //【2】顯示原始圖
	imshow("【原始圖】", srcImage);

	//【3】轉為灰度圖,進行影象平滑
	cvtColor(srcImage, midImage, CV_BGR2GRAY);//轉化邊緣檢測後的圖為灰度圖
	GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);

	//【4】進行霍夫圓變換
	vector<Vec3f> circles;
	HoughCircles(midImage, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);

	//【5】依次在圖中繪製出圓
	for (size_t i = 0; i < circles.size(); i++)
	{
		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
		int radius = cvRound(circles[i][2]);
		//繪製圓心
		circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
		//繪製圓輪廓
		circle(srcImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);
	}

	//【6】顯示效果圖  
	imshow("【效果圖】", srcImage);

	waitKey(0);

	return 0;
}