首页 > 其他分享 >霍夫变换

霍夫变换

时间:2023-04-28 15:35:28浏览次数:43  
标签:直线 变换 霍夫 rho np theta

OpenCV: Hough Line Transform
GitHub上的一个项目

原理与代码

二维直线检测

一条直线可以表示为:

\[\rho=x\cos \theta+y\sin\theta \]

在(x,y)空间中的一个点(x0,y0),在\((\theta,\rho)\)空间中表示为一条曲线。
在\((\theta,\rho)\)空间中的一个点\((\theta_0,\rho_0)\),在(x,y)空间中表示为一条直线。
因此,一条直线上的点在霍夫空间中,表现为多条曲线相交于一点。

%% 读取图片
% I = imread('circuit.tif');
I = imread('243153c2d4cce8e2531ed747a22a2c4.png');
I = rgb2gray(I);
rotI = I;
% imrotate(I,33,'crop');

%% 边缘提取
BW = edge(rotI,'canny');


%% 霍夫空间变换 Input: BW,rhoresolution,theta_limit,n_theta
%%%参数:
[y,x]=find(BW==1);
rhoresolution=1; %%分辨率
theta_mmN=[-pi/2,pi/2];  %%theta的最小最大值和个数
n_theta=180; %%theta的个数

sz=size(BW);
rho_max=sqrt(sz(1)^2+sz(2)^2);  %%最大的rho值
n_rho=ceil(rho_max/rhoresolution)*2; %%霍夫空间rho向的个数
H=zeros(n_rho,n_theta); %%用来存储投票数的矩阵

theta=linspace(theta_mmN(1),theta_mmN(2),n_theta+1); theta=theta(1:end-1);
rho_axis = ((1:n_rho)-n_rho/2-1)*rhoresolution;
rho=x.*cos(theta)+y.*sin(theta);

%% 投票 
rho_num = floor(rho/rhoresolution) + ceil(rho_max/rhoresolution) +1; %%rho值对应的区间[1-n_rho]
%%计算对应theta下,每个rho区间中的个数
[rho_num_sorted , sort_index] = sort(rho_num,1);
diff_01 = [ones(1,n_theta); diff(rho_num_sorted,1); ones(1,n_theta)];
for i = 1:n_theta
    num_temp = diff(find(diff_01(:,i)>0),1);
    rho_temp = rho_num_sorted(:,i);
    rho_num_temp = rho_temp(diff_01(1:end-1,i)>0);
    H(rho_num_temp,i) = H(rho_num_temp,i)+num_temp;
end

%% 找到N条直线
N=5;
lines=zeros(N,6); %%每条直线6个参数: x1,y1,x2,y2,rho,theta
size_H = size(H);
[H_sort, H_sort_Index] = sort(H(:));
H_sort_Index_1 = mod(H_sort_Index,n_rho); %%H的行索引
H_sort_Index_2 = ceil(H_sort_Index/n_rho); %%H的列索引

for i=1:N
    line = zeros(1,6);
    line(5) = rho_axis(H_sort_Index_1(end-i+1));
    line(6) = theta(H_sort_Index_2(end-i+1));
    rho_num_1lie = rho_num(:,H_sort_Index_2(end-i+1));
    num_points=find(rho_num_1lie==H_sort_Index_1(end-i+1));
    line(1) = x(num_points(1));
    line(2) = y(num_points(1));
    line(3) = x(num_points(end));
    line(4) = y(num_points(end));
    lines(i,:)=line;
end


%% 绘图
%原始图片
figure;
imshow(rotI);

%边缘提取
figure;
ax=axes();
imshow(BW)
hold on;
axis equal;
pbaspect([1,1,0.8]);%坐标轴比例
colormap gray;
% plot(x,y,'.');

%%%霍夫空间
% figure;
% plot(theta,rho);
figure;
imshow(imadjust(rescale(H)),[],...
       'XData',theta,...
       'YData',rho_axis,...
       'InitialMagnification','fit');
hold on;
xlabel('\theta (degrees)')
ylabel('\rho')
axis on
axis normal
hold on
colormap(gca,hot)
plot(lines(6),lines(5),'s','color','r');


%%%在原始图像上
plot(ax,[lines(:,1)';lines(:,3)'],[lines(:,2)';lines(:,4)'],'-+','LineWidth',2)

二维圆检测

三维霍夫变换

(1条消息) 3D Hough变换点云平面检测算法_时义龙的博客-CSDN博客

ChatGPT


role::user

什么是霍夫变换?


role::assistant

霍夫变换(Hough Transform)是一种图像处理算法,用于检测图像中的直线、圆和其他形状。它的基本思想是将图像中的每个点转换为参数空间中的一个曲线或点,并在参数空间中查找共线或共圆的曲线或点。这样就可以检测出图像中的直线、圆或其他形状。霍夫变换在计算机视觉、图像处理、模式识别等领域有广泛的应用。


role::user

什么是三维霍夫变换?


role::assistant

三维霍夫变换(3D Hough Transform)是一种扩展的霍夫变换,用于在三维空间中检测和识别三三维霍夫变换(3D Hough Transform)是在三维空间中进行的霍夫变换,用于检测三维空间中的直线、平面和其他形状。与二维霍夫变换类似,三维霍夫变换将三维空间中的每个点转换为参数空间中的一个曲线或点,并在参数空间中查找共线或共面的曲线或点。这样就可以检测出三维空间中的直线、平面或其他形状。

三维霍夫变换在计算机视觉、机器人视觉、医学图像处理等领域有广泛的应用。例如,在机器人视觉中,可以使用三维霍夫变换来检测三维空间中的物体,从而实现机器人的自主定位和导航。在医学图像处理中,可以使用三维霍夫变换来检测三维空间中的肿瘤和其他异常结构,从而帮助医生进行诊断和治疗。


role::user

如何做二维的霍夫变换


role::assistant

二维霍夫变换(2D Hough Transform)是一种用于检测图像中的直线、圆和其他形状的算法。下面是二维霍夫变换的步骤:

  1. 将图像转换为二值图像,即将图像中的像素值转换为0或1,其中1表示图像中的目标物体。

  2. 对于每个目标像素,计算其在参数空间中的曲线或点。对于直线检测,曲线可以表示为y = mx + b的形式,其中m和b是直线的斜率和截距。对于圆检测,曲线可以表示为(x - a)^2 + (y - b)^2 = r^2的形式,其中(a, b)是圆心坐标,r是半径。

  3. 在参数空间中查找共线或共圆的曲线或点。对于直线检测,共线的曲线在参数空间中会形成一个点,因为它们共享相同的斜率和截距。对于圆检测,共圆的曲线在参数空间中会形成一个圆,因为它们共享相同的圆心和半径。

  4. 在参数空间中找到最大的点或圆,它们对应于图像中的最长直线或最大圆。

  5. 根据参数空间中的点或圆,绘制检测到的直线或圆。

二维霍夫变换在计算机视觉、图像处理、模式识别等领域有广泛的应用。


role::user
如何做三维的霍夫变换


role::assistant

三维霍夫变换(3D Hough Transform)是一种用于检测三维空间中的直线、平面和其他形状的算法。下面是三维霍夫变换的步骤:

  1. 将三维空间中的点转换为参数空间中的曲线或点。对于直线检测,曲线可以表示为x = at + b, y = ct + d, z = e*t + f的形式,其中(a, c, e)是直线的方向向量,(b, d, f)是直线的起点坐标,t是参数。对于平面检测,曲线可以表示为ax + by + cz + d = 0的形式,其中(a, b, c)是平面的法向量,d是平面的距离。

  2. 在参数空间中查找共线或共面的曲线或点。对于直线检测,共线的曲线在参数空间中会形成一个点,因为它们共享相同的方向向量和起点坐标。对于平面检测,共面的曲线在参数空间中会形成一个平面,因为它们共享相同的法向量和距离。

  3. 在参数空间中找到最大的点或平面,它们对应于三维空间中的最长直线或最大平面。

  4. 根据参数空间中的点或平面,绘制检测到的直线或平面。

三维霍夫变换在计算机视觉、机器人视觉、医学图像处理等领域有广泛的应用。例如,在机器人视觉中,可以使用三维霍夫变换来检测三维空间中的物体,从而实现机器人的自主定位和导航。在医学图像处理中,可以使用三维霍夫变


role::user
不要用matlab自带的函数,写一个二维霍夫变换的代码


role::assistant

以下是一个简单的Python代码实现二维霍夫变换:

import numpy as np
import cv2

# 读取图像
img = cv2.imread('image.jpg', 0)

# Canny边缘检测
edges = cv2.Canny(img, 50, 150, apertureSize=3)

# 霍夫变换
lines = []
theta_range = np.deg2rad(np.arange(-90, 90))  # 角度范围
cos_theta = np.cos(theta_range)
sin_theta = np.sin(theta_range)
h, w = edges.shape
for y in range(h):
    for x in range(w):
        if edges[y][x] > 0:
            for i in range(len(theta_range)):
                rho = x * cos_theta[i] + y * sin_theta[i]
                lines.append((rho, i))

# 统计直线数量
counts = np.zeros(len(theta_range))
for line in lines:
    counts[line[1]] += 1

# 取出前N条直线
N = 10
indices = np.argsort(-counts)[:N]
for index in indices:
    rho, theta = lines[index]
    a = np.cos(theta_range[theta])
    b = np.sin(theta_range[theta])
    x0 = a * rho
    y0 = b * rho
    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), 2)

# 显示结果
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

好的,以下是一个简单的Python实现,用于在图像中检测直线:

import numpy as np
import cv2

# 读取输入图像并转换为灰度图像
img = cv2.imread('input.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 设置霍夫变换参数(步长、角度范围等)
edges = cv2.Canny(gray, 50, 150)
lines = cv2.HoughLines(edges, rho=1, theta=np.pi/180, threshold=100)

# 在原始图像上绘制检测到的直线
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

cv.line(img,(x1,y1),(x2,y2),(255,255,255),3)

# 显示结果并保存输出图像
cv.imshow('output', img)
cv.imwrite('output.jpg', img)
cv.waitKey(0)

这段代码首先将输入图像转化为灰度图,并使用Canny边缘检测算法提取出边缘。然后通过调用HoughLines()函数进行霍夫变换,并设置了一些相关参数(例如rho和theta的步长、阈值等)。最后,遍历检测到的直线并在原始图像上绘制出来。


role::user

上述代码中,HoughLines是怎么实现的,可以帮我写一下吗


role::assistant

当然可以,以下是一个简单的Python实现,用于在图像中检测直线:

import numpy as np
import cv2

# 读取输入图像并转换为灰度图像
img = cv2.imread('input.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 设置霍夫变换参数(步长、角度范围等)
edges = cv2.Canny(gray, 50, 150)
lines = cv2.HoughLines(edges, rho=1, theta=np.pi/180, threshold=100)

# 在原始图像上绘制检测到的直线
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

cv.line(img,(x1,y1),(x2,y2),(255,255,255),3)

# 显示结果并保存输出图像
cv.imshow('output', img)
cv.imwrite('output.jpg', img)
cv.waitKey(0)

这段代码首先将输入图像转化为灰度图,并使用Canny边缘检测算法提取出边缘。然后通过调用HoughLines()函数进行霍夫变换,并设置了一些相关参数(例如rho和theta的步长、阈值等)。最后,遍历检测到的直线并在原始图像上绘制出来。


role::user

不是这个意思,我是说HoughLines这个函数是怎么写的,帮我写下这个函数


role::assistant

抱歉,我之前理解有误。cv2.HoughLines()函数是OpenCV库中提供的一个霍夫变换函数,用于在图像中检测直线。

以下是一个简单的Python实现:

def HoughLines(image, rho, theta, threshold):
    # 初始化累加器数组
    accumulator = np.zeros((180 // theta, np.sqrt(image.shape[0]**2 + image.shape[1]**2) // rho))

    # 遍历输入图像上所有非零点,并对应到极坐标空间上进行投票
    for y in range(image.shape[0]):
        for x in range(image.shape[1]):
            if image[y][x] > 0:
                for t_idx in range(accumulator.shape[0]):
                    t = (t_idx * theta) / 180.0 * np.pi
                    r = int(x * np.cos(t) + y * np.sin(t))
                    accumulator[t_idx][r] += 1

    # 根据阈值筛选出可能存在的直线(即累加器数组中大于等于阈值的位置)
    lines = []
    for t_idx in range(accumulator.shape[0]):
        for r_idx in range(accumulator.shape[1]):
            if accumulator[t_idx][r_idx] >= threshold:
                lines.append([rho*rho+t*t, t])

    return lines

这个函数接受四个参数:输入图像、rho和theta步长以及阈值。它首先初始化了一个二维数组作为累加器,并遍历输入图像上所有非零点,在极坐标空间上进行投票。然后,根据阈值筛选出可能存在的直线,并将它们存储在一个列表中返回。

需要注意的是,这个实现只考虑了图像中存在水平和竖直方向的直线。如果要检测任意角度的直线,则需要对累加器数组进行更复杂的处理。

标签:直线,变换,霍夫,rho,np,theta
From: https://www.cnblogs.com/CryCat/p/17362321.html

相关文章

  • halcon 仿射变换
    一、两点计算:刚体仿射变换1、vector_to_rigid:1)根据两个以上点对计算计算刚性仿射变换矩阵,支持旋转和平移2、vector_angle_to_rigid1)根据点和角度计算刚性仿射变换矩阵,支持旋转和平移 ......
  • 矩阵旋转,仿射变换
    importnumpyasnpimportmathasmdefRx(theta):returnnp.matrix([[1,0,0],[0,m.cos(theta),-m.sin(theta)],[0,m.sin(theta),m.cos(theta)]])defRy(theta):returnnp.matrix([[......
  • 【学习笔记】快速傅里叶变换
    怎么有人省选后才来学FFT啊由于时间原因,本篇笔记仅为个人总结,真正想要学习FFT的请参看这篇博客。前置知识单位根性质:$w_n^{2k}=w_{n/2}^k$$w_n^a+w_n^b=w_n^{a+b}$算法原理可知n+1个点可以唯一确定一条n次多项式,于是可以用n个点的点对集合表示一条曲线。......
  • 动作识别中的傅里叶变换
    数据收集与清洗最近的项目有一个需求是需要根据手机传感器的信息,对用户进行动作识别。动作识别是通过一系列用户动作的记录和环境状况的数据,判断用户的运动状态(motionactivity)。项目的需求仅限于根据数据判断用户的运动状态,如步行,跑步,驾车,骑车等。采集数据采用的手机中的加速......
  • 证明霍夫丁引理 Hoeffding Lemma
    马尔可夫不等式(Markov'sinequality)\(X\ge0\)为非负随机变量,\(t>0\)为常数,则有\[\begin{align*}\mathbbP(X\get)\le{\mathbbEX\overt}\end{align*}\]证:指示器函数\(I\lbraceA\rbrace=\begin{cases}1&\text{if}A\\0&\text{else}\end{cases}......
  • 变换编码的设计与实现
    访问【WRITE-BUG数字空间】_[内附完整源码和文档]一、实验目的采用dct变换,编制对图象进行变换的程序,图象采用8x8分快。对变换系数做Z型扫描,分别采用前2、3、5、8个和全部系数恢复原图象,观察结果,给出psnr值。对变换后系数做量化,量化表采用JPEG量化表,量化过程如下:,j)=C(i,j)/Q(i,j),其......
  • Halcon图像的 BLOB 分析处理几何变换 &刚性仿射变换
    平移move_region缩放zoom_region镜像mirror_region倒置transpose_region6.2仿射变换刚性仿射变换vector_angle_to_rigid对图像,区域进行仿射变换算子:vector_angle_to_rigid(:: Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)示例:vector_angle_......
  • 傅里叶变换学习资源与笔记
    傅里叶变换推荐视频傅里叶变换这样学,何愁不会呢?直观理解傅里叶变换傅里叶变换这样学,何愁不会呢?直观理解傅里叶变换推荐文章二维傅里叶变换是怎么进行的?-阿姆斯特朗的回答-知乎为什么要变换?如果学过线性代数,那么你一定知道空间变换与基变换,简单来说,一个问题在原来的......
  • Halcon区域集合运算及变换
     集合运算           将多个区域连接为一个区域:union1             算子:union1(Region : RegionUnion ::)             示例:union1(ConnectedRegions,RegionUnion)                   ConnectedRegio......
  • 基于小波变换的数据峰值检测matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:    2.算法涉及理论知识概要        小波变换(wavelettransform,WT)是一种新的变换分析方法,它继承和发展了短时傅立叶变换局部化的思想,同时又克服了窗口大小不随频率变化等缺点,能够提供一个随频率改变的“时间-频率”窗......