14 #define GAUSS_CONV_ROWS 4 15 #define GAUSS_CONV_COLUMNS 4 16 #define GAUSS_CONV_CORNERS 16 24 size_t image_width,
size_t image_height,
25 size_t mask_width,
size_t mask_height,
26 std::function<
double(std::vector<T>
const& sub_image) > convolution_operation
40 std::vector<double>
res(image.size(), 0);
41 std::vector<T> sub_image(mask_width * mask_height, 0);
43 size_t row_bound[
GAUSS_CONV_ROWS] = { 0, 1, image_height - 1,image_height - 2 };
49 for (
auto jj = 0; jj < image_width - mask_width + 1; jj++)
51 ind = first_rows[
row] * mask_width * lines[
row];
52 for (
auto l = first_rows[
row] * lines[
row]; l < mask_height - last_rows[
row] * lines[
row]; l++)
54 for (
size_t k = 0; k < mask_width; k++)
56 auto p = (l - first_rows[
row] * lines[
row] + last_rows[
row] * (-2 + row_bound[
row])) * image_width + jj + k;
57 sub_image[ind++] = (image[
p]);
61 ind = first_rows[
row] * mask_width * lines[
row] + last_rows[
row] * (mask_width * (mask_height - lines[
row]));
62 auto ind_pad = last_rows[
row] * (mask_width * (mask_height - lines[
row] - 1));
63 for (
size_t k = 0; k < mask_width * lines[
row]; k++)
65 auto idx1 = last_rows[
row] *
ind;
66 auto idx2 = last_rows[
row] * ind_pad + first_rows[
row] *
ind;
67 sub_image[k + idx1] = sub_image[k % mask_width + idx2];
69 auto mid = jj + mask_width / 2 + row_bound[
row] * image_width;
70 res[mid] = convolution_operation(sub_image);
75 size_t column_boundaries[
GAUSS_CONV_COLUMNS] = { 0,1, image_width - 1 ,image_width - 2 };
80 for (
size_t ii = 0;
ii < image_height - mask_height + 1;
ii++)
83 for (
size_t l = 0; l < mask_height; l++)
85 ind += left_column[
col] * columns[
col];
86 for (
auto k = left_column[
col] * columns[
col]; k < mask_width - right_column[
col] * columns[
col]; k++)
88 size_t p = (
ii + l) * image_width + k - left_column[
col] * columns[
col] + right_column[
col] * (column_boundaries[
col] - 2);
89 sub_image[ind++] = (image[
p]);
91 ind += right_column[
col] * columns[
col];
95 for (
size_t l = 0; l < mask_height; l++)
97 ind = left_column[
col] * columns[
col] + right_column[
col] * (mask_height - columns[
col] - 1) + l * mask_width;
98 for (
size_t k = 1; k <= columns[
col]; k++)
100 auto idx = left_column[
col] * (ind - k) + right_column[
col] * (ind + k);
101 sub_image[
idx] = sub_image[
ind];
104 auto mid = (
ii + mask_height / 2) * image_width + column_boundaries[
col];
105 res[mid] = convolution_operation(sub_image);
110 size_t corners_arr[
GAUSS_CONV_CORNERS] = { 0,1,image_width, image_width + 1, image_width - 1, image_width - 2, 2 * image_width - 1, 2 * image_width - 2,
111 (image_height - 2) * image_width,(image_height - 2) * image_width,
112 (image_height - 1) * image_width,(image_height - 1) * image_width,
113 (image_height - 2) * image_width,(image_height - 2) * image_width,
114 (image_height - 1) * image_width,(image_height - 1) * image_width };
116 size_t corners_arr_col[
GAUSS_CONV_CORNERS] = { 0,0,0,0,0,0,0,0,0,1,0,1,image_width - 1,image_width - 2,image_width - 1,image_width - 2 };
117 size_t left_col[
GAUSS_CONV_CORNERS] = { 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0 };
118 size_t right_col[
GAUSS_CONV_CORNERS] = { 0,0,0,0,1,1 ,1,1,0,0,0,0,1,1,1,1 };
119 size_t up_rows[
GAUSS_CONV_CORNERS] = { 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 };
120 size_t down_rows[
GAUSS_CONV_CORNERS] = { 0,0,0,0,0,0 ,0,0,1,1,1,1,1,1,1,1 };
121 size_t corner_columns[
GAUSS_CONV_CORNERS] = { 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1 };
122 size_t corner_rows[
GAUSS_CONV_CORNERS] = { 2, 2,1,1 ,2,2,1,1,1,1,2,2,1,1,2,2 };
124 ind = up_rows[corner] * corner_rows[corner] * mask_width;
125 for (
auto l = up_rows[corner] * corner_rows[corner]; l < mask_height - down_rows[corner] * corner_rows[corner]; l++)
127 ind += left_col[corner] * corner_columns[corner];
128 for (
auto k = left_col[corner] * corner_columns[corner]; k < mask_width - right_col[corner] * corner_columns[corner]; k++)
130 auto up_row_i = (l - corner_rows[corner] + right_col[corner] * (corner_rows[corner] - 2)) * image_width;
131 auto up_col_i = k - left_col[corner] * corner_columns[corner] + right_col[corner] * (corners_arr[corner] - 2);
132 auto down_row_i = (l - 2) * image_width + corners_arr[corner];
133 auto down_col_i = k - left_col[corner] * corner_columns[corner] + right_col[corner] * (corners_arr_col[corner] - 2);
134 auto col_i = down_rows[corner] * down_col_i + up_rows[corner] * up_col_i;
135 auto row_i = down_rows[corner] * down_row_i + up_rows[corner] * up_row_i;
136 auto p = row_i + col_i;
137 sub_image[ind++] = (image[
p]);
139 ind += right_col[corner] * corner_columns[corner];
144 auto l_init = down_rows[corner] * (mask_height - corner_rows[corner]);
145 auto l_limit = up_rows[corner] * corner_rows[corner] + down_rows[corner] * mask_height;
146 for (
auto l = l_init; l < l_limit; l++)
148 ind = up_rows[corner] * (corner_rows[corner] * mask_width) + down_rows[corner] * (mask_height - corner_rows[corner] - 1) * mask_width;
149 auto ind2 = l * mask_width;
150 for (
size_t k = 0; k < mask_width; k++)
152 sub_image[k + ind2] = sub_image[ind++];
156 for (
size_t l = 0; l < mask_height; l++)
158 ind = l * mask_width + left_col[corner] * corner_columns[corner] + right_col[corner] * (mask_width - 1 - corner_columns[corner]);
159 auto ind2 = l * mask_width + right_col[corner] * (mask_width - corner_columns[corner]);
160 for (
size_t k = 0; k < corner_columns[corner]; k++)
162 sub_image[k + ind2] = sub_image[
ind];
165 auto mid = corners_arr[corner] + corners_arr_col[corner];
166 res[mid] = convolution_operation(sub_image);
170 for (
size_t i = 0;
i < image_height - mask_height + 1;
i++)
172 for (
size_t j = 0;
j < image_width - mask_width + 1;
j++)
175 for (
size_t l = 0; l < mask_height; l++)
177 for (
size_t k = 0; k < mask_width; k++)
179 size_t p = (
i + l) * image_width +
j + k;
180 sub_image[ind++] = (image[
p]);
184 auto mid = (
i + mask_height / 2) * image_width +
j + mask_width / 2;
185 res[mid] = convolution_operation(sub_image);
194 size_t image_width,
size_t image_height,
195 size_t mask_width,
size_t mask_height,
196 std::function<
uint8_t(std::vector<T>
const& sub_image) > convolution_operation
203 std::vector<uint8_t>
res(image.size(), 0);
204 std::vector<T> sub_image(mask_width * mask_height, 0);
206 size_t rows[2] = { 0, image_height - 1 };
208 for (
auto rows_i = 0; rows_i < 2; rows_i++) {
209 for (
auto jj = 0; jj < image_width - mask_width + 1; jj++)
212 for (
size_t l = 0; l < mask_height; l++)
214 for (
size_t k = 0; k < mask_width; k++)
216 size_t p = (l + rows[rows_i]) * image_width + jj + k;
219 p = p - 2 * image_width;
221 sub_image[
ind] = (image[
p]);
222 bool cond1 = (l == 2) && (rows_i == 0);
223 bool cond2 = (l == 0) && (rows_i == 1);
224 if (cond1 || cond2) {
230 size_t mid = jj + mask_width / 2 + rows[rows_i] * image_width;
231 res[mid] = convolution_operation(sub_image);
236 size_t columns[2] = { 0, image_width - 1 };
237 for (
size_t columns_i = 0; columns_i < 2; columns_i++) {
238 for (
size_t ii = 0;
ii < image_height - mask_height + 1;
ii++)
241 for (
size_t l = 0; l < mask_height; l++)
243 for (
size_t k = 0; k < mask_width; k++)
245 size_t p = (
ii + l) * image_width + k + columns[columns_i];
250 sub_image[
ind] = (image[
p]);
251 bool cond1 = (k == 2) && (columns_i == 0);
252 bool cond2 = (k == 0) && (columns_i == 1);
253 if (cond1 || cond2) {
258 auto mid = (
ii + mask_height / 2) * image_width + columns[columns_i];
259 res[mid] = convolution_operation(sub_image);
264 for (
size_t i = 0;
i < image_height - mask_height + 1;
i++)
266 for (
size_t j = 0;
j < image_width - mask_width + 1;
j++)
269 for (
size_t l = 0; l < mask_height; l++)
271 for (
size_t k = 0; k < mask_width; k++)
273 size_t p = (
i + l) * image_width +
j + k;
274 sub_image[
ind++] = (image[
p]);
278 size_t mid = (
i + mask_height / 2) * image_width +
j + mask_width / 2;
279 res[mid] = convolution_operation(sub_image);
287 double const min_min_max_ratio,
288 double const min_weighted_edge_per_section,
289 double & min_max_ratio )
298 double z_max = *std::max_element(sum_weights_per_section.begin(), sum_weights_per_section.end());
299 double z_min = *std::min_element(sum_weights_per_section.begin(), sum_weights_per_section.end());
300 min_max_ratio = z_min / z_max;
301 if( min_max_ratio < min_min_max_ratio )
304 "Edge distribution ratio ({min}" 305 << z_min <<
"/" << z_max <<
"{max} = " << min_max_ratio
306 <<
") is too small; minimum= " << min_min_max_ratio );
319 bool is_edge_distributed =
true;
320 for(
auto it = sum_weights_per_section.begin();
it != sum_weights_per_section.end(); ++
it )
322 if( *
it < min_weighted_edge_per_section )
324 is_edge_distributed =
false;
328 if( ! is_edge_distributed )
330 AC_LOG(
DEBUG,
"check_edge_distribution: weighted edge per section is too low: " );
331 for(
auto it = sum_weights_per_section.begin();
it != sum_weights_per_section.end(); ++
it )
333 AC_LOG(
DEBUG,
"threshold is: " << min_weighted_edge_per_section );
335 return is_edge_distributed;
349 AC_LOG(
DEBUG,
" sum_per_section(z), section #1 " << *(
it + 2));
350 AC_LOG(
DEBUG,
" sum_per_section(z), section #2 " << *(
it + 1));
351 AC_LOG(
DEBUG,
" sum_per_section(z), section #3 " << *(
it + 3));
365 section_map_rgb.data() );
370 AC_LOG(
DEBUG,
" sum_per_section(yuy), section #0 " << *(
it));
371 AC_LOG(
DEBUG,
" sum_per_section(yuy), section #1 " << *(
it + 2));
372 AC_LOG(
DEBUG,
" sum_per_section(yuy), section #2 " << *(
it + 1));
373 AC_LOG(
DEBUG,
" sum_per_section(yuy), section #3 " << *(
it + 3));
384 std::vector< double >
const & directions,
386 std::vector< double > * p_weights_per_dir,
387 double * p_dir_ratio1 )
390 std::vector< double > weights_per_dir( 4, 0. );
393 for(
size_t ii = 0;
ii < directions.size(); ++
ii )
395 if( directions[
ii] ==
dir + 1 )
396 weights_per_dir[
dir] += weights[
ii];
399 if( p_weights_per_dir )
400 *p_weights_per_dir = weights_per_dir;
415 auto max_val = max_element( weights_per_dir.begin(), weights_per_dir.end() );
416 auto max_ix =
distance( weights_per_dir.begin(), max_val );
421 auto ix_match = (max_ix + 1) % 3;
425 if (weights_per_dir.at(ix_match) < 1
e-3)
429 dir_ratio1 = *max_val / weights_per_dir.at( ix_match );
431 *p_dir_ratio1 = dir_ratio1;
439 double max_val_perp = DBL_MIN;
440 double min_val_perp = DBL_MAX;
441 for (
auto i = 0;
i < 4; ++
i)
443 if ((
i != max_ix) && (
i != ix_match))
445 if( max_val_perp < weights_per_dir[
i] )
446 max_val_perp = weights_per_dir[
i];
447 if( min_val_perp > weights_per_dir[i] )
448 min_val_perp = weights_per_dir[
i];
453 auto perp_ratio = *max_val / max_val_perp;
457 " gradient direction is not balanced : " << dir_ratio1 <<
"; threshold is: " 461 if( min_val_perp < 1
e-3 )
464 " gradient direction is not balanced : " << dir_ratio1 <<
"; threshold is: " 470 double dir_ratio2 = max_val_perp / min_val_perp;
475 " gradient direction is not balanced : " << dir_ratio1 <<
"; threshold is: " 485 size_t const section_w,
486 size_t const section_h,
487 byte *
const section_map )
502 assert(section_w * section_h <= 256);
507 size_t const section_y =
row * section_h / f.
height;
510 size_t const section_x =
col * section_w / f.
width;
512 *section++ =
byte(section_y + section_x * section_h);
523 for (
size_t i = 0;
i < sub_image.size();
i++)
525 res = res || (
uint8_t)(sub_image[
i] * mask[
i]);
539 std::vector< uint8_t > dilation_mask = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
540 return dilation_convolution< uint8_t >( logic_edges,
545 [&]( std::vector< uint8_t >
const & sub_image ) {
556 for (
auto i = 0;
i < sub_image.size();
i++)
558 res = res + (double)(sub_image[
i] * mask[
i]);
566 std::vector< uint8_t >
const & prev_lum_frame,
567 std::vector< double > & yuy_diff,
568 std::vector< double > & gaussian_filtered_image,
573 auto area = height *
width;
578 std::vector< double > gaussian_kernel
579 = { 0.0029690167439504968, 0.013306209891013651, 0.021938231279714643, 0.013306209891013651,
580 0.0029690167439504968, 0.013306209891013651, 0.059634295436180138, 0.098320331348845769,
581 0.059634295436180138, 0.013306209891013651, 0.021938231279714643, 0.098320331348845769,
582 0.16210282163712664, 0.098320331348845769, 0.021938231279714643, 0.013306209891013651,
583 0.059634295436180138, 0.098320331348845769, 0.059634295436180138, 0.013306209891013651,
584 0.0029690167439504968, 0.013306209891013651, 0.021938231279714643, 0.013306209891013651,
585 0.0029690167439504968 };
587 auto yuy_iter = lum_frame.begin();
588 auto yuy_prev_iter = prev_lum_frame.begin();
589 for (
auto i = 0UL;
i < area;
i++, yuy_iter++, yuy_prev_iter++)
591 yuy_diff.push_back((
double)(*yuy_prev_iter) - (
double)(*yuy_iter));
593 gaussian_filtered_image
594 = gauss_convolution< double >( yuy_diff,
599 [&]( std::vector< double >
const & sub_image ) {
607 for(
double &
val : vec_in )
616 std::vector< uint8_t >
const & dilation_mask )
618 auto gauss_it = gauss_diff.begin();
619 auto dilation_it = dilation_mask.begin();
620 for(
size_t i = 0;
i < gauss_diff.size();
i++, gauss_it++, dilation_it++ )
629 std::vector< double >
const & gauss_diff_masked,
630 double const movement_threshold )
632 move_suspect.reserve( gauss_diff_masked.size() );
633 size_t n_movements = 0;
634 for(
auto it = gauss_diff_masked.begin();
it != gauss_diff_masked.end(); ++
it )
636 if( *
it > movement_threshold )
638 move_suspect.push_back(1);
643 move_suspect.push_back(0);
653 double const move_thresh_pix_val,
654 double const move_threshold_pix_num,
668 std::vector< double > gaussian_diff_masked;
670 std::vector< uint8_t > dilated_image;
672 std::vector< double > gaussian_filtered_image;
676 std::vector< double > yuy_diff;
680 gaussian_filtered_image,
701 gaussian_diff_masked = gaussian_filtered_image;
711 std::vector< uint8_t > move_suspect;
712 auto sum_move_suspect
720 if( sum_move_suspect > move_threshold_pix_num )
723 " found movement: " << sum_move_suspect <<
" pixels above threshold; allowed: " 748 AC_LOG( ERROR,
"Scene is not valid: movement detected between current & previous frames [MOVE]" );
765 const std::vector<double>& subpixels_x,
766 const std::vector<double>& subpixels_y,
774 for (
auto &&
i : directions)
776 edges_amount_per_dir[(int)
i - 1]++;
783 auto edges_amount_per_dir_normalized = (double)edges_amount_per_dir[
i] / (width * height);
791 { 1 / sqrt(2), 1 / sqrt(2) },
793 { -1 / sqrt(2), 1 / sqrt(2) }
797 auto diag_length = sqrt((
double)width*(
double)width + (
double)height*(
double)height);
801 for (
size_t i = 0;
i < subpixels_x.size();
i++)
803 auto dir = (int)directions[
i] - 1;
804 auto val = subpixels_x[
i] * dir_vecs[
dir].
x + subpixels_y[
i] * dir_vecs[
dir].
y;
805 val_per_dir[
dir].push_back(
val);
813 auto curr_dir = val_per_dir[
i];
814 double sum = std::accumulate(curr_dir.begin(), curr_dir.end(), 0.0);
815 double mean = sum / curr_dir.size();
817 double dists_sum = 0;
818 std::for_each(curr_dir.begin(), curr_dir.end(), [&](
double val) {dists_sum += (
val - mean)*(
val - mean); });
823 auto stdev = sqrt(dists_sum / (curr_dir.size() - 1));
824 std_per_dir[
i] = stdev / diag_length;
832 valid_directions[
i] = dirs_with_enough_edges[
i] && std_bigger_than_th[
i];
834 auto valid_directions_sum = std::accumulate(&valid_directions[0], &valid_directions[N_BASIC_DIRECTIONS], 0);
838 if (!edges_dir_spread)
841 "Scene is not valid: not enough edge direction spread (have " 843 return edges_dir_spread;
848 auto valid_even =
true;
851 valid_even &= valid_directions[
i];
854 auto valid_odd =
true;
857 valid_odd &= valid_directions[
i];
859 auto orthogonal_valid_dirs = valid_even || valid_odd;
861 if( ! orthogonal_valid_dirs )
863 "Scene is not valid: need at least two orthogonal directions that have enough " 864 "spread edges [EDGE-DIR]" );
866 return edges_dir_spread && orthogonal_valid_dirs;
869 return edges_dir_spread;
877 size_t saturated_pixels = 0;
879 for (
auto&&
i : ir_frame)
885 auto saturated_pixels_ratio = (double)saturated_pixels / (
double)(width*
height);
889 "Scene is not valid: saturation ratio (" 901 size_t min_section_with_enough_edges)
903 std::vector<int> num_pix_per_sec(n_sections, 0);
905 for (
auto&&
i : section_map)
907 num_pix_per_sec[
i]++;
909 std::vector<double> num_pix_per_sec_over_area(n_sections, 0);
910 std::vector<bool> num_sections_with_enough_edges(n_sections,
false);
912 for (
size_t i = 0;
i < n_sections;
i++)
914 num_pix_per_sec_over_area[
i] = (double)num_pix_per_sec[
i] / (width*height)*n_sections;
915 num_sections_with_enough_edges[
i] = num_pix_per_sec_over_area[
i] > th;
918 double sum = std::accumulate(num_sections_with_enough_edges.begin(), num_sections_with_enough_edges.end(), 0.0);
920 return sum >= min_section_with_enough_edges;
941 if( ! depth_spatial_spread )
942 AC_LOG( ERROR,
"Scene is not valid: not enough depth edge spread [EDGE-D]" );
944 if( ! rgb_spatial_spread )
945 AC_LOG( ERROR,
"Scene is not valid: not enough RGB edge spread [EDGE-C]" );
948 AC_LOG( ERROR,
"Scene is not valid: not enough movement from last-calibrated scene [SALC]" );
959 return dir_spread && not_saturated && depth_spatial_spread && rgb_spatial_spread
double min_weighted_edge_per_section_depth
std::vector< double > yuy_diff
bool require_orthogonal_valid_dirs
std::vector< uint8_t > images_dilation(std::vector< uint8_t > const &logic_edges, size_t width, size_t height)
std::vector< uint8_t > dilation_convolution(std::vector< T > const &image, size_t image_width, size_t image_height, size_t mask_width, size_t mask_height, std::function< uint8_t(std::vector< T > const &sub_image) > convolution_operation)
bool is_movement_in_images(movement_inputs_for_frame const &prev, movement_inputs_for_frame const &curr, movement_result_data *result_data, double const move_thresh_pix_val, double const move_threshold_pix_num, size_t width, size_t height)
double pix_per_section_depth_th
static bool is_grad_dir_balanced(std::vector< double > const &weights, std::vector< double > const &directions, params const &_params, std::vector< double > *p_weights_per_dir, double *p_dir_ratio1)
GLenum GLenum GLsizei void * row
bool is_edge_distributed(z_frame_data &z_data, yuy2_frame_data &yuy_data)
std::vector< double > gaussian_diff_masked
const int N_BASIC_DIRECTIONS
bool input_validity_checks(input_validity_data *data=nullptr)
double gaussian_calc(std::vector< T > const &sub_image, std::vector< double > const &mask)
std::vector< ir_t > ir_frame
#define GAUSS_CONV_CORNERS
static bool check_edge_distribution(std::vector< double > &sum_weights_per_section, double const min_min_max_ratio, double const min_weighted_edge_per_section, double &min_max_ratio)
std::vector< double > sum_weights_per_direction
double edges_per_direction_ratio_th
std::vector< double > gaussian_filtered_image
GLsizei GLsizei GLfloat distance
bool check_edges_spatial_spread(const std::vector< byte > §ion_map, size_t width, size_t height, double th, size_t n_sections, size_t min_section_with_enough_edges)
GLenum GLenum GLsizei void * image
double move_threshold_pix_num
static size_t move_suspected_mask(std::vector< uint8_t > &move_suspect, std::vector< double > const &gauss_diff_masked, double const movement_threshold)
static void gaussian_dilation_mask(std::vector< double > &gauss_diff, std::vector< uint8_t > const &dilation_mask)
std::vector< byte > supressed_edges
std::vector< double > subpixels_x
#define GAUSS_CONV_COLUMNS
std::vector< uint8_t > move_suspect
std::vector< uint8_t > dilated_image
int min_section_with_enough_edges
bool movement_from_last_success
void sum_per_section(std::vector< double > &sum_weights_per_section, std::vector< byte > const §ion_map, std::vector< double > const &weights, size_t num_of_sections)
std::vector< byte > section_map_edges
std::vector< uint8_t > logic_edges
GLint GLsizei GLsizei height
uint8_t dilation_calc(std::vector< T > const &sub_image, std::vector< uint8_t > const &mask)
std::vector< double > sum_weights_per_section
double dir_std_th[N_BASIC_DIRECTIONS]
double saturation_ratio_th
std::vector< byte > section_map
bool check_edges_dir_spread(const std::vector< double > &directions, const std::vector< double > &subpixels_x, const std::vector< double > &subpixels_y, size_t width, size_t height, const params &p)
#define AC_LOG(TYPE, MSG)
bool check_saturation(const std::vector< ir_t > &ir_frame, size_t width, size_t height, const params &p)
size_t num_of_sections_for_edge_distribution_y
double grad_dir_ratio_prep
std::vector< double > subpixels_y
static void abs_values(std::vector< double > &vec_in)
double edge_distribution_min_max_ratio
bool is_scene_valid(input_validity_data *data=nullptr)
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
double min_weighted_edge_per_section_rgb
std::vector< double > edges_IDT
void gaussian_filter(std::vector< uint8_t > const &lum_frame, std::vector< uint8_t > const &prev_lum_frame, std::vector< double > &yuy_diff, std::vector< double > &gaussian_filtered_image, size_t width, size_t height)
std::vector< uint8_t > get_logic_edges(std::vector< double > const &edges)
int minimal_full_directions
std::vector< double > gauss_convolution(std::vector< T > const &image, size_t image_width, size_t image_height, size_t mask_width, size_t mask_height, std::function< double(std::vector< T > const &sub_image) > convolution_operation)
bool movement_from_prev_frame
void section_per_pixel(frame_data const &, size_t section_w, size_t section_h, byte *section_map)
std::vector< double > directions
std::vector< double > sum_weights_per_section
std::vector< double > weights
size_t num_of_sections_for_edge_distribution_x
double pix_per_section_rgb_th
std::string to_string(T value)