基于hough变换的平行线识别

2024-04-21 17:32
文章标签 识别 变换 hough 平行线

本文主要是介绍基于hough变换的平行线识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于hough变换的平行线识别

hough变换基本原理讲述

线段识别是识别图像中平行线的基础。但一张图像中所包含的线段几乎是无限的所以无法在图像中直接判断,因此引入Hough变换[32]。Hough变换的基础是建立极坐标空间用(ρ,θ)表示空间各点,并根据极坐标变换将图像中所有直线用空间各点(ρ,θ)表示。根据直线在极坐标系与直角坐标系间转换关系得式(1)。
ρ=xcos⁡θ+ysin⁡θ (1)
式中ρ为原点到该直线的垂直距离;θ为垂线与x轴的夹角。
Hough变换后得出极坐标空间与图像空间满足下述关系:(1) 极坐标空间中任意点(ρ, θ)都代表图像空间中的一条直线并将此直线记作l((ρ,θ));(2) 图像空间中任意点(x, y)对应于极坐标空间中一条三角函数线。
在这里插入图片描述

程序编写

- 程序实现步骤

在程序编写过程中将总体流程分为三部分:图像边缘线检测、线段检测与平行线检测。在图像边缘线检测中根据灰度梯度的变化情况,利用sobel算子完成边缘线检测;线段检测中利用Hough变换,识别边缘线中的线段,并输出所识别线段的角度和极径参数;在平行线检测过程中,根据平行线的几何特征制定线段组夹角、距离以及间距3种判定条件完成平行线判断,并识别程序流程图如下图所示。
在这里插入图片描述

程序代码

clc;
clear;
iceThickness=0;
%%   图片的读入与裁剪
f=imread('C:\Users\huawei\Desktop\海冰识别\前期过程\所识别图片\dachuang1.png');
%f=imcrop(f,[900,760,200,300]);  %裁剪图片
% f=imcrop(f,[670,0,689,817]);  %裁剪图片
% f=imcrop(f,[890,0,689,817]);  %裁剪图片
f=imcrop(f,[850,710,400,400]);
figure(10)
imshow(f);
%%   判断参数的定义
%角度----------------------------------- 2
theta_chazhi=3;
%两线间距离(极坐标下 )---------------- 70~15
distance_max=70;
distance_min=15;
%端点距离 ---------------------------- -10~25
boundray_point_distance_max=15;
boundray_point_distance_min=-15;
%中点距离----------------------------- -10~20
middle_point_distance_max=20;
middle_point_distance_min=-10;
%平行条件判断---------------------------- 13
parallel_judge=10;
%两线间距离(直角坐标系下)-------------- 10~100
xy_distance_max=100;
xy_distance_min=10;
%直线本身长度----------------------------- 25    
length_min=25;
%两线长度差值--------------------------- 0.25~2.5
length_ratio_max=2;
length_ratio_min=0.5;%%   输出值预定义
iceThickness=0;
iceParameter.k_1=0;
iceParameter.k_2=0;
iceParameter.b_1=0;
iceParameter.b_2=0;
iceParameter.start_1=[0,0];
iceParameter.start_2=[0,0];
iceParameter.end_1=[0,0];
iceParameter.end_2=[0,0];%%   从视频中读入图片
% video=VideoReader('C:\Users\86132\Desktop\大创\20171203(1).mp4');      %读取MP4文件
% nFrames=video.NumberOfFrames;     %从视频中读取视频的总帧数
% n=round((nFrames-10)/25);
% im=cell(1,n);
% for k=1:n
%     m1=read(video,25*k);%读取第k帧,存入im中
%     im{k}=im2double(m1);%将图片存入元胞im,
% end
% f=imcrop(im{14},[850,0,689,817]);% figNames=struct2cell(dir('C:\Users\86132\Desktop\大创\截图\*.jpg'));
% [~,len]=size(figNames);
% for i=1:len
%     name=figNames{1,i};
% end
% f=imread(['C:\Users\86132\Desktop\大创\所识别图片\',name]);
% f=imcrop(f,[870,0,689,817]);  %裁剪图片%%   图像的基本处理
I=rgb2gray(f);     %进行灰度化% imshow(I),title('原图I');
% figure (1)
% imshow(I),title('裁剪图');se=strel('disk',20);%disk指定构建一个圆形的结构体,第二个参数指定结构体的半径
%接下来,进行基于重建的开操作。使用imerode和imreconstruct函数实现
Ie=imerode(I, se);%先腐蚀‘erosion’
Iobr=imreconstruct(Ie, I);%再重建% figure(10)
% imshow(Iobr);Iobrd=imdilate(Iobr, se);%在基于重建的开操作的结果基础上,进行腐蚀
Iobrcbr=imreconstruct(imcomplement(Iobrd), imcomplement(Iobr));%重建,标记图像为腐蚀后图像取补,模板为腐蚀前原图取补。
Iobrcbr=imcomplement(Iobrcbr);%重建结果再取补,得到实际基于重建的闭操作的结果。% figure(2)
% imshow(Iobrcbr),title('基本图像处理后所得图形');%%   图像的边缘检测
BW=edge(Iobrcbr,'sobel');
% figure(3);
% imshow(BW),title('边缘图');%%   图像中的直线检测
[x,y]=size(BW);
[H,T,R]=hough(BW,'RhoResolution',1,'Theta',-90:1:89.5);      %Hough变换
P=houghpeaks(H,10,'threshold',ceil(0.05*max(H(:))));   %查找Hough峰值
lines1=houghlines(BW,T,R,P,'FillGap',15,'MinLength',20);
L=0;
for k=1:length(lines1)
%     if lines1(k).theta<=45&&lines1(k).theta>=-45L=L+1;Lines(L).point1=lines1(k).point1;Lines(L).point2=lines1(k).point2;Lines(L).theta=lines1(k).theta;Lines(L).rho=lines1(k).rho;
%     end
end
figure(4),imshow(BW,[]),title('直线检测图');
hold on
n=length(Lines);
for i=1:nfor j=1:3color(i,j)=rand(1);end
end
for k=1:length(Lines)xy=[Lines(k).point1;Lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'color',color(k,:));
endif (L)==0return;
end
for i=1:length(Lines)A(i)=Lines(i).theta;       %A代表角度B(i)=Lines(i).rho;         %B代表极径长度x1y1(i,1:2)=Lines(i).point1;   %x1y1代表起始点的坐标x2y2(i,1:2)=Lines(i).point2;   %x2y2代表终止点的坐标
end
%合并相同的直线的不同线段
o=1;h(1:length(A))=0;
A1(1)=A(1);B1(1)=B(1);
X1Y1(1,1:2)=x1y1(1,1:2);
X2Y2(1,1:2)=x2y2(1,1:2);
for i=2:length(A)z=A(i)-A(i-1);l=B(i)-B(i-1);if (z~=0||l~=0)o=o+1;elseh(o)=h(o)+1;  %记录相同直线的个数endA1(o)=A(i);   %A1代表角度B1(o)=B(i);   %B1代表极径长度
end
z(1:17)=0;
same_number(1:length(A1))=h(1:length(A1))+1;o=0; %用same_number来接收相同直线的个数
for i=1:length(same_number)xy1(1:same_number(i),1:2)=x1y1((1+o):(same_number(i)+o),1:2);xy1(same_number(i)+1:2*same_number(i),1:2)=x2y2((1+o):(same_number(i)+o),1:2); %记录同一下直线上的所有点if A1(i)~=0for k=1:2*same_number(i)z=0;for j=1:2*same_number(i)if xy1(k,1)>=xy1(j,1)z=z+1;endendif z==2*same_number(i)X1Y1(i,1:2)=xy1(k,1:2);endendfor k=1:2*same_number(i)z=0;for j=1:2*same_number(i)if xy1(k,1)<=xy1(j,1)z=z+1;endendif z==2*same_number(i)X2Y2(i,1:2)=xy1(k,1:2);endendendif A1(i)==0for k=1:2*same_number(i)z=0;for j=1:2*same_number(i)if xy1(k,2)>=xy1(j,2)z=z+1;endendif z==2*same_number(i)X1Y1(i,1:2)=xy1(k,1:2);endendfor k=1:2*same_number(i)z=0;for j=1:2*same_number(i)if xy1(k,2)<=xy1(j,2)z=z+1;endendif z==2*same_number(i)X2Y2(i,1:2)=xy1(k,1:2);endendendo=o+same_number(i);
end%%   坐标转换for i=1:size(A1,2)if A1(i)>=0&&A1(i)<=90K(i)=tan((90-A1(i))*(pi/180));  %k_lines表示直线在直角坐标系中的斜率endif A1(i)>=-90&&A1(i)<0K(i)=tan((-90-A1(i))*(pi/180));endend%利用中点和上一个循环得到的斜率计算两直线之间的平均距离for i=1:size(A1,2)Middle(i,1)=0.5*(X1Y1(i,1)+X2Y2(i,1));Middle(i,2)=0.5*(X1Y1(i,2)+X2Y2(i,2));B(i)=Middle(i,2)-K(i)*Middle(i,1);  %b_lines代表直线的截距endfor u=1%% 判断条件1:利用角度差值初步判断两线是否平行%查找并记录近似平行的直线o=0;for i=1:length(A1)for j=i+1:length(A1)if abs(A1(i)-A1(j))<=theta_chazhi&&A1(i)>=-5&&A1(i)<=60    %根据角度的差异大小,以及角度本身的大小进行判断  o=o+1;paralleltheta_number(o,1:2)=[i,j];endendendif o==0break;endf=0;for i=1:size(paralleltheta_number,1)distance(i)=abs(B1(paralleltheta_number(i,1))-B1(paralleltheta_number(i,2)));   %计算线段之间的距离if distance(i)<=distance_max&&distance(i)>=distance_minf=f+1;Paralleltheta_number(f,1:2)=paralleltheta_number(i,1:2);endendif f==0break;end%%   判断条件2:用两条线段间的距离判断for i=1:size(Paralleltheta_number,1)a(1:2)=X1Y1(Paralleltheta_number(i,1),1:2);b(1:2)=X2Y2(Paralleltheta_number(i,1),1:2);c(1:2)=X1Y1(Paralleltheta_number(i,2),1:2);d(1:2)=X2Y2(Paralleltheta_number(i,2),1:2);middle(i,1)=0.5*(a(1)+b(1));middle(i,2)=0.5*(a(2)+b(2));middle_2(i,1)=0.5*(c(1)+d(1));middle_2(i,2)=0.5*(c(2)+d(2));point_distance(1,i)=sqrt((middle(i,1)-middle_2(i,1))^2+(middle(i,2)-middle_2(i,2))^2);  %每一对平行线的中点距离point_distance(2,i)=sqrt((a(1)-c(1))^2+(a(2)-c(2))^2);point_distance(3,i)=sqrt((b(1)-d(1))^2+(b(2)-d(2))^2);endp=0;            for i=1:size(Paralleltheta_number,1)e(i)=abs(B1(Paralleltheta_number(i,1))-B1(Paralleltheta_number(i,2)));panduan(1:3,i)=point_distance(1:3,i)-e(i);    %线段距离和中点以及端点的距离差值大小if (panduan(1,i)<=middle_point_distance_max&&panduan(1,i)>=middle_point_distance_min)||(panduan(2,i)<=boundray_point_distance_max&&panduan(2,i)>=boundray_point_distance_min)||(panduan(3,i)<=boundray_point_distance_max&&panduan(3,i)>=boundray_point_distance_min)p=p+1;Paralleltheta_number2(p,1:2)=Paralleltheta_number(i,1:2);endendif p==0break;end%% 判断条件3:判断两条直线是否有相交的情况%将线段参数中的角度theta转化为斜率k_linesfor i=1:size(Paralleltheta_number2,1)theta(i,1)=A1(Paralleltheta_number2(i,1));theta(i,2)=A1(Paralleltheta_number2(i,2));for j=1:2if theta(i,j)>=0&&theta(i,j)<=90k_lines(i,j)=tan((90-theta(i,j))*(pi/180));  %k_lines表示直线在直角坐标系中的斜率endif theta(i,j)>=-90&&theta(i,j)<0k_lines(i,j)=tan((-90-theta(i,j))*(pi/180));endendend%利用中点和上一个循环得到的斜率计算两直线之间的平均距离for i=1:size(k_lines,1)k_merge(i,1)=0.5*(k_lines(i,1)+k_lines(i,2));a(1:2)=X1Y1(Paralleltheta_number2(i,1),1:2);b(1:2)=X2Y2(Paralleltheta_number2(i,1),1:2);c(1:2)=X1Y1(Paralleltheta_number2(i,2),1:2);d(1:2)=X2Y2(Paralleltheta_number2(i,2),1:2);middle(i,1)=0.5*(a(1)+b(1));middle(i,2)=0.5*(a(2)+b(2));middle_2(i,1)=0.5*(c(1)+d(1));middle_2(i,2)=0.5*(c(2)+d(2));b_lines(i,1)=middle(i,2)-k_merge(i,1)*middle(i,1);  %b_lines代表直线的截距b_lines(i,2)=middle_2(i,2)-k_merge(i,1)*middle_2(i,1);b_distance(i,1)=(abs(b_lines(i,1)-b_lines(i,2))/sqrt(1+k_merge(i,1)^2));  %b_distance表示由虚设斜率所得两直线之间的平均距离endo=0;for i=1:size(Paralleltheta_number2,1)judge(i,1)=abs(b_distance(i,1)-abs(B1(Paralleltheta_number2(i,1))-B1(Paralleltheta_number2(i,2))));if (judge(i,1)<=parallel_judge)&&(b_distance(i,1)>=xy_distance_min)&&(b_distance(i,1)<=xy_distance_max)  %平行线判断标准o=o+1;Paralleltheta_number3(o,1:2)=Paralleltheta_number2(i,1:2);ice_thickness1(o)=b_distance(i);endendif o==1     %如果经过判断的直线组只剩下一个那么就直接输出此时的直线结果end%% 判断条件4:判断直线自身长度,以及两直线差值是否满足要求Q=0;for i=1:size(Paralleltheta_number3,1)a(1:2)=X1Y1(Paralleltheta_number3(i,1),1:2);%线段1起始点b(1:2)=X2Y2(Paralleltheta_number3(i,1),1:2);%线段1终止点c(1:2)=X1Y1(Paralleltheta_number3(i,2),1:2);%线段2起始点d(1:2)=X2Y2(Paralleltheta_number3(i,2),1:2);%线段2终止点self_distance(i,1)=sqrt((a(1)-b(1))^2+(a(2)-b(2))^2)+1;self_distance(i,2)=sqrt((c(1)-d(1))^2+(c(2)-d(2))^2)+1;self_distance_panduan(i)=abs(self_distance(i,1)/self_distance(i,2));if (self_distance(i,1)>length_min&&self_distance(i,2)>length_min)&&(self_distance_panduan(i)<length_ratio_max&&self_distance_panduan(i)>length_ratio_min)Q=Q+1;Paralleltheta_number4(Q,1:2)=Paralleltheta_number3(i,1:2);ice_thickness2(Q)=ice_thickness1(i);endend%如果经过判断的直线组只剩下一个那么就直接输出此时的直线结果if Q~=0end   
end

这篇关于基于hough变换的平行线识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/923649

相关文章

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i

Clion不识别C代码或者无法跳转C语言项目怎么办?

如果是中文会显示: 此时只需要右击项目,或者你的源代码目录,将这个项目或者源码目录标记为项目源和头文件即可。 英文如下:

BERN2(生物医学领域)命名实体识别与命名规范化工具

BERN2: an advanced neural biomedical named entity recognition and normalization tool 《Bioinformatics》2022 1 摘要 NER和NEN:在生物医学自然语言处理中,NER和NEN是关键任务,它们使得从生物医学文献中自动提取实体(如疾病和药物)成为可能。 BERN2:BERN2是一个工具,

行为智能识别摄像机

行为智能识别摄像机 是一种结合了人工智能技术和监控摄像技术的先进设备,它能够通过深度学习算法对监控画面进行实时分析,自动识别和分析监控画面中的各种行为动作。这种摄像机在安防领域有着广泛的应用,可以帮助监控人员及时发现异常行为,并采取相应的措施。 行为智能识别摄像机可以有效预防盗窃事件。在商场、超市等公共场所安装这种摄像机,可以通过识别异常行为等情况,及时报警并阻止不安全行为的发生

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题 GitHub Pages是一个直接从GitHub存储库托管的静态站点服务,‌它允许用户通过简单的配置,‌将个人的代码项目转化为一个可以在线访问的网站。‌这里使用flutter build web来构建web发布到GitHub Pages。 最近通过flutter build web,通过发布到GitHu

T1打卡——mnist手写数字识别

🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 1.定义GPU import tensorflow as tfgpus=tf.config.list_physical_devices("GPU")if gpus:gpu0=gpus[0]tf.config.experimental.set_memort_groth(gpu0,True) #设置GPU现存用量按需

使用 VisionTransformer(VIT) FineTune 训练驾驶员行为状态识别模型

一、VisionTransformer(VIT) 介绍 大模型已经成为人工智能领域的热门话题。在这股热潮中,大模型的核心结构 Transformer 也再次脱颖而出证明了其强大的能力和广泛的应用前景。Transformer 自 2017年由Google提出以来,便在NLP领域掀起了一场革命。相较于传统的循环神经网络(RNN)和长短时记忆网络(LSTM), Transformer 凭借自注意力机制

T7:咖啡豆识别

T7:咖啡豆识别 **一、前期工作**1.设置GPU,导入库2.导入数据3.查看数据 **二、数据预处理**1.加载数据2.可视化数据3.配置数据集 **三、构建CNN网络模型**1、手动搭建2、直接调用官方模型 **四、编译模型****五、训练模型****六、模型评估****七、预测**八、暂时总结 🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K

mysql无法启动以及cmd下mysql命令无法识别的

1.mysql无法启动 解决方式: Win+R,输入services.msc,找到mysql服务 即默认的服务名是mysql55而不是mysql 2.mysql命令无法识别 直接输入mysql进入数据库报错 这是因为系统并不知道mysql是什么,我们需要在环境变量里添加mysql的安装地址中的bin目录地址。 C:\Program Files\My