Hough 算法(霍夫变换)

这篇具有很好参考价值的文章主要介绍了Hough 算法(霍夫变换)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

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

它的基本思想是:

Hough 变换的主要步骤为:

二、Hough 变换的应用

它的主要应用如下:

1. 直线检测:

2. 圆检测:

3. 椭圆检测:

4. 三角形检测:

5. 人脸检测:


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

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

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

它的基本思想是:

1. 寻找图像中曲线的一系列特征点,例如直线上的各个点。
2. 对每一个特征点,都考虑通过此点可能超出很多条曲线,每条曲线都有对应的一个参数值。
3. 在参数空间中,对所有可能通过该特征点的曲线参数值进行累加。
4. 找出参数空间中累加值最大的曲线,即为图像中最可能的曲线。
5. 其余特征点与找到的曲线吻合的也属于该曲线,继续在剩余特征点中寻找另一条曲线。比如直线检测,每条直线可以用angle-distance参数描述,特征点为各个像素。每条可能通过该点的直线都对应一个(angle, distance)参数,在angle-distance参数空间累加,找到局部最大值点,即可得到检测直线的角度和距离。

Hough 变换的主要步骤为:

1. 边缘检测:检测出图像中的曲线特征点(局部最大,局部最小,递增点等)。
2. 参数空间生成:对每条可能的曲线,确定其在参数空间中的坐标。
3. 投票:对每一个特征点,判断出其对应的参数空间中的所有可能的曲线,并对相应的参数空间坐标进行投票(累加)。
4. 检测曲线:在参数空间中检测出投票数较大的局部最大值点,这些点对应的参数值即为图像中存在的曲线的参数。
5. 群聚分析:连接符合要检测的曲线定义的特征点,形成较完整的曲线。

所以,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://www.toymoban.com/news/detail-717198.html

到了这里,关于Hough 算法(霍夫变换)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Hough变换原理-直线检测

    目录   一、简介 二、原理 三、Python代码实现           Hough(霍夫)变换是图像处理中从图像中识别几何形状的基本方法之一。 Hough变换是将图像坐标空间变换到参数空间 ,利用点与线的对偶性,将原始图像空间的给定的曲线(今天主要介绍直线)通过曲线表达形式变

    2024年02月04日
    浏览(38)
  • Hough变换(仅供学习使用)

    Hough变换是一种用于在图像中检测直线、圆等形状的技术。Hough变换的基本思想是将图像空间中的点映射到参数空间中,形成一个参数空间图像,然后在参数空间中寻找明显的峰值,这些峰值对应于图像空间中的直线或圆。 在Hough变换中,直线的参数表示为两个变量:斜率和截

    2024年02月10日
    浏览(41)
  • 图像处理之Hough变换检测直线

    霍夫变换是一种特征检测(feature extraction),被广泛应用在图像分析(image analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。由RichardDuda和PeterHart在公元1972年发明,并称之为广义霍夫变换(generalizedHoughtransform),广义霍夫变换和更早前1962年的PaulHough的专利

    2024年02月15日
    浏览(45)
  • OpenCV官方教程中文版 —— Hough 圆环变换

    目标 • 学习使用霍夫变换在图像中找圆形(环) • 学习函数:cv2.HoughCircles() opencv_logo.png :

    2024年02月06日
    浏览(45)
  • 线性变换与计算机视觉的发展

    计算机视觉(Computer Vision)是一门研究如何让计算机理解和解析人类视觉系统所处的环境的科学。它涉及到许多领域,包括图像处理、模式识别、机器学习等。线性变换(Linear Transform)是计算机视觉中的一个基本概念,它可以用来处理图像和其他多维数据。 线性变换是一种将一个

    2024年02月22日
    浏览(48)
  • 计算机视觉-图像的傅里叶变换

    😊😊😊 欢迎来到本博客 😊😊😊 本次博客内容将继续讲解关于OpenCV的相关知识 🎉 作者简介 : ⭐️⭐️⭐️ 目前计算机研究生在读。主要研究方向是人工智能和群智能算法方向。目前熟悉python网页爬虫、机器学习、计算机视觉(OpenCV)、群智能算法。然后正在学习深度

    2023年04月08日
    浏览(41)
  • 【计算机视觉】图像增强----图像的傅立叶变换

    个人简介:  📦个人主页:赵四司机 🏆学习方向:JAVA后端开发  ⏰往期文章:SpringBoot项目整合微信支付 🔔博主推荐网站:牛客网 刷题|面试|找工作神器 📣种一棵树最好的时间是十年前,其次是现在! 💖喜欢的话麻烦点点关注喔,你们的支持是我的最大动力。 目录 一:

    2024年02月04日
    浏览(39)
  • 【计算机视觉】二、图像形成——实验:2D变换编辑(Pygame)

    【计算机视觉】二、图像形成:1、向量和矩阵的基本运算:线性变换与齐次坐标   几何基元是计算机图形学中最基本的图形对象,它们是构建更复杂图形的基础单元。常见的几何基元包括: 点(Point) : 由一对或一组坐标值表示的零维对象。 线段(Line Segment) : 由两个端点确定的

    2024年03月22日
    浏览(45)
  • MATLAB使用hough变换函数输出[H,theta,rho]的具体含义

    输出[H,theta,rho]。 其中Theta 取值-90至89,为1×180的数组。 rho取值根据图片f的大小确定,如图片为400×400像素,则rho取值-(400^2+400^2)^0.5至(400^2+400^2)^0.5,即图片的对角线长度,为1×1131的数组。 Theta,rho仅为hough变换的坐标取值。hough变换的结果储存于输出的H矩阵中。 H矩阵为rho×

    2024年02月06日
    浏览(39)
  • 计算机视觉 图像形成 几何图形和变换 3D到2D投影

            现在我们知道如何表示2D和3D几何图元以及如何在空间上转换它们,我们需要指定如何将 3D图元投影到图像平面上。 我们可以使用线性3D到2D投影矩阵来做到这一点。最简单的模型是正交法,它不需要除法就可以得到最终的(不均匀的)结果。更常用的模型是透视,

    2023年04月08日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包