用MATLAB实现对运动物体识别与跟踪

时间:2024-10-25 16:43:57

不得不说MATLAB的图像处理函数有点多,但速度有时也是出奇的慢。还是想c的指针,虽然有点危险,但速度那是杠杠的。
第二个MATLAB程序,对运动物体的识别与追踪。
这里我们主要运用帧差法实现运动物体与背景图像的分离,由于视频中的物体较为简单,我们只对两帧图像取帧差(也是为了提高速度)
对于运动物体的提取我们运用了MATLAB里自带的函数bwareaopen
bwareaopen(src,int),src为二值图像,int为设置的联通域的大小,是对帧差法,在转化为二值的图像进行操作,结果是将大小小于设定的int的连通域置为0;
对于第一帧与第二帧图像运动物体的坐标的提取我们用了自带的regionprops函数
regionprops(src,’‘)其中src为传入的二值图像,’‘内的为你所需要的属性
具体属性可以查看MATLAB的help
这里写图片描述
这里我们选用了其中的Centroid属性,返回的时连通域的质心坐标,注返回的第一个值为横坐标,第二个值为纵坐标~
对于运动物体的追踪我们用了质心追踪,
在第一二三两帧的帧间差的运动物体的质心求出来后,将质心做差得到的向量预测下一帧间差运动物体可能到达的位置,接下来在对这个位置进行局部的找质心,再做差如此循环。
追踪大致如图(画的不好):
这里写图片描述
这个相对与全局再次进行bwareaopen,regionprops,速度应该会快一下,而且这是进行局部地搜索所以可以减小背景,或其他噪声的影响。
这里写图片描述
如图为直接进行帧间差分后的转化的二值图像,即使噪声很大用局部追踪也能跟上。
具体代码:

  1. yuandian=zeros(2,2);
  2. i=1293;
  3. filename1 = strcat('I:\2d3d\2\dxshiyan2\C',num2str(i),'.jpg');
  4. src1=imread('');
  5. src2=imread('');
  6. %src1=rgb2gray(src1);
  7. %src2=rgb2gray(src2);
  8. zhic1=src2-src1;
  9. zhic1=im2bw(zhic1,0.2);
  10. imshow(zhic1);
  11. zhic2= bwareaopen(zhic1,3000);
  12. imshow(zhic2);
  13. quyu=regionprops(zhic2,'Centroid');
  14. [u,v]=zhixin(zhic2,int16((2)),int16((1)));
  15. yuandian(1,1)=u;
  16. yuandian(1,2)=v;
  17. %去一个模板为400*400;
  18. src1=src2;
  19. src2=imread('');
  20. %src2=rgb2gray(src2);
  21. zhic2=src2-src1;
  22. zhic1=im2bw(zhic2,0.2);
  23. zhic2= bwareaopen(zhic1,3000);
  24. imshow(zhic2);
  25. quyu=regionprops(zhic2,'Centroid');
  26. [u,v]=zhixin(zhic2,int16((2)),int16((1)));
  27. yuandian(2,1)=u;
  28. yuandian(2,2)=v;
  29. for i=1294:1386
  30. filename1 = strcat('I:\2d3d\2\dxshiyan2\C',num2str(i),'.jpg');
  31. src1=src2;
  32. src2=imread(filename1);
  33. src3=src2;
  34. zhic2=src2-src1;
  35. zhic2=im2bw(zhic2,0.2);
  36. imshow(zhic2);
  37. houx=2*yuandian(2,2)-yuandian(1,2);
  38. houy=2*yuandian(2,1)-yuandian(1,1);
  39. [u,v]=zhixin(zhic2,houy,houx);
  40. [state,result]=draw_rect(src3,[v-250,u-250],[500,500],0);
  41. %imshow(result);
  42. pause(0.01);
  43. yuandian(1,1)=yuandian(2,1);
  44. yuandian(1,2)=yuandian(2,2);
  45. if(abs(yuandian(1,1)-u<400)&&abs(yuandian(1,2)-v<400))
  46. yuandian(2,1)=u;
  47. yuandian(2,2)=v;
  48. end
  49. end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

fanction:

  1. %找质心
  2. function [u,v]=zhixin(erzhi,y,x)
  3. u=0;
  4. v=0;
  5. zuobiaox=0;
  6. zuobiaoy=0;
  7. number=0;
  8. jilux=0;
  9. jiluy=0;
  10. for i=y-200:y+200
  11. for j=x-200:x+200
  12. if(j<3839)
  13. if(erzhi(i,j)==1)
  14. number=number+1;
  15. u=(int64(i)+int64(u));
  16. v=(int64(j)+int64(v));
  17. zuobiaox=zuobiaox+double(erzhi(i,j));
  18. zuobiaoy=double(erzhi(i,j))+zuobiaoy;
  19. jilux=int64(jilux)+int64(j);
  20. jiluy=int64(jiluy)+int64(i);
  21. end
  22. end
  23. end
  24. end
  25. u=int64(u/zuobiaoy);
  26. %p=jilux/int64(number)-u;
  27. v=int64(v/zuobiaox);
  28. %q=jiluy/int64(number)-v;
  29. %k=0;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

draw-rect

  1. function [state,result]=draw_rect(img,startPosition,windowSize,showOrNot)
  2. % 函数调用:[state,result]=draw_rect(img,startPosition,windowSize,showOrNot)
  3. % 函数功能:在图像画个长方形框
  4. % 函数输入:img为原始的大图,可为灰度图,可为彩色图
  5. % startPosition 框的左上角在大图中的坐标(每行代表x,y坐标),startPosition=[10,30],分别表示x,y为10,30
  6. % windowSize 框的大小 windowSize=[112,92] 分别表示宽、高
  7. % showOrNot 是否要显示结果?默认为显示出来?
  8. % 函数输出:state -- 表示程序结果状态?
  9. % result - 结果图像数据
  10. if nargin < 4
  11. showOrNot = 1;
  12. end
  13. rgb = [255 0 0]; % 边框颜色
  14. lineSize = 3; % 边框大小,取1,2,3
  15. windowSize(1,1)=windowSize(1,1);
  16. windowSize(1,2) = windowSize(1,2);
  17. if windowSize(1,2) > size(img,1) ||...
  18. windowSize(1,1) > size(img,2)
  19. state = -1; % 说明窗口太大,图像太小,
  20. disp('the window size is larger then image...');
  21. return;
  22. end
  23. result = img;
  24. if size(img,3) == 3
  25. for k=1:3
  26. for i=1:size(startPosition,1) %矩形框的总数
  27. if(startPosition(i,1)>=0 && startPosition(i,2)>=0)
  28. result(startPosition(i,2),startPosition(i,1):startPosition(i,1)+windowSize(i,1),k) = rgb(1,k); %画上边框
  29. result(startPosition(i,2):startPosition(i,2)+windowSize(i,2),startPosition(i,1)+windowSize(i,1),k) = rgb(1,k);%画右边框
  30. result(startPosition(i,2)+windowSize(i,2),startPosition(i,1):startPosition(i,1)+windowSize(i,1),k) = rgb(1,k); %画下边框
  31. result(startPosition(i,2):startPosition(i,2)+windowSize(i,2),startPosition(i,1),k) = rgb(1,k); %画左边框
  32. if lineSize == 2 || lineSize == 3
  33. result(startPosition(i,2)+1,startPosition(i,1):startPosition(i,1)+windowSize(i,1),k) = rgb(1,k);
  34. result(startPosition(i,2):startPosition(i,2)+windowSize(i,2),startPosition(i,1)+windowSize(i,1)-1,k) = rgb(1,k);
  35. result(startPosition(i,2)+windowSize(i,2)-1,startPosition(i,1):startPosition(i,1)+windowSize(i,1),k) = rgb(1,k);
  36. result(startPosition(i,2):startPosition(i,2)+windowSize(i,2),startPosition(i,1)-1,k) = rgb(1,k);
  37. if lineSize == 3
  38. result(startPosition(i,2)-1,startPosition(i,1):startPosition(i,1)+windowSize(i,1),k) = rgb(1,k);
  39. result(startPosition(i,2):startPosition(i,2)+windowSize(i,2),startPosition(i,1)+windowSize(i,1)+1,k) = rgb(1,k);
  40. result(startPosition(i,2)+windowSize(i,2)+1,startPosition(i,1):startPosition(i,1)+windowSize(i,1),k) = rgb(1,k);
  41. result(startPosition(i,2):startPosition(i,2)+windowSize(i,2),startPosition(i,1)+1,k) = rgb(1,k);
  42. end
  43. end
  44. end
  45. end
  46. end
  47. end
  48. state = 1;
  49. if showOrNot == 1
  50. figure;
  51. hold on;
  52. imshow(result);
  53. end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

追踪效果:
这里写图片描述
这里写图片描述
时间:
这里写图片描述

注(画框函数引用网上现有的)
可能是matlab问题,这段视频为4K,无法直接读取,所以只能将其转化为图片逐帧读取。
结果是还是太慢,而且不能预读取,好像用这个无法实时,可能与图片为4k也有点关系有点伤