1 // Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * ma.h: A video stabilizer that uses moving averages to calculate
34 * Stabilize using moving averages.
36 * For a given frame x, the moving averages are calculated over frames
37 * ranging from x - r to x + r, where r is the specified RANGE size.
40 class ma
: public vise
{
43 ma(render
*r
, unsigned int range
, const char *prefix
, const char *suffix
,
44 ale_real scale_factor
) : vise(r
, prefix
, suffix
, scale_factor
) {
45 r
->extend_queue(range
);
50 * Accept an image for rendering.
53 void render_frame(unsigned int frame_number
) {
55 const image
*im
= r
->get_image(frame_number
);
58 const filter::scaled_filter
*scf
= NULL
;
59 unsigned int rx_count
= render::get_rx_count();
60 const exclusion
*rx_parameters
= render::get_rx_parameters();
61 int rx_show
= render::is_rx_show();
64 * Determine, for single-invariant chains, whether replacement
65 * is occurring, and, if so, determine whether we are honoring
68 if (typeid(*r
) == typeid(incremental
)
69 && ((incremental
*)r
)->get_invariant()->is_last()) {
70 scf
= ((incremental
*)r
)->get_invariant()->ssfe()->get_scaled_filter();
71 if (scf
->is_coarse() && scf
->get_filter()->support() >= 1) {
73 replace_ex
= ((incremental
*)r
)->get_invariant()->ssfe()->ex_is_honored();
78 * Calculate the parameters for the desired
89 ale_pos bd
[BARREL_DEGREE
] = {0, /* ... */};
90 unsigned int bd_count
= BARREL_DEGREE
;
93 for (int f
= frame_number
- range
; f
<= (int) (frame_number
+ range
); f
++) {
95 || f
>= (int) image_rw::count())
100 transformation t
= align::of(f
);
102 for (unsigned int i
= 0; i
< 4; i
++)
103 p
[i
] = p
[i
] + t
.transform_scaled(point((i
== 1 || i
== 2) ? t
.scaled_height() : 0,
104 (i
> 1) ? t
.scaled_width() : 0));
106 if (t
.bd_count() < bd_count
)
107 bd_count
= t
.bd_count();
109 for (unsigned int i
= 0; i
< bd_count
; i
++)
110 bd
[i
] += t
.bd_get(i
);
113 for (unsigned int i
= 0; i
< 4; i
++)
114 p
[i
] = p
[i
] / (ale_real
) frame_count
;
116 for (unsigned int i
= 0; i
< bd_count
; i
++)
117 bd
[i
] /= frame_count
;
120 * Generate the desired transformation.
122 transformation t
= align::of(frame_number
);
123 transformation s
= t
;
124 unsigned int new_height
= (unsigned int)
125 floor(s
.unscaled_height() * scale_factor
);
126 unsigned int new_width
= (unsigned int)
127 floor(s
.unscaled_width() * scale_factor
);
128 s
.set_domain(new_height
, new_width
);
130 s
.bd_set(bd_count
, bd
);
132 image
*rendered
= new image_ale_real(new_height
, new_width
, 3);
135 const image
*replace_image
= NULL
;
136 replace_image
= image_rw::open(frame_number
);
137 scf
->set_parameters(t
, s
, replace_image
);
140 for (unsigned int i
= 0; i
< rendered
->height(); i
++)
141 for (unsigned int j
= 0; j
< rendered
->width(); j
++) {
142 point unoffset_p
= s
.transform_scaled(point(i
, j
));
143 point p
= unoffset_p
- im
->offset();
144 // point p_replace = t.inverse_transform(s(point(i, j)));
148 if (rx_show
|| (replace
&& replace_ex
))
149 for (unsigned int param
= 0; param
< rx_count
; param
++) {
150 if (rx_parameters
[param
].type
== exclusion::RENDER
151 && unoffset_p
[0] >= rx_parameters
[param
].x
[0]
152 && unoffset_p
[0] <= rx_parameters
[param
].x
[1]
153 && unoffset_p
[1] >= rx_parameters
[param
].x
[2]
154 && unoffset_p
[1] <= rx_parameters
[param
].x
[3]
155 && frame_number
>= (unsigned) rx_parameters
[param
].x
[4]
156 && frame_number
<= (unsigned) rx_parameters
[param
].x
[5])
159 if (rx_parameters
[param
].type
== exclusion::FRAME
160 && i
>= rx_parameters
[param
].x
[0] * scale_factor
161 && i
<= rx_parameters
[param
].x
[1] * scale_factor
162 && j
>= rx_parameters
[param
].x
[2] * scale_factor
163 && j
<= rx_parameters
[param
].x
[3] * scale_factor
164 && frame_number
>= (unsigned) rx_parameters
[param
].x
[4]
165 && frame_number
<= (unsigned) rx_parameters
[param
].x
[5])
169 if (shading
< 1 && !rx_show
&& replace
&& replace_ex
)
175 scf
->filtered(i
, j
, &value
, &weight
, replace_ex
, frame_number
);
177 if (weight
.min_norm() > 0) {
178 rendered
->set_pixel(i
, j
, shading
* value
);
185 && p
[0] <= im
->height() - 1
187 && p
[1] <= im
->width() - 1)
188 rendered
->set_pixel(i
, j
, shading
* im
->get_bl(p
));
190 rendered
->set_pixel(i
, j
, pixel(0, 0, 0));
194 image_rw::close(frame_number
);
196 write_frame(rendered
, frame_number
);
202 * Report the frame lag for this stabilizer.