1 | function [rep_motion motion_vector] = fastMV(im1, im2, w) |
2 | % Author: Arash Jalalian |
3 | % E-mail: arash.jalalian@gmail.com |
4 | % Arguments: [rep_motion motion_vector] = fastMV(im1, im2, w) |
5 | % This is the simplified block matching algorithm(BMA) which is proposed by |
6 | % L. Hao. I've simplified this algorithm for use it in a real-time problem. |
7 | % We have a dynamic search pattern during finding the motion vector. |
8 | % 1. check with big diamond. |
9 | % 2. check with one of the hexagon subject to previous results. |
10 | % 3. check with small diamond. |
11 | % 'im1' is base frame of a video and 'im2' is the second frame. and 'w' is |
12 | % the window size. 'rep_motion' is the representative motion vector and |
13 | % 'motion_vector' declare motion vectors for each block of image. |
14 | % Example: |
15 | % im1 = imread('frame001.jpg'); |
16 | % im2 = imread('frame002.jpg'); |
17 | % w = 16; |
18 | % [rep_m m_vector] = fastMV(im1, im2, w); |
19 | |
20 | % clear all |
21 | % close all |
22 | % clc |
23 | % im1 = imread('img_1057.pgm'); |
24 | % im2 = imread('img_1058.pgm'); |
25 | % % dis = 2; |
26 | % w = 8; |
27 | |
28 | |
29 | % initialization |
30 | [r1 c1] = size(im1); |
31 | [r2 c2] = size(im2); |
32 | if r1 ~= r2 || c1 ~= c2 |
33 | error('The images must be in a same size') |
34 | end |
35 | |
36 | pat.org = [0; 0]; |
37 | pat.diam1 = [2 0 -2 0; 0 2 0 -2];%big diamond |
38 | pat.diam2 = [1 0 -1 0; 0 1 0 -1];%small diamond |
39 | pat.hexver = [2 1 -1 -2 -1 1; 0 2 2 0 -2 -2]; |
40 | pat.hexhor = [2 0 -2 -2 0 2 ;1 2 1 -1 -2 -1]; |
41 | |
42 | r_time = int16(floor(r1 ./ w)); |
43 | c_time = int16(floor(c1 ./ w)); |
44 | |
45 | % for preventing index exceeding from end of image. 4 is the maximum |
46 | % Magnitude of the motion vector |
47 | if mod(r1, w) < 4 |
48 | r_time = r_time -1; |
49 | end |
50 | if mod(c1, w) < 4 |
51 | c_time = c_time -1; |
52 | end |
53 | slice1 = cell(r_time, c_time); |
54 | slice2 = cell(r_time, c_time); |
55 | motion_vector = cell(r_time, c_time); |
56 | |
57 | % creating slices with cell array of slices |
58 | for i = 1:r_time |
59 | for j = 1:c_time |
60 | slice1{i, j} = im1(((i-1) * w) + 1:i * w, ((j-1) * w) + 1:j * w); |
61 | slice2{i, j} = im2(((i-1) * w) + 1:i * w, ((j-1) * w) + 1:j * w); |
62 | end |
63 | end |
64 | |
65 | % first step checking with 4 points of big diamond and the origin |
66 | mad_org = zeros(r_time, c_time); |
67 | min_mad = zeros(r_time, c_time); |
68 | idx_min_mad = zeros(r_time, c_time); |
69 | for i = 1:r_time |
70 | for j = 1:c_time |
71 | s_h_r = ((i-1) * w) + 1;%slice head row |
72 | s_h_c = ((j-1) * w) + 1;%slice head column |
73 | diff.org{i, j} = abs(slice2{i, j} - slice1{i, j}); |
74 | [r_diam c_diam] = size(pat.diam1); |
75 | for k = 1:c_diam |
76 | if s_h_r + pat.diam1(1, k) > 0 && s_h_c + pat.diam1(2, k) > 0 |
77 | diff.diam1{1, k} = abs(slice1{i, j}- im2(s_h_r + pat.diam1(1, k):... |
78 | i *w + pat.diam1(1, k),... |
79 | s_h_c + pat.diam1(2, k):... |
80 | j * w + pat.diam1(2, k))); |
81 | % calculating MAD = Mean Absolute Difference |
82 | diff.diam1{2, k} = sum(sum(diff.diam1{1,k})) / (w ^ 2);% insert each MAD below each Pat |
83 | mad(k) = sum(sum(diff.diam1{1,k})) / (w ^ 2); |
84 | else |
85 | diff.diam1{1, k} = 9999999999999; |
86 | diff.diam1{2, k} = 9999999999999; |
87 | mad(k) = sum(sum(diff.diam1{1,k})) / (w ^ 2); |
88 | end |
89 | end |
90 | % calculating minimum of mad in 4 pat and the origin and inserting |
91 | % them into a min_mad(i, j). where i, j decler the position of the |
92 | % slice in the image |
93 | mad_org(i , j) = sum(sum(diff.org{i,j})) / (w ^ 2); |
94 | mad = [mad mad_org(i, j)]; |
95 | [min_mad(i, j) idx_min_mad(i, j)] = min(mad); |
96 | clear mad |
97 | |
98 | end |
99 | end |
100 | % if the idx_min_mad == 5 it means that the origin has the minimum value of |
101 | % mad (between 4 big diamond points and the origin the orogin has the |
102 | % minimum value) otherwise the index in idx_min_mad shows the pat index that |
103 | % has the min mad value. |
104 | idx_min_mad2 = zeros(r_time, c_time); |
105 | min_mad2 = zeros(r_time, c_time); |
106 | for i = 1:r_time |
107 | for j = 1:c_time |
108 | clear mad |
109 | if idx_min_mad(i, j) == 5 |
110 | % it means this point didn't moved and it's better to do not use |
111 | % any motion vectors so we must put [0; 0] for these points as a |
112 | % motion vector.accourding to the paper for any slices that |
113 | % idx_min_mad(i, j) ==5 we must use anothe four points as new |
114 | % pat and check the slices with these i and j for mad. and the |
115 | % final solution for these slices is these mad. here we must |
116 | % use pat.diam2 as new patterns and repeat thise process again. |
117 | s_h_r = ((i-1) * w) + 1;%slice head row |
118 | s_h_c = ((j-1) * w) + 1;%slice head column |
119 | % diff.org{i, j} = abs(slice2{i, j} - slice1{i, j}); |
120 | [r_diam c_diam] = size(pat.diam1); |
121 | for k = 1:c_diam |
122 | if s_h_r + pat.diam2(1, k) > 0 && s_h_c + pat.diam2(2, k) > 0 |
123 | diff.diam2{1, k} = abs(slice1{i, j}- im2(s_h_r + pat.diam2(1, k):... |
124 | i *w + pat.diam2(1, k),... |
125 | s_h_c + pat.diam2(2, k):... |
126 | j * w + pat.diam2(2, k))); |
127 | % calculating MAD = Mean Absolute Diffrence |
128 | diff.diam2{2, k} = sum(sum(diff.diam2{1,k})) / (w ^ 2);% insert each MAD below each Pat |
129 | mad(k) = sum(sum(diff.diam2{1,k})) / (w ^ 2); |
130 | else |
131 | diff.diam2{1, k} = 9999999999999; |
132 | diff.diam2{2, k} = 9999999999999; |
133 | mad(k) = sum(sum(diff.diam2{1,k})) / (w ^ 2); |
134 | end |
135 | end |
136 | % calculating minimum of mad in 4 pat and the origin and inserting |
137 | % them into a min_mad(i, j). where i, j decler the position of the |
138 | % slice in the image |
139 | % mad_org(i , j) = sum(sum(diff.org{i,j})) / (w ^ 2); |
140 | % mad = [mad mad_org(i, j)]; |
141 | [min_mad2(i, j) idx_min_mad2(i, j)] = min(mad); |
142 | |
143 | end |
144 | end |
145 | end |
146 | for i = 1:r_time |
147 | for j = 1:c_time |
148 | if idx_min_mad2(i, j) ~= 0 |
149 | motion_vector{i , j} = pat.diam2(:, idx_min_mad2(i, j)); |
150 | end |
151 | end |
152 | end |
153 | |
154 | % other points that their minimum mads idx ~= 5. it means that these slices |
155 | % are closer to farder slices. |
156 | idx_min_mad3 = zeros(r_time, c_time); |
157 | min_mad3 = zeros(r_time, c_time); |
158 | for i = 1:r_time |
159 | for j = 1:c_time |
160 | clear mad |
161 | if idx_min_mad(i, j) ~= 5 |
162 | s_h_r = ((i-1) * w) + 1;%slice head row |
163 | s_h_c = ((j-1) * w) + 1;%slice head column |
164 | % diff.org{i, j} = abs(slice2{i, j} - slice1{i, j}); |
165 | [r_hex c_hex] = size(pat.hexhor); |
166 | for k = 1:c_hex |
167 | if s_h_r + pat.hexhor(1, k) > 0 && s_h_c + pat.hexhor(2, k) > 0 && (idx_min_mad(i, j) == 1 || idx_min_mad(i, j) == 3) |
168 | diff.hex{1, k} = abs(slice1{i, j}- im2(s_h_r + pat.hexhor(1, k):... |
169 | i *w + pat.hexhor(1, k),... |
170 | s_h_c + pat.hexhor(2, k):... |
171 | j * w + pat.hexhor(2, k))); |
172 | % calculating MAD = Mean Absolute Diffrence |
173 | diff.hex{2, k} = sum(sum(diff.hex{1,k})) / (w ^ 2);% insert each MAD below each Pat |
174 | mad(k) = sum(sum(diff.hex{1,k})) / (w ^ 2); |
175 | elseif s_h_r + pat.hexver(1, k) > 0 && s_h_c + pat.hexver(2, k) > 0 && (idx_min_mad(i, j) == 2 || idx_min_mad(i, j) == 4) |
176 | diff.hex{1, k} = abs(slice1{i, j}- im2(s_h_r + pat.hexver(1, k):... |
177 | i *w + pat.hexver(1, k),... |
178 | s_h_c + pat.hexver(2, k):... |
179 | j * w + pat.hexver(2, k))); |
180 | % calculating MAD = Mean Absolute Diffrence |
181 | diff.hex{2, k} = sum(sum(diff.hex{1,k})) / (w ^ 2);% insert each MAD below each Pat |
182 | mad(k) = sum(sum(diff.hex{1,k})) / (w ^ 2); |
183 | else |
184 | diff.hex{1, k} = 9999999999999; |
185 | diff.hex{2, k} = 9999999999999; |
186 | mad(k) = sum(sum(diff.hex{1,k})) / (w ^ 2); |
187 | end |
188 | end |
189 | % calculating minimum of mad in 4 pat and inserting |
190 | % them into a min_mad(i, j). where i, j decler the position of the |
191 | % slice in the image |
192 | % mad_org(i , j) = sum(sum(diff.org{i,j})) / (w ^ 2); |
193 | % mad = [mad mad_org(i, j)]; |
194 | [min_mad3(i, j) idx_min_mad3(i, j)] = min(mad); |
195 | |
196 | end |
197 | end |
198 | end |
199 | % org_mov declare the movement vector for new pattern origins. |
200 | org_mov = cell(r_time, c_time); |
201 | for i = 1:r_time |
202 | for j = 1:c_time |
203 | if idx_min_mad3(i, j) ~= 0 && (idx_min_mad(i, j) == 1 || idx_min_mad(i, j) == 3) |
204 | org_mov{i , j} = pat.hexhor(:, idx_min_mad3(i, j)); |
205 | elseif idx_min_mad3(i, j) ~= 0 && (idx_min_mad(i, j) == 2 || idx_min_mad(i, j) == 4) |
206 | org_mov{i , j} = pat.hexver(:, idx_min_mad3(i, j)); |
207 | end |
208 | end |
209 | end |
210 | % now we must go the theird step. the minimum mad point found in the |
211 | % previous search step is repositioned as the center point to form a new |
212 | % hexagon nad only three new non overlaped points will be checked as |
213 | % candidates each time. so we must define new pattern. this time our |
214 | % patterns must have a dynamic behavior. and also these pattern must be |
215 | % created based on the old pat.hexver and pat.hexhor |
216 | [r_mov c_mov] = size(org_mov); |
217 | idx_min_mad4 = zeros(r_mov, c_mov); |
218 | min_mad4 = zeros(r_mov, c_mov); |
219 | for i = 1:r_mov |
220 | for j = 1:c_mov |
221 | clear mad |
222 | nu = sparse(org_mov{i, j}); |
223 | [r_nu c_nu] = size(nu); |
224 | if r_nu ~= 0 || c_nu ~= 0 |
225 | for z = 1:c_hex |
226 | pat.hexver_new(:, z) = pat.hexver(:, z) + org_mov{i, j}; |
227 | pat.hexhor_new(:, z) = pat.hexhor(:, z) + org_mov{i, j}; |
228 | end |
229 | s_h_r = ((i-1) * w) + 1;%slice head row |
230 | s_h_c = ((j-1) * w) + 1;%slice head column |
231 | % diff.org{i, j} = abs(slice2{i, j} - slice1{i, j}); |
232 | [r_hex c_hex] = size(pat.hexhor_new); |
233 | for k = 1:c_hex |
234 | % clear mad |
235 | if s_h_r + pat.hexhor_new(1, k) > 0 && s_h_c + pat.hexhor_new(2, k) > 0 && (idx_min_mad(i, j) == 1 || idx_min_mad(i, j) == 3) |
236 | diff.hex{1, k} = abs(slice1{i, j}- im2(s_h_r + pat.hexhor_new(1, k):... |
237 | i *w + pat.hexhor_new(1, k),... |
238 | s_h_c + pat.hexhor_new(2, k):... |
239 | j * w + pat.hexhor_new(2, k))); |
240 | % calculating MAD = Mean Absolute Diffrence |
241 | diff.hex{2, k} = sum(sum(diff.hex{1,k})) / (w ^ 2);% insert each MAD below each Pat |
242 | mad(k) = sum(sum(diff.hex{1,k})) / (w ^ 2); |
243 | elseif s_h_r + pat.hexver_new(1, k) > 0 && s_h_c + pat.hexver_new(2, k) > 0 && (idx_min_mad(i, j) == 2 || idx_min_mad(i, j) == 4) |
244 | diff.hex{1, k} = abs(slice1{i, j}- im2(s_h_r + pat.hexver_new(1, k):... |
245 | i *w + pat.hexver_new(1, k),... |
246 | s_h_c + pat.hexver_new(2, k):... |
247 | j * w + pat.hexver_new(2, k))); |
248 | % calculating MAD = Mean Absolute Diffrence |
249 | diff.hex{2, k} = sum(sum(diff.hex{1,k})) / (w ^ 2);% insert each MAD below each Pat |
250 | mad(k) = sum(sum(diff.hex{1,k})) / (w ^ 2); |
251 | else |
252 | diff.hex{1, k} = 9999999999999; |
253 | diff.hex{2, k} = 9999999999999; |
254 | mad(k) = sum(sum(diff.hex{1,k})) / (w ^ 2); |
255 | end |
256 | end |
257 | % calculating minimum of mad in 4 pat and inserting |
258 | % them into a min_mad(i, j). where i, j declare the position of the |
259 | % slice in the image |
260 | % mad_org(i , j) = sum(sum(diff.org{i,j})) / (w ^ 2); |
261 | mad = [mad mad_org(i, j)]; |
262 | [min_mad4(i, j) idx_min_mad4(i, j)] = min(mad); |
263 | % clear mad |
264 | end |
265 | end |
266 | end |
267 | % org_mov declare the movement vector for new pattern origins. |
268 | % final motion vector calculation |
269 | for i = 1:r_mov |
270 | for j = 1:c_mov |
271 | if idx_min_mad4(i, j) == 7 |
272 | motion_vector{i, j} = pat.org; |
273 | elseif idx_min_mad4(i, j) ~= 0 && (idx_min_mad(i, j) == 1 || idx_min_mad(i, j) == 3) |
274 | motion_vector{i , j} = pat.hexhor_new(:, idx_min_mad4(i, j)); |
275 | elseif idx_min_mad4(i, j) ~= 0 && (idx_min_mad(i, j) == 2 || idx_min_mad(i, j) == 4) |
276 | motion_vector{i , j} = pat.hexver_new(:, idx_min_mad3(i, j)); |
277 | end |
278 | end |
279 | end |
280 | |
281 | % now we want to find rep_motion vector |
282 | motion_vectors = cat(2, motion_vector{:}); |
283 | most_motion_vector = zeros(1, r_time .* c_time); |
284 | clear temp |
285 | temp = motion_vectors; |
286 | for i=1:r_time .* c_time |
287 | my_count = 0; |
288 | element(:, 1) = temp(:, i); |
289 | for k = i+1:r_time .* c_time |
290 | if temp(:, k) == element(:, 1) |
291 | my_count = my_count+1; |
292 | % temp(:, k) = []; |
293 | end |
294 | end |
295 | most_motion_vector(i) = my_count; |
296 | end |
297 | [value, idx] = max(most_motion_vector); |
298 | rep_motion= motion_vectors(:, idx); |
from http://www.mathworks.com/matlabcentral/fileexchange/15767-fast-motion-detection-bugs-fixed-
Snippet is not live.
Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #2000475 |
Snippet name: | fastMV.m (fast motion detection in MATLAB) |
Eternal ID of this version: | #2000475/1 |
Text MD5: | 58b7089023914955e95075a921fb6063 |
Author: | stefan |
Category: | |
Type: | New Tinybrain snippet |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2015-08-01 16:28:49 |
Source code size: | 13213 bytes / 298 lines |
Pitched / IR pitched: | No / Yes |
Views / Downloads: | 715 / 128 |
Referenced in: | [show references] |