霍夫变换原理及实现

时间:2022-03-11 11:16:58

霍夫变换是图像处理必然接触到的一个算法,为了检测出来直线和圆,椭圆之类的形状。
比较好的教程霍夫变换原理
霍夫变换实现步骤:

import cv2

import numpy as np

def hough_detectline(img):

   thetas=np.deg2rad(np.arange(0,180))


   row,cols=img.shape

   diag_len=np.ceil(np.sqrt(row**2+cols**2))

   rhos=np.linspace(-diag_len,diag_len,int(2*diag_len))

   cos_t=np.cos(thetas)

   sin_t=np.sin(thetas)

   num_theta=len(thetas)

   #vote

   vote=np.zeros((int(2*diag_len),num_theta),dtype=np.uint64)

   y_inx,x_inx=np.nonzero(img)

   #vote in hough space

   for i in range(len(x_inx)):

       x=x_inx[i]

       y=y_inx[i]

       for j in range(num_theta):

           rho=round(x*cos_t[j]+y*sin_t[j])+diag_len

           if isinstance(rho,int):

               vote[rho,j]+=1

           else:

               vote[int(rho),j]+=1

   return vote,rhos,thetas

#image = cv2.imread(r'C:\Users\Y\Desktop\input_0.png')

#image_gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

#image_binary=cv2.Canny(image_gray,150,255)

image = np.zeros((500,500))

image[10:100, 10:100] = np.eye(90)

accumulator, rhos,thetas= hough_detectline(image)

#look for peaks

idx = np.argmax(accumulator)

rho = rhos[int(idx/accumulator.shape[1])]

theta = thetas[idx % accumulator.shape[1]]

k=-np.cos(theta)/np.sin(theta)

b=rho/np.sin(theta)

x=np.float32(np.arange(1,150,2))

#要在image 上画必须用float32,要不然会报错(float不行)

y=np.float32(k*x+b)

cv2.imshow("original image",image),cv2.waitKey(0)

for i in range(len(x)-1):

   cv2.circle(image,(x[i],y[i]),5,(255,0,0),1)

cv2.imshow("hough",image),cv2.waitKey(0)

print ("rho={0:.2f}, theta={1:.0f}".format(rho, np.rad2deg(theta)))

使用霍夫变换检测直线具体步骤:

  1. 彩色图像->灰度图
  2. 去噪(高斯核)
  3. 边缘提取(梯度算子、拉普拉斯算子、canny、sobel)
  4. 二值化(判断此处是否为边缘点,就看灰度值==255)
  5. 映射到霍夫空间(准备两个容器,一个用来展示hough-space概况,一个数组hough-space用来储存voting的值,因为投票过程往往有某个极大值超过阈值,多达几千,不能直接用灰度图来记录投票信息)
  6. 取局部极大值,设定阈值,过滤干扰直线
  7. 绘制直线、标定角点
    houghlinesp函数用法
import cv2
import numpy as np

img = cv2.imread('text3.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
cv2.imshow('edges',edges)
cv2.waitKey(0)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,10,minLineLength,maxLineGap)#返回的是所有检测到的直线,每一个元素line是一个[x1,y1,x2,y2]的list
for line in lines:
    for x1, y1, x2, y2 in line:
        cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)


cv2.imwrite('houghlines1.jpg',img)