-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathselective_blockmatching.m
More file actions
136 lines (113 loc) · 5.64 KB
/
selective_blockmatching.m
File metadata and controls
136 lines (113 loc) · 5.64 KB
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
function macroblock = selective_blockmatching(current_macroblock,x,y,prev_frame,denied_x_range_start,denied_x_range_end,denied_y_range_start,denied_y_range_end,macroblock_size)
% topic 2
% this is a modified version of the blockmatching_search function
% key differences:
% macroblock size is not predefiend, it is passed on as parameter
% there is only one pyramid level to contribute to accuracy
% denial area (start position ,end position for both x and y axes)
k = 32; % search radius
% base frame dimensions
width = 640;
height = 640;
pyramid_levels = 1; % image scaling levels ( 3 is lowest_resolution = base_resolution/(2^3) )
matched_macroblock_pos = [x,y];
sk = k;
for level=pyramid_levels:-1:0
x = matched_macroblock_pos(1);
y = matched_macroblock_pos(2);
if(level==pyramid_levels) % lowest level
scaling_factor = 2^pyramid_levels;
% if rounding result 0<result<1 -> set result as 1
sx = max(1, round(x/scaling_factor));
sy = max(1, round(y/scaling_factor));
denied_x_range_start = max (1, round(denied_x_range_start/scaling_factor));
denied_x_range_end = max (1, round(denied_x_range_end/scaling_factor));
denied_y_range_start = max (1, round(denied_y_range_start/scaling_factor));
denied_y_range_end =max (1, round(denied_y_range_end/scaling_factor));
else
sk = sk/2;
scaling_factor = scaling_factor/2;
sx = x*2;
sy = y*2;
denied_x_range_start = denied_x_range_start*2;
denied_y_range_start = denied_y_range_start*2;
denied_x_range_end = denied_x_range_end*2;
denied_y_range_end = denied_y_range_end*2;
end
% scaled frame sizes
s_width = width/scaling_factor;
s_height = height/scaling_factor;
if(sx>s_width)
sx=s_width;
end
if(sy>s_height)
sy=s_height;
end
s_macroblock_size = macroblock_size/scaling_factor;
% scaling original macroblock and the whole predicted frame
s_current_macro = imresize( current_macroblock , [ s_macroblock_size, s_macroblock_size ] );
s_prev_f = imresize( prev_frame , [ s_width, s_height ] );
top_b = max(1,sy-sk); % top border
left_b = max(1,sx-sk); % left border
bottom_b = sy+sk; % bottom border
right_b = sx+sk; % right border
if(bottom_b > s_height )
bottom_b = s_height;
end
if(right_b > s_width )
right_b = s_width;
end
% this check is needed because when dividing sx and sy by 2,
% sometimes they are not % divisible by 2, so they need to be rounded to the
% closest integer, at the start of the pyramid loop (excluding 1st
% iteration)these numbers need to be multiplied by 2, thus if sx,sy were
% near the bottom or right border, multiplication would lead to
% border exceedment
if(sx+s_macroblock_size-1 > s_width)
sx = s_width - macroblock_size-1;
end
if(sy+s_macroblock_size-1 > s_height)
sy = s_height - macroblock_size-1;
end
min_mad = 999999; % a very excessive positive number
matched_macroblock_pos=[sx,sy]; % starting (top-left) position of matched macroblock
for i = left_b:right_b
for j = top_b:bottom_b
searching_macroblock_right_end = i+s_macroblock_size-1;
searching_macroblock_bottom_end = j+s_macroblock_size-1;
if( (searching_macroblock_right_end) <= s_width && (searching_macroblock_bottom_end) <= s_height) % if search does not exceed frame size
if( (i+s_macroblock_size-1 < denied_x_range_start | i > denied_x_range_end) && (j+s_macroblock_size-1 < denied_y_range_start | j > denied_y_range_end) )
% ^ denial area check
MAD = mean_diff(s_current_macro, s_prev_f(i:searching_macroblock_right_end,j:searching_macroblock_bottom_end));
if( MAD < min_mad) % min MAD calculation
min_mad = MAD;
matched_macroblock_pos = [i,j]; % position of most fitting macroblock
end
end
end
end
end
end
%matched_macroblock_pos = matched_macroblock_pos*2;
% above line needed if we change the pyramid 'for loop' to stop at 1
% instead of 0 (will skip 1 to 1 pixel blockmatching), is faster
% same margin error as explained on line 68
if(matched_macroblock_pos(1)+(macroblock_size-1)>width)
matched_macroblock_pos(1) = width-macroblock_size-1;
end
if(matched_macroblock_pos(2)+(macroblock_size-1)>height)
matched_macroblock_pos(2) = height-macroblock_size-1;
end
% minimum mean difference macroblock
macroblock = prev_frame(matched_macroblock_pos(1):matched_macroblock_pos(1)+(macroblock_size-1),matched_macroblock_pos(2):matched_macroblock_pos(2)+(macroblock_size-1));
end
% calculates the mean difference (or MAD) between two microblocks
function MAD = mean_diff(original_m,selected_m)
MAD = 0;
for x=1:size(original_m,1)
for y=1:size(original_m,2)
MAD = MAD + abs(original_m(x,y) - selected_m(x,y));
end
end
MAD = MAD/((size(original_m,1)^2));
end