閱讀前請看<前言>,謝謝!
霍夫變換(Hough Transform)是圖像處理中的一種特徵提取技術,他是檢測和定位直線和解析曲線的有效方法,它通過將邊緣二值圖像變換到Hough空間,在參數空間用極值點的檢測來完成目標的檢測。
就直線檢測而言:
在極座標中ρ = x cos(θ) + y sin(θ)表示一條直線。其中(ρ,θ)確定一條直線,因此可以先將圖片進行邊緣檢測,然後對圖像上每一個非零像素點,在參數座標下變換爲一條直線,然後構建hist(ρ,θ)二維直方圖。在二維直方圖中找到大於給定閾值的值,即爲檢測到的直線。對θ的取值爲0-90度,ρ的取值爲0-sqrt(h*h+w*w),其中邊緣檢測算子我採用sobel算子,也可以用我前兩篇提到的另外兩種邊緣檢測算子。
程序代碼如下:
public void hough(){
Image im = this.clone();
im.sobel();
im.IterBinary();
int ro = (int)Math.sqrt(h*h+w*w);
int theta = 180;
int[][] hist = new int[ro][theta];
for(int k=0;k<theta;k++){
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
if(im.data[j+i*w] != 0){
int rho=(int)(j*Math.cos(k*Math.PI/(theta*2))+i*Math.sin(k*Math.PI/(theta*2)));
hist[rho][k]++;
}
}
}
}
ArrayList<h> index = math.maxIndex(hist,70); //找到大於最大值*0.7的二維直方圖的點
for(int k =0;k<index.size();k++){
double resTheta = index.get(k).angle*Math.PI/(theta*2);
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
int rho = (int)(j*Math.cos(resTheta)+i*Math.sin(resTheta));
if(im.data[j+i*w] != 0 && rho == index.get(k).ro){
data[j+i*w] = setRed(); //在直線上的點設爲紅色
}else{
data[j+i*this.w] = (255<<24)|(data[j+i*this.w]<<16)|(data[j+i*this.w]<<8)|(data[j+i*this.w]);
}
}
}
}
this.gray = false;
}
其中/*
* to save the hough transform's results
*/
class h{
int ro;
int angle;
public h(int r,int a){
this.ro = r;
this.angle = a;
}
}
運行結果如下:
soble算子處理加二值化的結果如下:
該程序只能檢測到0-90度的直線。