最近几天做了一些图像检测定位的工作,虽然老师否定了这一方法。但是还是想把最近的工作
总结总结。也许会对以后有所帮助。
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);
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实现部分后续有时间再完善。如果文中有纰漏或者不足之处,还望读
者匹配指正。
转载请注明作者:小刘