Hough 算法(霍夫变换)

Hough 算法(霍夫变换)Hough 变换 HoughTransfo 是一种常用的检测图形的算法

大家好,欢迎来到IT知识分享网。

目录

一.什么是Hough 算法(霍夫变换)

它的基本思想是:

Hough 变换的主要步骤为:

二、Hough 变换的应用

它的主要应用如下:

1. 直线检测:

2. 圆检测:

3. 椭圆检测:

4. 三角形检测:

5. 人脸检测:


一.什么是Hough 算法(霍夫变换)

Hough 变换(Hough Transform)是一种常用的检测图形的算法。

它通过搜索特定形状(如直线,圆,椭圆等)在参数空间的累加器中的局部最大值来检测形状。Hough 变换主要用于检测图像中的基本形状,如直线,圆等。

它的基本思想是:

Hough 变换的主要步骤为:

所以,Hough 变换通过在参数空间中的投票统计,实现了对图像中基本形状的检测,它广泛应用于图像处理和计算机视觉中曲线检测的问题。

二、Hough 变换的应用

Hough 变换在许多领域有着广泛的应用,主要原理是通过在参数空间中的投票统计来检测图像中的基本形状。

它的主要应用如下:

1. 直线检测:

直线可以用ρ-θ参数描述,ρ表示直线到原点的距离,θ表示直线与x轴的角度。对每个像素点,累加所有可能通过其的直线在ρ-θ空间的坐标,找到局部最大值点即为检测直线。

import cv2 import numpy as np img = cv2.imread('line.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray,50,150,apertureSize = 3) # 直线的参数由两条信息决定,距离和角度 # distance表示直线到原点(0, 0)的距离 # theta表示直线与x轴的角度 min_distance = 10 # 最小距离 max_distance = 200 # 最大距离 min_theta = -np.pi / 2 # -90° max_theta = np.pi / 2 # 90° # 生成直线参数空间 thetas = np.deg2rad(np.arange(min_theta, max_theta, step=1)) distances = np.linspace(min_distance, max_distance, num=100) line_params = np.zeros((len(distances), len(thetas), 3)) # 在参数空间中投票 for i, distance in enumerate(distances): for j, theta in enumerate(thetas): a = np.cos(theta) b = np.sin(theta) x0 = a * distance y0 = b * distance line_params[i, j, :] = [x0, y0, distance] x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * (a)) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * (a)) cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1) # 统计每个直线参数的投票数(轮廓上的点) votes = np.sum(edges, axis=(0, 1)) # 找到投票数最大的前3条直线 top_idxs = np.argsort(votes)[::-1][:3] top_lines = line_params[top_idxs] # 在原图像中绘制最有可能的3条直线 for x0, y0, distance in top_lines: x1 = int(x0 - 1000 * np.sin(theta)) y1 = int(y0 + 1000 * np.cos(theta)) x2 = int(x0 + 1000 * np.sin(theta)) y2 = int(y0 - 1000 * np.cos(theta)) cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imshow('img', img) cv2.waitKey(0) ''' 1. 边缘检测,得到图像中所有边缘点。 2. 构建直线2维参数空间,即(距离,角度)。 3. 在不同(距离,角度)对在图像中画出对应的直线。 4. 统计每条直线的参数在图像中的投票数(即与直线相交的边缘点数)。 5. 在参数空间中找到投票数前3最大的直线,对应的就是图像中3条最有可能的直线。 6. 在原图像中高亮显示检测到的3条直线。 7. 显示最终结果。 '''

2. 圆检测:

圆可以用圆心坐标和半径描述。每个像素对应多个可能的圆,在三维参数空间(x, y, r)中投票,得到局部最大值点为检测圆的参数。

import cv2 import numpy as np img = cv2.imread('circles.jpg',0) output = img.copy() # 高斯滤波平滑图像,降低噪声 img = cv2.GaussianBlur(img, (5, 5), 0) # 边缘检测 edges = cv2.Canny(img,100,200) # 参数空间中每条曲线对应3个参数(x0,y0,r) # x0,y0: 圆心坐标 # r: 圆半径 min_radius = 10 # 最小半径 max_radius = 100 # 最大半径 # 生成对应参数空间 thetas = np.deg2rad(np.arange(0.0, 360.0, step=1)) circle_params = np.zeros((len(thetas), 3)) # 对每条可能通过边缘点的圆曲线进行参数空间投票 for i, theta in enumerate(thetas): circle_params[i, 0] = np.cos(theta) * min_radius + img.shape[1] / 2 circle_params[i, 1] = np.sin(theta) * min_radius + img.shape[0] / 2 circle_params[i, 2] = min_radius # 在参数空间不同半径上滑动,投票 for r in range(min_radius, max_radius): for i, param in enumerate(circle_params): circle_params[i, 2] = r x, y, r = param cv2.circle(img, (int(x), int(y)), r, (0, 0, 0), 2) # 在参数空间中找出投票最多的3个圆 votes = np.sum(img, axis=(0, 1)) top_idxs = np.argsort(votes)[::-1][:3] top_circles = circle_params[top_idxs] # 绘制出投票前3的圆 for x, y, r in top_circles: cv2.circle(output, (int(x), int(y)), r, (0, 255, 0), 3) # 显示结果 cv2.imshow('input', img) cv2.imshow('output', output) cv2.waitKey(0) ''' 1. 高斯滤波及边缘检测,得到图像中所有边缘点。 2. 构建圆3维参数空间,即(x0,y0,r)。 3. 对每条可能通过某边缘点的圆曲线,在参数空间中投票。在不同半径上滑动,投票。 4. 在参数空间中找到投票数前3最大的圆,对应的就是图像中3条最有可能的圆曲线。 5. 在原图像中画出检测到的3条圆曲线。 6. 显示最终结果。 '''

3. 椭圆检测:

椭圆有五个参数描述,要在五维参数空间中投票统计。

import cv2 import numpy as np img = cv2.imread('ellipses.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray,50,150,apertureSize = 3) # 参数空间中每条曲线对应5个参数(A,B,x0,y0,theta) # A:椭圆长轴大小,B:椭圆短轴大小 # x0,y0: 椭圆中心点坐标 # theta: 椭圆的旋转角度 min_A, max_A = 10, 100 # 椭圆长轴范围 min_B, max_B = 10, 100 # 椭圆短轴范围 # 模型参数空间 thetas = np.deg2rad(np.arange(0.0, 180.0)) params = np.zeros((len(thetas), 5)) # 对每条可能通过边缘点的椭圆曲线进行参数空间投票 for theta in thetas: params[:, 2] = gray.shape[1]/2 # x0坐标设为图像中心 params[:, 3] = gray.shape[0]/2 # y0坐标设为图像中心 params[:, 4] = theta # 旋转角度theta # 根据楞次方程得到不同A和B的值对相应参数进行投票 for A in range(min_A, max_A): for B in range(min_B, max_B): params[A * B, 0] += A # 更新A的值 params[A * B, 1] += B # 更新B的值 # 在参数空间中找出投票最多的前n条椭圆曲线 votes = np.sum(params, axis=1) peak_idxs = np.argsort(votes)[::-1][:3] peaks = params[peak_idxs] # 绘制出投票前3的椭圆曲线 for peak in peaks: A, B, x0, y0, theta = peak theta *= -1 a = A/2 b = B/2 ellipse = ((A*np.cos(theta), B*np.sin(theta)), (x0, y0), a, b * -1) cv2.ellipse(img, ellipse, (0,255,0), 1) # 显示结果 cv2.imshow('img',img) cv2.waitKey(0) ''' 1. 边缘检测,得到图像中所有边缘点。 2. 构建椭圆5维参数空间,即(A,B,x0,y0,theta)。 3. 对每条可能通过某边缘点的椭圆曲线,在参数空间中投票。 4. 在参数空间中找到投票数前3最大的椭圆,对应的就是图像中3条最有可能的椭圆曲线。 5. 在原图像中画出检测到的3条椭圆曲线。 6. 显示最终结果。 '''

4. 三角形检测:

每个三角形有6个自由参数,要在六维空间检测。

 import cv2 import numpy as np img = cv2.imread('triangles.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray,50,150,apertureSize = 3) # 三角形有6个参数(x1,y1,x2,y2,x3,y3) # x1,y1: 三角形第一个顶点坐标 # x2,y2: 三角形第二个顶点坐标 # x3,y3: 三角形第三个顶点坐标 min_vertex = 10 # 最小顶点间距 max_vertex = 100 # 最大顶点间距 # 生成对应参数空间,6维 thetas = np.deg2rad(np.arange(0.0, 180.0, step=2)) d = np.arange(min_vertex, max_vertex, step=5) triangle_params = [] for x1 in d: for y1 in d: for x2 in d: for y2 in d: for x3 in d: for y3 in d: triangle_params.append((x1,y1,x2,y2,x3,y3)) triangle_params = np.array(triangle_params) # 对每条可能通过边缘点的三角形曲线进行参数空间投票 for i, param in enumerate(triangle_params): x1, y1, x2, y2, x3, y3 = param.astype(int) cv2.line(img,(x1,y1),(x2,y2),(0,0,255), 1) cv2.line(img,(x2,y2),(x3,y3),(0,0,255), 1) cv2.line(img,(x3,y3),(x1,y1),(0,0,255), 1) # 统计每组三角形参数的投票数 votes = np.sum(img, axis=(0, 1)) top_idxs = np.argsort(votes)[::-1][:3] top_triangles = triangle_params[top_idxs] # 绘制出投票前3的三角形 for x1, y1, x2, y2, x3, y3 in top_triangles: cv2.line(img,(x1,y1),(x2,y2),(0,255,0), 2) cv2.line(img,(x2,y2),(x3,y3),(0,255,0), 2) cv2.line(img,(x3,y3),(x1,y1),(0,255,0), 2) cv2.imshow('img', img) cv2.waitKey(0) ''' 1. 边缘检测,得到图像中所有边缘点。 2. 构建三角形6维参数空间,即(x1,y1,x2,y2,x3,y3)。 3. 生成所有可能的三角形参数,对每组参数在图像中画出三角形。 4. 统计每组三角形参数的投票数(即图像中三角形边上的黑点数)。 5. 在参数空间中找到投票数前3最大的三角形,对应的就是图像中3条最有可能的三角形曲线。 6. 在原图像中高亮显示检测到的3个三角形。 7. 显示最终结果。 '''

5. 人脸检测:

人脸可以看作椭圆的一种,在相关参数空间中检测人脸。

import cv2 import numpy as np img = cv2.imread('face.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 人脸检测需要一个已经训练好的人脸检测器 # 我们这里使用OpenCV自带的面部级联分类器 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # 先检测图像中的人脸 faces = face_cascade.detectMultiScale(gray, 1.3, 5) # 人脸可以近似看作一个椭圆形状 # 对每个检测到的人脸,确定其外接矩形框 for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # 获取人脸区域的图像,在其上检测眼睛 roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] # Hough变换检测椭圆 # 生成对应参数空间,5维(A,B,x0,y0,theta) min_A = h/4 # 椭圆长轴最小值 max_A = h*3/4 # 椭圆长轴最大值 min_B = w/4 # 椭圆短轴最小值 max_B = w*3/4 # 椭圆短轴最大值 thetas = np.deg2rad(np.arange(0.0, 180.0)) params = np.zeros((len(thetas), 5)) # 对每条可能的椭圆曲线进行参数空间投票 for theta in thetas: params[:, 2] = face.shape[1]/2 params[:, 3] = face.shape[0]/2 params[:, 4] = theta for A in range(min_A, max_A): for B in range(min_B, max_B): params[A * B, 0] += A params[A * B, 1] += B # 找到投票数最大的前n条椭圆曲线,对应图像中n个最可能的眼睛 votes = np.sum(params, axis=1) peak_idxs = np.argsort(votes)[::-1][:2] peaks = params[peak_idxs] # 在检测到的人脸区域中绘制出两条椭圆曲线 # 这两条曲线对应人脸区域中最有可能的两只眼睛 for peak in peaks: A, B, x0, y0, theta = peak theta *= -1 a = A/2 b = B/2 ellipse = ((A*np.cos(theta), B*np.sin(theta)),(x0, y0), a, b * -1) cv2.ellipse(roi_color, ellipse, (0,255,0), 1) cv2.imshow('img',img) cv2.waitKey(0) ''' 1. 使用OpenCV的人脸检测器haarcascade_frontalface_default.xml检测输入图像中的人脸。 2. 对每个检测到的人脸,获取其图像区域。 3. 在人脸区域图像上,使用Hough变换检测椭圆,对应眼睛。 4. 构建椭圆5维参数空间(A,B,x0,y0,theta)。 5. 对每条可能的椭圆曲线在参数空间中投票。 6. 找到投票数前2最大的椭圆曲线,对应人脸区域图像中最有可能的两只眼睛。 7. 在原人脸区域图像上绘制出检测到的两条眼睛椭圆曲线。 8. 显示最终结果。 '''

除此之外,Hough 变换还用于道路分割,指纹识别,磁共振图像分析等领域。它通过参数空间中的投票统计这一简单而有效的原理,实现对各种基本形状的检测,在图像处理和计算机视觉中有广泛的应用。

所以,Hough 变换是一种重要而实用的图像形状检测算法。熟练掌握它的原理,可以在许多领域中得到广泛应用。并且,随着 parameter space 的扩展,Hough 变换的应用范围也在不断扩大。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117531.html

(0)
上一篇 2025-11-20 12:10
下一篇 2025-11-20 12:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信