Project

General

Profile

Basic Image Processing for Moving Object Tracking » find_hexbug.m

Tanzeem William, 20 Oct 2020 13:37

 
1

    
2
%Student Dave's tutorial on:  Image processing for object
3
%tracking  (aka giving eyes to your robot :) 
4
%Copyright Student Dave's Tutorials 2012
5
%if you would like to use this code, please feel free, just remember to
6
%reference and tell your friends! :)
7
%requires matlabs image processing toolbox
8

    
9

    
10
%What the heck does this code do!?
11
%the code finds the hexbug buy using a series of basic, but effective
12
%images processing techniques (formal talk for a second -->) :
13
% 1) Averaged background subtraction
14
% 2) Noise reduction via image smoothing using 2-d gaussian filter.
15
% 3) Threshold and point detection in binary image.
16

    
17
clear all;
18
close all;
19
set(0,'DefaultFigureWindowStyle','docked') %dock the figures..just a personal preference you don't need this.
20

    
21
base_dir = 'E:\Dropbox\Student_dave\hexbug_frames\';
22

    
23
cd(base_dir);
24

    
25
%% get listing of frames so that you can cycle through them easily.
26
f_list =  dir('*png');
27

    
28

    
29
%% make average of background images (i.e. images with no objects of interest)
30
% Here we just read in a set of images (N) and then take the average of
31
% them so that we are confident we got a good model of what the background
32
% looks like (i.e. a template free from any potential weird image artifacts
33

    
34
N = 20; % num of frames to use to make averaged background...that is, images with no bug!
35
img = zeros(288,352,N); %define image stack for averaging (if you don't know what this is, just load the image and  check it with size())
36
for i = 1:N    
37
    img_tmp = imread(f_list(i).name); %read in the given image
38
    img(:,:,i) = img_tmp(:,:,1); % we don't really care about the rgb image values, so we just take the first dimension of the image
39
end
40
bck_img = (mean(img,3)); %take the average across the image stack..and bingo! there's your background template!
41
subplot(121);imagesc(bck_img)
42
subplot(122);imagesc(img(:,:,1))
43
colormap(gray)
44
clear img; % free up memory.
45

    
46
%initialize gaussian filter
47

    
48
%using fspecial, we will make a gaussian template to convolve (pass over)
49
%over the image to smooth it.
50
hsize = 20;
51
sigma = 10;
52
gaus_filt = fspecial('gaussian',hsize , sigma);
53
subplot(121); imagesc(gaus_filt)
54
subplot(122); mesh(gaus_filt)
55
colormap(jet)
56

    
57
%this one is just for making the coordinate locations more visible.
58
SE = strel('diamond', 7); %another tool make for making fun matrice :) this one makes a matrice object for passing into imdilate())
59

    
60

    
61
%% iteratively (frame by frame) find bug!
62
CM_idx = zeros(length(f_list),2); % initize the variable that will store the bug locations (x,y)
63

    
64
for i = 1:2:length(f_list) 
65
   
66
    img_tmp = double(imread(f_list(i).name)); %load in the image and convert to double too allow for computations on the image
67
    img = img_tmp(:,:,1); %reduce to just the first dimension, we don't care about color (rgb) values here.
68
    subplot(221);imagesc(img);
69
    title('Raw');
70
    
71
    %{
72
    %VERY HARD TRACKING
73
    %for frames 230:280, make the bug very hard to track    
74
    if (i > 230) && (i < 280) && (mod(i,3) == 0 )      
75
        J = imnoise(img,'speckle');
76
        img = img+J*200;
77
    end
78
    %}
79
  
80
    
81
    %subtract background from the image
82
    sub_img = (img - bck_img);
83
    subplot(222);imagesc(sub_img);
84
    title('background subtracted');
85
    %gaussian blurr the image
86
    gaus_img = filter2(gaus_filt,sub_img,'same');     
87
    subplot(223);imagesc(gaus_img);
88
    title('gaussian smoothed');
89
    %threshold the image...here i just made a quick histogram to see what
90
    %value the bug was below
91
    subplot(224);hist(gaus_img(:));
92
    thres_img = (gaus_img < -15);
93
    subplot(224);imagesc(thres_img);
94
    title('thresholded');
95
   
96
    
97
    %% TRACKING! (i.e. get the coordinates of the bug )
98
    %quick solution for finding center of mass for a BINARY image
99
    %basically, just get indices of all locations above threshold (1) and
100
    %take the average, for both the x and y directions. This will give you
101
    %the average location in each dimension, and hence the center of the
102
    %bug..unless of course, something else (like my hand) passes threshold
103
    %:P  
104
    %if doesn't find anything, it randomly picks a pixel
105
    [x,y] = find (thres_img);    
106
    if ~isempty(x)
107
        CM_idx(i,:) = ceil([mean(x) mean(y)]+1); % i used ceiling to avoid zero indices, but it makes the system SLIGHTLY biased, meh, no biggie, not the point here :).
108
    else
109
        CM_idx(i,:) = ceil([rand*200 rand*200]);
110
    end
111
    
112
    
113
   
114
    %{
115
    %NOT SO HARD TRACKING
116
     %for frames 230:280, make the bugtracking just a lil noisy by randomly sampling
117
    %around the bugtracker
118
    if (i > 230) && (i < 280) && (mod(i,2) == 0 )  
119
       CM_idx(i,:) = [round(CM_idx(i,1) + randn*10) round(CM_idx(i,2) + randn*10)];
120
    end
121
    %}
122
    
123
     %{
124
    %NO  TRACKING
125
     %for frames 230:280, make the bugtracking just a lil noisy by randomly sampling
126
    %around the bugtracker
127
    if (i > 230) && (i < 280)   
128
       CM_idx(i,:) = [NaN NaN];
129
    end
130
    %}
131
    
132
    
133
    %% now, we visual everything :)
134
    
135
    %create a dilated dot at this point for visualize
136
    %make binary image with single coordinate of bug = 1 and rest zeros.
137
    %then dilate that point to make a more visible circle.
138
    bug_img = zeros(size(thres_img)); 
139
    bug_img(CM_idx(i,1),CM_idx(i,2)) = 1;
140

    
141
    %{
142
    % if you are running the "no tracking segment above, you'll need to
143
    % skip over that  segment, and thus use this code
144
    if ~((i > 230) && (i < 280))
145
        bug_img(CM_idx(i,1),CM_idx(i,2)) = 1;
146
    end
147
    %}
148
    
149
    bug_img = imdilate(bug_img, SE);
150
    subplot(224);imagesc(thres_img + bug_img);
151
    title('thresholded and extracted (red diamond)');
152
    axesHandles = get(gcf,'children');
153
    set(axesHandles, 'XTickLabel', [], 'XTick', []);
154
    set(axesHandles, 'YTickLabel', [], 'YTick', [])  ;    
155

    
156
    pause(.01)
157
end
158

    
159
%save out the hexbug coordinates
160
    
161
%save('CM_idx_no.mat', 'CM_idx')
162

    
163

    
164
     
165
    %{
166
    %nice and elegant solution for center of mass of gray scale image (i.e. doesn't have to be binary like in our case)----------------------------------
167
    % http://www.mathworks.com/matlabcentral/newsreader/author/109726
168
    %These next 4 lines produce a matrix C whose rows are
169
    % the pixel coordinates of the image A
170
    C=cellfun(@(n) 1:n, num2cell(size(thres_img)),'uniformoutput',0);
171
    [C{:}]=ndgrid(C{:});
172
    C=cellfun(@(x) x(:), C,'uniformoutput',0);
173
    C=[C{:}]; 
174
    %This line computes a weighted average of all the pixel coordinates. 
175
    %The weight is proportional to the pixel value.
176
    CenterOfMass=thres_img(:).'*C/sum(thres_img(:),'double')
177
    %---------------------------------------------------------------------
178
    %}
(1-1/5)