最近几天做了一些图像检测定位的工作,虽然老师否定了这一方法。但是还是想把最近的工作
总结总结。也许会对以后有所帮助。
POTDR_室外实验_20140120_160549TwoPoint2.mat
此文件为原始数据文件。我们需要将其转化为位图
进行分析处理。
部分matlab程序:
load POTDR_室外实验_20140120_160549TwoPoint2.mat %加载数据
Data=data(1:size(data,1),:); %Data两点扰动的矩阵数据388行*3472列
ColmStart=100; %因数据量太大,需要对列数据进行采样。从第100列开始取数据
ColmLag=10; %采样数据间隔,每隔10列采一列
VAR=[]; %定义一个空向量
ColmI=ColmStart:ColmLag:size(Data,2)-mod(size(Data,1),ColmLag)-ColmLag; %ColmI为具体对3472列中哪些列进行采样绘图为1*331的向量
NewData=Data(:,ColmI); %NewData为在原3472行数据中采样抽取出来的145列.388*331(原始采样图像数据)
DiffData=diff(NewData,1); %DiffData为对NewData作一阶差分运算的差分矩阵也是145列 388*331
imshow(DiffData),title('差分灰度图');
差分灰度图的边缘:(定位出红线的位置是本文的目标)
I=edge(DiffData,'sobel','vertical');%差分灰度图的边缘
imshow(I),title('差分灰度的边缘');
由于红色边缘并不突出,所以我们需要利用图像膨胀使边缘轮廓清晰.
膨胀matlab代码:
B=[ 0 1 0
1 1 1
0 1 0
];
A1=imdilate(I,B);%图像I被结构元素B膨胀
A2=imdilate(A1,B);
A3=imdilate(A2,B);
A4=imdilate(A3,B);
A5=imdilate(A4,B);
A6=imdilate(A5,B);
A7=imdilate(A6,B);
A8=imdilate(A7,B);
A9=imdilate(A8,B);
A10=imdilate(A9,B);
A11=imdilate(A10,B);
A12=imdilate(A11,B);
A13=imdilate(A12,B);
A14=imdilate(A13,B);
A15=imdilate(A14,B);
A16=imdilate(A15,B);
A17=imdilate(A16,B);
A18=imdilate(A17,B);
A19=imdilate(A18,B);
A20=imdilate(A19,B);
A21=imdilate(A20,B);
A22=imdilate(A21,B);
A23=imdilate(A22,B);
A24=imdilate(A23,B);
A25=imdilate(A24,B);
A26=imdilate(A25,B);
A27=imdilate(A26,B);
A28=imdilate(A27,B);
A29=imdilate(A28,B);
膨胀29次后的图像(红色边缘逐渐清晰):
imshow(A29);title('3*3第二十九次膨胀');
画出膨胀后的轮廓以便进行最终的红线定位:
LastPerim=bwperim(A29); %对膨胀29次的图像求轮廓
imshow(LastPerim),title('二十九次膨胀后的轮廓');
轮廓图如下:
轮廓逐渐清晰明了。
那么接下来我们如何检查出这两条红线的位置呢。
其实这里的原理很简单。
1.我们首先只保留图像中白线列信息。
比如p5=[17 17 17 17 17 17 17 18 18 18 18 18 18 19 19 19 19 19 19 19 20 20 21 21....... 22 22 23 23 24 24 25 25 25 25 25 25 26 26 26]
表明第17列有7个点,第18列有6个点依次类推
2.我们还需要了解这样的一个原理.
看图如下:
3.显然根据上图我们不难将x1和x3附近所以的列保留下来.保存至memlocate向量中.
matlab代码如下:
p=sparse(LastPerim);%对LastPerim求稀疏矩阵即只保留值为1的元素
p1=find(p); %按列索引,即找出稀疏矩阵的按列一维索引
p2=p1/388 %388为列数,此值为稀疏矩阵中保留位置的列值
p3=floor(p2) %对p2进行取整
p4=p3' %转置成一维行向量
len=length(p4)-1;
len=len-388; %减去最后一列边缘的388个数据点
calculate=0;
k=1;
p5=p4(:,1:len);
%%找出p4中连续五个以上相等的数存储在memlocate中
for i=1:1:len-4
if (p5(i)==p5(i+1)&&p5(i+1)==p5(i+2)&&p5(i+2)==p5(i+3))
calculate=calculate+1;
else
if(calculate>=3)
memlocate(k) = p5(i);
k=k+1;
calculate=0;
end
end
end
4.而此时我们只需要在memlocate中进行分类即可.
我们在这里用简单相邻列的差来区分x1和x3这两个不同的边缘.
如何差值等于1则表明是属于同一类。否则属于不同类。
这样便把不同类的列位置得到了,定位也随即完成.
此部分matlab代码如下:
%%对入侵点进行定位
p=1;
j=0;
for t=1:1:k-2
j=j+1;
if((memlocate(t+1)-memlocate(t))>=2)
fid=fopen('LocateResult15.txt','at+');
fprintf(fid,'The %d location is:%d\n',p,memlocate(t+1-j));
p=p+1;
j=0;
end
end
LocateResult.txt截图如下:
第一边缘列的位置在17列,第二边缘列的位置在254列.
定位成功!
我相信如果大家今后在工作中遇到类似的工作,那么一点能从这篇文章中获取一定的启发.
作者水平有限.至于VC实现部分后续有时间再完善。如果文中有纰漏或者不足之处,还望读
者匹配指正。
转载请注明作者:小刘