Matlab论坛
直播中

乂乂统天下

6年用户 162经验值
擅长:可编程逻辑 测量仪表 嵌入式技术
私信 关注
[资料]

MATLAB图像处理实现直线识别

`新手学习,互相交流,多多关照
处理效果如下图所示:

NO.1原始图像:


NO.2预处理:
result2=图像预处理
NO.3分割为9宫格 各子块单独分析:
result3=分割为9宫格 各子块单独分析
NO.4各子块拟合得到的直线的k、b值:
result4=各子块拟合得到的直线的k、b值
NO.5结果标记:
result5=结果标记
源码下载地址:https://www.lanzous.com/iajjk8b
密码:acak  

这是主程序:
  1. % 功能:matlab图像处理实现直线识别(拟合角平分线)
  2. % 说明:此程序可直接运行
  3. % 运行前请确保子程序文件zikuai.m存在

  4. %第1步
  5. close all
  6. I=imread('1.jpg'); % 读取图像
  7. figure
  8. imshow(I) % 显示原始图像
  9. I=rgb2gray(I); % 彩色图像转换成灰度图

  10. % I=im2bw(I); % 二值化
  11. I=edge(double(I)); % 检测图像的边缘
  12. figure
  13. imshow(I) % 显示边缘检测的结果

  14. %第2步
  15. [m,n]=size(I); %计算图像的尺寸

  16. M=3; %定义X方向分割的块数
  17. N=3; %定义Y方向分割的块数
  18. mm=floor(m/M); %子块行的长度
  19. nn=floor(n/N); %子块列的长度
  20. count=1; %计数器
  21. figure
  22. for i=1:M
  23. for j=1:N
  24. A=I((i-1)*mm+1:i*mm,(j-1)*nn+1:j*nn); %分割原图像,得到一个子块
  25. subplot(M,N,count)
  26. imshow(A) %显示一个子块
  27. zuoshangjiao=[(i-1)*mm+1 (j-1)*nn+1]; %子块左上角的坐标
  28. [x,y,k,b]=zikuai(A,zuoshangjiao); %得到子块里白色像素点拟合得到的直线的斜率k和截距b(调用zikuai函数)
  29. X{count}=x; %保存子块里所有白色像素的x坐标
  30. Y{count}=y; %保存子块里所有白色像素的y坐标
  31. K(count)=k; %保存子块里拟合得到的直线的斜率k
  32. B(count)=b; %保存子块里拟合得到的直线的截距b
  33. count=count+1; %计数器加1,进行下一个子块的计算
  34. end
  35. end

  36. %第3步
  37. KK=K(~isnan(K)); %去掉K中的NaN(白色像素点少于10的子块)
  38. BB=B(~isnan(B)); %去掉B中的NaN(白色像素点少于10的子块)

  39. mean_K=mean(KK); %求所有斜率的平均值
  40. mean_B=mean(BB); %求所有截距的平均值

  41. figure
  42. subplot(2,1,1)
  43. plot(KK,'-o')
  44. title('各子块拟合得到的直线k值')
  45. subplot(2,1,2)
  46. plot(BB,'-o')
  47. title('各子块拟合得到的直线b值')

  48. count1=1;
  49. count2=1;
  50. for i=1:length(K)
  51. if ~isnan(K(i))
  52. if K(i)>mean_K %大于斜率平均值的子块,将这些子块的白色像素点位置集合到cell型数组X1和Y1(分别存x和y)
  53. X1{count1}=X{i};
  54. Y1{count1}=Y{i};
  55. count1=count1+1;
  56. else %小于斜率平均值的子块,将这些子块的白色像素点位置集合到cell型数组X2和Y2(分别存x和y)
  57. X2{count2}=X{i};
  58. Y2{count2}=Y{i};
  59. count2=count2+1;
  60. end
  61. end
  62. end

  63. XX1=[];
  64. YY1=[];
  65. XX2=[];
  66. YY2=[];

  67. for i=1:length(X1) %大于斜率平均值的子块,将这些子块的白色像素点位置集合到double型数组里,方便计算
  68. XX1=[XX1;X1{i}];
  69. YY1=[YY1;Y1{i}];
  70. end

  71. for i=1:length(X2) %小于斜率平均值的子块,将这些子块的白色像素点位置集合到double型数组里,方便计算
  72. XX2=[XX2;X2{i}];
  73. YY2=[YY2;Y2{i}];
  74. end

  75. %%%%%直线1和直线2被从图像里提取出来了分别为XX1,YY1和XX2,YY2
  76. %离散点拟合得到直线1的斜率k1和截距b1
  77. A1=[XX1,ones(length(XX1),1)];
  78. kb1=A1YY1;
  79. k1=kb1(1);
  80. b1=kb1(2);

  81. %离散点拟合得到直线2的斜率k2和截距b2
  82. A2=[XX2,ones(length(XX2),1)];
  83. kb2=A2YY2;
  84. k2=kb2(1);
  85. b2=kb2(2);

  86. xx0=[1 m];
  87. yy0=[1 n];

  88. yy1=k1*xx0+b1; %得到直线1上的两点,以便绘制直线1
  89. yy2=k2*xx0+b2; %得到直线3上的两点,以便绘制直线2

  90. %%%%绘制拟合得到的直线和分离出来的离散点
  91. %直线1
  92. figure
  93. axis([1,m,1,n]) %设定显示范围
  94. hold on
  95. scatter(XX1,YY1,'LineWidth',5) %绘制直线1对应的白色像素位置
  96. plot(xx0,yy1,'r','LineWidth',3) %绘制拟合到的直线1

  97. %直线2
  98. hold on
  99. scatter(XX2,YY2,'k','LineWidth',5) %绘制直线2对应的白色像素位置
  100. plot(xx0,yy2,'y','LineWidth',3) %绘制拟合到的直线2


  101. %第4步

  102. %求两条直线的交点
  103. X0=(b2-b1)/(k1-k2);
  104. Y0=k1*X0+b1;

  105. alpha=atan(k1); %直线1与x夹角
  106. beta=atan(k2); %直线2与x夹角

  107. K01=tan((alpha+beta)/2); %角平分线1的斜率
  108. K02=tan(-pi/2+(alpha+beta)/2); %角平分线2的斜率

  109. B01=Y0-K01*X0; %角平分线1的截距
  110. B02=Y0-K02*X0; %角平分线2的截距

  111. %绘制角平分线
  112. xx0=[1 m];
  113. yy0=[1 n];

  114. YY1=K01*xx0+B01; %角平分线1
  115. YY2=K02*xx0+B02; %角平分线2
  116. plot(xx0,YY1); %绘制角平分线1
  117. plot(xx0,YY2); %绘制角平分线2

  118. view([90 90])
这是主程序所调用的子程序:
  1. % 此程序为子函数,请直接运行chengxu.m
  2. function [x,y,k,b]=zikuai(feikuai,zuoshangjiao)
  3. %求每个子块数据拟合出来的直线y=kx+b,返回k和b,以及子块里白色像素点的坐标
  4. x0=zuoshangjiao(1);     %得到子块的左上角x坐标
  5. y0=zuoshangjiao(2);     %得到子块的左上角y坐标

  6. [m,n]=size(feikuai);    %计算子块的大小
  7. N=1;                    %N从1开始计数
  8. x=[];                   %定义子块白色像素x坐标保存的向量x
  9. y=[];                   %定义子块白色像素y坐标保存的向量y
  10. for i=1:m               %依次扫描子块各个点的像素值
  11.     for j=1:n
  12.         if feikuai(i,j)==1  %如果是白色像素,保存该像素的坐标
  13.             x(N)=i;     %保存相对坐标(x方向)
  14.             y(N)=j;     %保存相对坐标(y方向)
  15.             N=N+1;      %计数加1,判断下一个像素
  16.         end
  17.     end
  18. end

  19. if length(x)<10   %少于10个白色像素的子块(包括没有白点的子块),舍弃掉(点数太少,可能是噪声)
  20.     k=NaN;        %将k b x y 赋值NaN(Matlab系统变量,表示Not a Number),以示与其他子块的区别
  21.     b=NaN;
  22.     x=NaN;
  23.     y=NaN;
  24.     return       %返回
  25. else             %子块白色像素点个数大于等于10,对白色像素点的坐标进行拟合,得到直线的斜率k和截距b
  26.     x=x+x0;      %得到子块内白色像素点相对于原图像的绝对坐标x
  27.     y=y+y0;      %得到子块内白色像素点相对于原图像的绝对坐标y
  28.     x=x';
  29.     A=[x,ones(length(x),1)];    %定义矩阵A(直线拟合就是解超越线性方程组的最小二乘解,未知数为k和b)即A*[k;b]=y';
  30.     y=y';
  31.     kb=Ay;                     %得到最小二乘解,对应k和b     
  32.     k=kb(1);                    %得到k
  33.     b=kb(2);                    %得到b
  34. end

  35. end

  36.             




` result1=原始图像

回帖(1)

刘超

2020-3-25 14:17:01
很好的学习分享
1 2 举报

更多回帖

发帖
×
20
完善资料,
赚取积分