阅读前请看<前言>,谢谢!
霍夫变换(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度的直线。