| /* |
| |
| * Copyright (c) 2012-2017 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "test_engine/test.h" |
| #include <VX/vx.h> |
| #include <VX/vxu.h> |
| #include <math.h> |
| |
| #include "shared_functions.h" |
| |
| #define VX_GAUSSIAN_PYRAMID_TOLERANCE 1 |
| |
| TESTCASE(GaussianPyramid, CT_VXContext, ct_setup_vx_context, 0) |
| |
| |
| TEST(GaussianPyramid, testNodeCreation) |
| { |
| vx_context context = context_->vx_context_; |
| vx_image input = 0; |
| vx_pyramid pyr = 0; |
| vx_graph graph = 0; |
| vx_node node = 0; |
| const vx_size levels = 4; |
| const vx_float32 scale = VX_SCALE_PYRAMID_HALF; |
| const vx_uint32 width = 640; |
| const vx_uint32 height = 480; |
| const vx_df_image format = VX_DF_IMAGE_U8; |
| |
| ASSERT_VX_OBJECT(input = vxCreateImage(context, width, height, format), VX_TYPE_IMAGE); |
| |
| ASSERT_VX_OBJECT(pyr = vxCreatePyramid(context, levels, scale, width, height, format), VX_TYPE_PYRAMID); |
| |
| { |
| vx_size ch_levels; |
| vx_float32 ch_scale; |
| vx_uint32 ch_width, ch_height; |
| vx_df_image ch_format; |
| |
| VX_CALL(vxQueryPyramid(pyr, VX_PYRAMID_LEVELS, &ch_levels, sizeof(ch_levels))); |
| if (levels != ch_levels) |
| { |
| CT_FAIL("check for pyramid attribute VX_PYRAMID_LEVELS failed\n"); |
| } |
| VX_CALL(vxQueryPyramid(pyr, VX_PYRAMID_SCALE, &ch_scale, sizeof(ch_scale))); |
| if (scale != ch_scale) |
| { |
| CT_FAIL("check for pyramid attribute VX_PYRAMID_SCALE failed\n"); |
| } |
| VX_CALL(vxQueryPyramid(pyr, VX_PYRAMID_WIDTH, &ch_width, sizeof(ch_width))); |
| if (width != ch_width) |
| { |
| CT_FAIL("check for pyramid attribute VX_PYRAMID_WIDTH failed\n"); |
| } |
| VX_CALL(vxQueryPyramid(pyr, VX_PYRAMID_HEIGHT, &ch_height, sizeof(ch_height))); |
| if (height != ch_height) |
| { |
| CT_FAIL("check for pyramid attribute VX_PYRAMID_HEIGHT failed\n"); |
| } |
| VX_CALL(vxQueryPyramid(pyr, VX_PYRAMID_FORMAT, &ch_format, sizeof(ch_format))); |
| if (format != ch_format) |
| { |
| CT_FAIL("check for pyramid attribute VX_PYRAMID_FORMAT failed\n"); |
| } |
| } |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| |
| ASSERT_VX_OBJECT(node = vxGaussianPyramidNode(graph, input, pyr), VX_TYPE_NODE); |
| |
| VX_CALL(vxVerifyGraph(graph)); |
| |
| VX_CALL(vxReleaseNode(&node)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| VX_CALL(vxReleasePyramid(&pyr)); |
| VX_CALL(vxReleaseImage(&input)); |
| |
| ASSERT(node == 0); |
| ASSERT(graph == 0); |
| ASSERT(pyr == 0); |
| ASSERT(input == 0); |
| } |
| |
| #define LEVELS_COUNT_MAX 7 |
| |
| static CT_Image gaussian_pyramid_generate_random(const char* fileName, int width, int height) |
| { |
| CT_Image image; |
| |
| ASSERT_NO_FAILURE_(return 0, |
| image = ct_allocate_ct_image_random(width, height, VX_DF_IMAGE_U8, &CT()->seed_, 0, 256)); |
| |
| return image; |
| } |
| |
| static CT_Image gaussian_pyramid_read_image(const char* fileName, int width, int height) |
| { |
| CT_Image image = NULL; |
| ASSERT_(return 0, width == 0 && height == 0); |
| image = ct_read_image(fileName, 1); |
| ASSERT_(return 0, image); |
| ASSERT_(return 0, image->format == VX_DF_IMAGE_U8); |
| return image; |
| } |
| |
| static int32_t gaussian5x5_pyramid_get(int32_t *values) |
| { |
| int32_t res = 1 * (values[ 0] + values[ 4] + values[20] + values[24]) + |
| 4 * (values[ 1] + values[ 3] + values[ 5] + values[ 9] + values[15] + values[19] + values[21] + values[23]) + |
| 6 * (values[ 2] + values[10] + values[14] + values[22]) + |
| 16 * (values[ 6] + values[ 8] + values[16] + values[18]) + |
| 24 * (values[ 7] + values[11] + values[13] + values[17]) + |
| 36 * values[12]; |
| res = res >> 8; |
| return res; |
| } |
| |
| static uint8_t gaussian5x5_pyramid_calculate(CT_Image src, uint32_t x, uint32_t y) |
| { |
| int32_t values[25] = { |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 2, y - 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 1, y - 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 0, y - 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 1, y - 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 2, y - 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 2, y - 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 1, y - 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 0, y - 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 1, y - 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 2, y - 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 2, y - 0), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 1, y - 0), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 0, y - 0), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 1, y - 0), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 2, y - 0), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 2, y + 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 1, y + 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 0, y + 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 1, y + 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 2, y + 1), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 2, y + 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x - 1, y + 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 0, y + 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 1, y + 2), |
| (int32_t)*CT_IMAGE_DATA_PTR_8U(src, x + 2, y + 2), |
| }; |
| return (uint8_t)gaussian5x5_pyramid_get(values); |
| } |
| |
| static uint8_t gaussian5x5_calculate_replicate(CT_Image src, uint32_t x_, uint32_t y_) |
| { |
| int32_t x = (int)x_; |
| int32_t y = (int)y_; |
| int32_t values[25] = { |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 2, y - 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 1, y - 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 0, y - 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 1, y - 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 2, y - 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 2, y - 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 1, y - 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 0, y - 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 1, y - 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 2, y - 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 2, y - 0), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 1, y - 0), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 0, y - 0), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 1, y - 0), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 2, y - 0), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 2, y + 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 1, y + 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 0, y + 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 1, y + 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 2, y + 1), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 2, y + 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x - 1, y + 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 0, y + 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 1, y + 2), |
| (int32_t)CT_IMAGE_DATA_REPLICATE_8U(src, x + 2, y + 2), |
| }; |
| return (uint8_t)gaussian5x5_pyramid_get(values); |
| } |
| |
| static uint8_t gaussian5x5_calculate_constant(CT_Image src, uint32_t x_, uint32_t y_, vx_uint32 constant_value) |
| { |
| int32_t x = (int)x_; |
| int32_t y = (int)y_; |
| int32_t values[25] = { |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 2, y - 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 1, y - 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 0, y - 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 1, y - 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 2, y - 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 2, y - 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 1, y - 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 0, y - 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 1, y - 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 2, y - 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 2, y - 0, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 1, y - 0, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 0, y - 0, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 1, y - 0, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 2, y - 0, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 2, y + 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 1, y + 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 0, y + 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 1, y + 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 2, y + 1, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 2, y + 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x - 1, y + 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 0, y + 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 1, y + 2, constant_value), |
| (int32_t)CT_IMAGE_DATA_CONSTANT_8U(src, x + 2, y + 2, constant_value), |
| }; |
| return (uint8_t)gaussian5x5_pyramid_get(values); |
| } |
| |
| static vx_int32 gaussian_pyramid_get_pixel(CT_Image input, int x, int y, vx_border_t border, int level) |
| { |
| if (border.mode == VX_BORDER_UNDEFINED) |
| { |
| if (x >= 2 + level && y >= 2 + level && x < (int)input->width - 2 - level && y < (int)input->height - 2 - level) |
| return gaussian5x5_pyramid_calculate(input, x, y); |
| else |
| return -1; |
| } |
| else if (border.mode == VX_BORDER_REPLICATE) |
| { |
| return gaussian5x5_calculate_replicate(input, x, y); |
| } |
| else if (border.mode == VX_BORDER_CONSTANT) |
| { |
| return gaussian5x5_calculate_constant(input, x, y, border.constant_value.U32); |
| } |
| CT_FAIL_(return -1, "NOT IMPLEMENTED"); |
| } |
| |
| static void gaussian_pyramid_check_pixel(CT_Image input, CT_Image output, int x, int y, vx_border_t border, int level) |
| { |
| vx_uint8 res = *CT_IMAGE_DATA_PTR_8U(output, x, y); |
| |
| vx_float64 x_src = (((vx_float64)x + 0.5) * (vx_float64)input->width / (vx_float64)output->width) - 0.5; |
| vx_float64 y_src = (((vx_float64)y + 0.5) * (vx_float64)input->height / (vx_float64)output->height) - 0.5; |
| int x_min = (int)floor(x_src), y_min = (int)floor(y_src); |
| int sx, sy; |
| for (sy = 0; sy <= 1; sy++) |
| { |
| for (sx = 0; sx <= 1; sx++) |
| { |
| vx_int32 candidate = 0; |
| ASSERT_NO_FAILURE_(return, candidate = gaussian_pyramid_get_pixel(input, x_min + sx, y_min + sy, border, level)); |
| if (candidate == -1 || abs(candidate - res) <= VX_GAUSSIAN_PYRAMID_TOLERANCE) |
| return; |
| } |
| } |
| CT_FAIL_(return, "Check failed for pixel (%d, %d): %d", x, y, (int)res); |
| } |
| |
| static void gaussian_pyramid_check_image(CT_Image input, CT_Image output, vx_border_t border, vx_size level) |
| { |
| ASSERT(input && output); |
| if (0 == level) |
| { |
| EXPECT_EQ_CTIMAGE(input, output); |
| } |
| else |
| { |
| CT_FILL_IMAGE_8U(, output, |
| { |
| ASSERT_NO_FAILURE(gaussian_pyramid_check_pixel(input, output, x, y, border, (int)level)); |
| }); |
| } |
| } |
| |
| static const vx_float64 c_orbscale[] = |
| { |
| 1.000000000000000000000000000000e+00, |
| 8.408964152537146130583778358414e-01, |
| 7.071067811865475727373109293694e-01, |
| 5.946035575013605134486738279520e-01, |
| 5.000000000000000000000000000000e-01, |
| 4.204482076268573065291889179207e-01, |
| 3.535533905932737308575042334269e-01, |
| 2.973017787506802567243369139760e-01, |
| 2.500000000000000000000000000000e-01, |
| 2.102241038134286532645944589603e-01, |
| 1.767766952966368654287521167134e-01, |
| 1.486508893753401283621684569880e-01, |
| 1.250000000000000000000000000000e-01, |
| 1.051120519067143266322972294802e-01, |
| 8.838834764831843271437605835672e-02, |
| 7.432544468767006418108422849400e-02, |
| 6.250000000000000000000000000000e-02, |
| }; |
| |
| |
| static void gaussian_pyramid_check(CT_Image input, vx_pyramid pyr, vx_size levels, vx_float32 scale, vx_border_t border) |
| { |
| vx_uint32 level = 0; |
| vx_image output_image = 0; |
| CT_Image output_prev = NULL, output_cur = NULL; |
| vx_uint32 ref_width = input->width; |
| vx_uint32 ref_height = input->height; |
| |
| ASSERT(input && pyr && (1 < levels) && (level < sizeof(c_orbscale) / sizeof(float) )); |
| ASSERT_VX_OBJECT(output_image = vxGetPyramidLevel(pyr, 0), VX_TYPE_IMAGE); |
| ASSERT_NO_FAILURE(output_prev = ct_image_from_vx_image(output_image)); |
| VX_CALL(vxReleaseImage(&output_image)); |
| ASSERT(output_image == 0); |
| |
| gaussian_pyramid_check_image(input, output_prev, border, 0); |
| if (CT_HasFailure()) |
| { |
| printf("=== Input ===\n"); |
| ct_dump_image_info(input); |
| printf("=== LEVEL %d ===\n", 0); |
| ct_dump_image_info(output_prev); |
| return; |
| } |
| |
| for (level = 1; level < levels; level++) |
| { |
| ASSERT_VX_OBJECT(output_image = vxGetPyramidLevel(pyr, level), VX_TYPE_IMAGE); |
| ASSERT_NO_FAILURE(output_cur = ct_image_from_vx_image(output_image)); |
| VX_CALL(vxReleaseImage(&output_image)); |
| ASSERT(output_image == 0); |
| |
| if (VX_SCALE_PYRAMID_ORB == scale) |
| { |
| vx_float64 orb_scale = c_orbscale[level]; |
| if ( (output_cur->width != ceil(orb_scale * ref_width)) || |
| (output_cur->height != ceil(orb_scale * ref_height))) |
| { |
| CT_FAIL_(return, "Check failed for size of level: %d", level); |
| } |
| } |
| else |
| { |
| if ( (output_cur->width != ceil(output_prev->width * scale)) || |
| (output_cur->height != ceil(output_prev->height * scale))) |
| { |
| CT_FAIL_(return, "Check failed for size of level: %d", level); |
| } |
| } |
| |
| gaussian_pyramid_check_image(output_prev, output_cur, border, level); |
| if (CT_HasFailure()) |
| { |
| printf("=== Input ===\n"); |
| ct_dump_image_info(output_prev); |
| printf("=== LEVEL %d ===\n", level); |
| ct_dump_image_info(output_cur); |
| return; |
| } |
| |
| output_prev = output_cur; |
| } |
| } |
| |
| |
| |
| static vx_uint8 gaussian_pyramid_reference_get_pixel(CT_Image prevLevel, int dst_width, int dst_height, int x, int y, vx_border_t border, int level) |
| { |
| vx_int32 candidate = -1; |
| vx_float64 x_src = (((vx_float64)x + 0.5) * (vx_float64)prevLevel->width / (vx_float64)dst_width) - 0.5; |
| vx_float64 y_src = (((vx_float64)y + 0.5) * (vx_float64)prevLevel->height / (vx_float64)dst_height) - 0.5; |
| int x_int = (int)floor(x_src), y_int = (int)floor(y_src); |
| vx_float64 x_f = x_src - x_int, y_f = y_src - y_int; |
| if (x_f >= 0.5) |
| x_int++; |
| if (y_f >= 0.5) |
| y_int++; |
| if (x_int >= (int)prevLevel->width) |
| x_int = prevLevel->width - 1; |
| if (y_int >= (int)prevLevel->height) |
| y_int = prevLevel->height - 1; |
| ASSERT_NO_FAILURE_(return 0, candidate = gaussian_pyramid_get_pixel(prevLevel, x_int, y_int, border, level)); |
| if (candidate == -1) |
| return 0; |
| return CT_CAST_U8(candidate); |
| } |
| |
| static CT_Image gaussian_pyramid_create_reference_image(CT_Image input, CT_Image prevLevel, vx_border_t border, vx_float32 scale, vx_size target_level) |
| { |
| vx_uint32 level = 0; |
| CT_Image dst; |
| vx_uint32 ref_width = input->width; |
| vx_uint32 ref_height = input->height; |
| vx_uint32 dst_width = input->width; |
| vx_uint32 dst_height = input->height; |
| |
| ASSERT_(return NULL, scale < 1.0); |
| ASSERT_(return NULL, input && (level < (sizeof(c_orbscale) / sizeof(float)))); |
| |
| ASSERT_(return NULL, input->format == VX_DF_IMAGE_U8); |
| |
| if (VX_SCALE_PYRAMID_HALF == scale) |
| { |
| dst_width = ref_width; |
| dst_height = ref_height; |
| for (level = 1; level <= target_level; level++) |
| { |
| dst_width = (vx_uint32)ceil(dst_width * scale); |
| dst_height = (vx_uint32)ceil(dst_height * scale); |
| } |
| } |
| else // if (VX_SCALE_PYRAMID_ORB == scale) |
| { |
| vx_float64 orb_scale = c_orbscale[target_level]; |
| dst_width = (vx_uint32)ceil(orb_scale * ref_width); |
| dst_height = (vx_uint32)ceil(orb_scale * ref_height); |
| } |
| |
| dst = ct_allocate_image(dst_width, dst_height, input->format); |
| |
| if (target_level == 0) |
| { |
| CT_FILL_IMAGE_8U(return 0, dst, |
| { |
| uint8_t res = *CT_IMAGE_DATA_PTR_8U(input, x, y); |
| *dst_data = res; |
| }); |
| } |
| else |
| { |
| CT_FILL_IMAGE_8U(return 0, dst, |
| { |
| uint8_t res = gaussian_pyramid_reference_get_pixel(prevLevel, dst_width, dst_height, x, y, border, (int)target_level); |
| *dst_data = res; |
| }); |
| } |
| |
| return dst; |
| } |
| |
| void gaussian_pyramid_fill_reference(CT_Image input, vx_pyramid pyr, vx_size levels, vx_float32 scale, vx_border_t border) |
| { |
| vx_uint32 level = 0; |
| vx_image output_image = 0; |
| CT_Image output_prev = NULL; |
| CT_Image output_cur = NULL; |
| vx_uint32 ref_width = input->width; |
| vx_uint32 ref_height = input->height; |
| |
| ASSERT(input && pyr && (levels < sizeof(c_orbscale) / sizeof(float) )); |
| ASSERT_VX_OBJECT(output_image = vxGetPyramidLevel(pyr, 0), VX_TYPE_IMAGE); |
| ASSERT_NO_FAILURE(output_prev = ct_image_from_vx_image(output_image)); |
| |
| CT_FILL_IMAGE_8U(return, output_prev, |
| { |
| uint8_t res = *CT_IMAGE_DATA_PTR_8U(input, x, y); |
| *dst_data = res; |
| }); |
| ASSERT_NO_FAILURE(ct_image_copyto_vx_image(output_image, output_prev)); |
| |
| VX_CALL(vxReleaseImage(&output_image)); |
| ASSERT(output_image == 0); |
| |
| for (level = 1; level < levels; level++) |
| { |
| ASSERT_VX_OBJECT(output_image = vxGetPyramidLevel(pyr, level), VX_TYPE_IMAGE); |
| ASSERT_NO_FAILURE(output_cur = ct_image_from_vx_image(output_image)); |
| |
| if (VX_SCALE_PYRAMID_ORB == scale) |
| { |
| vx_float64 orb_scale = c_orbscale[level]; |
| if ( (output_cur->width != ceil(ref_width * orb_scale)) || |
| (output_cur->height != ceil(ref_height * orb_scale))) |
| { |
| CT_FAIL_(return, "Check failed for size of level: %d", level); |
| } |
| } |
| else |
| { |
| if ( (output_cur->width != ceil(output_prev->width * scale)) || |
| (output_cur->height != ceil(output_prev->height * scale))) |
| { |
| CT_FAIL_(return, "Check failed for size of level: %d", level); |
| } |
| } |
| |
| ASSERT_NO_FAILURE(output_cur = gaussian_pyramid_create_reference_image(input, output_prev, border, scale, level)); |
| ASSERT_NO_FAILURE(ct_image_copyto_vx_image(output_image, output_cur)); |
| |
| VX_CALL(vxReleaseImage(&output_image)); |
| ASSERT(output_image == 0); |
| |
| output_prev = output_cur; |
| } |
| } |
| |
| |
| static vx_size gaussian_pyramid_calc_max_levels_count(int width, int height, vx_float32 scale) |
| { |
| vx_size level = 1; |
| while ((16 <= width) && (16 <= height) && level < LEVELS_COUNT_MAX) |
| { |
| level++; |
| width = (int)ceil((vx_float64)width * scale); |
| height = (int)ceil((vx_float64)height * scale); |
| } |
| return level; |
| } |
| |
| typedef struct { |
| const char* testName; |
| CT_Image (*generator)(const char* fileName, int width, int height); |
| const char* fileName; |
| vx_border_t border; |
| int width, height; |
| vx_float32 scale; |
| } Arg; |
| |
| #define ADD_VX_SCALE(testArgName, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(testArgName "/VX_SCALE_PYRAMID_HALF", __VA_ARGS__, VX_SCALE_PYRAMID_HALF)), \ |
| CT_EXPAND(nextmacro(testArgName "/VX_SCALE_PYRAMID_ORB", __VA_ARGS__, VX_SCALE_PYRAMID_ORB)) |
| |
| #define PARAMETERS \ |
| CT_GENERATE_PARAMETERS("randomInput", ADD_VX_BORDERS_REQUIRE_UNDEFINED_ONLY, ADD_SIZE_SMALL_SET, ADD_VX_SCALE, ARG, gaussian_pyramid_generate_random, NULL), \ |
| CT_GENERATE_PARAMETERS("lena", ADD_VX_BORDERS_REQUIRE_UNDEFINED_ONLY, ADD_SIZE_NONE, ADD_VX_SCALE, ARG, gaussian_pyramid_read_image, "lena.bmp") |
| |
| TEST_WITH_ARG(GaussianPyramid, testGraphProcessing, Arg, |
| PARAMETERS |
| ) |
| { |
| vx_size levels; |
| |
| vx_context context = context_->vx_context_; |
| vx_image input_image = 0; |
| vx_pyramid pyr = 0; |
| vx_graph graph = 0; |
| vx_node node = 0; |
| |
| CT_Image input = NULL; |
| |
| vx_border_t border = arg_->border; |
| |
| ASSERT(arg_->scale < 1.0); |
| |
| ASSERT_NO_FAILURE(input = arg_->generator( arg_->fileName, arg_->width, arg_->height)); |
| ASSERT_VX_OBJECT(input_image = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE); |
| |
| levels = gaussian_pyramid_calc_max_levels_count(input->width, input->height, arg_->scale); |
| |
| ASSERT_VX_OBJECT(pyr = vxCreatePyramid(context, levels, arg_->scale, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_PYRAMID); |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| |
| ASSERT_VX_OBJECT(node = vxGaussianPyramidNode(graph, input_image, pyr), VX_TYPE_NODE); |
| |
| if (border.mode != VX_BORDER_UNDEFINED) |
| VX_CALL(vxSetNodeAttribute(node, VX_NODE_BORDER, &border, sizeof(border))); |
| |
| VX_CALL(vxVerifyGraph(graph)); |
| VX_CALL(vxProcessGraph(graph)); |
| |
| CT_ASSERT_NO_FAILURE_(, gaussian_pyramid_check(input, pyr, levels, arg_->scale, arg_->border)); |
| |
| VX_CALL(vxReleaseNode(&node)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| ASSERT(node == 0); |
| ASSERT(graph == 0); |
| |
| VX_CALL(vxReleasePyramid(&pyr)); |
| VX_CALL(vxReleaseImage(&input_image)); |
| ASSERT(pyr == 0); |
| ASSERT(input_image == 0); |
| } |
| |
| |
| TEST_WITH_ARG(GaussianPyramid, testImmediateProcessing, Arg, |
| PARAMETERS |
| ) |
| { |
| vx_size levels; |
| |
| vx_context context = context_->vx_context_; |
| vx_image input_image = 0; |
| vx_pyramid pyr = 0; |
| |
| CT_Image input = NULL; |
| |
| vx_border_t border = arg_->border; |
| |
| ASSERT_NO_FAILURE(input = arg_->generator( arg_->fileName, arg_->width, arg_->height)); |
| |
| ASSERT_VX_OBJECT(input_image = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE); |
| |
| levels = gaussian_pyramid_calc_max_levels_count(input->width, input->height, arg_->scale); |
| |
| ASSERT_VX_OBJECT(pyr = vxCreatePyramid(context, levels, arg_->scale, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_PYRAMID); |
| |
| VX_CALL(vxSetContextAttribute(context, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border))); |
| |
| VX_CALL(vxuGaussianPyramid(context, input_image, pyr)); |
| |
| CT_ASSERT_NO_FAILURE_(, gaussian_pyramid_check(input, pyr, levels, arg_->scale, arg_->border)); |
| |
| VX_CALL(vxReleasePyramid(&pyr)); |
| VX_CALL(vxReleaseImage(&input_image)); |
| ASSERT(pyr == 0); |
| ASSERT(input_image == 0); |
| } |
| |
| TEST_WITH_ARG(GaussianPyramid, testReference, Arg, |
| PARAMETERS |
| ) |
| { |
| vx_size levels; |
| |
| vx_context context = context_->vx_context_; |
| vx_image input_image = 0; |
| vx_pyramid pyr = 0; |
| |
| CT_Image input = NULL; |
| |
| vx_border_t border = arg_->border; |
| |
| ASSERT_NO_FAILURE(input = arg_->generator( arg_->fileName, arg_->width, arg_->height)); |
| |
| ASSERT_VX_OBJECT(input_image = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE); |
| |
| levels = gaussian_pyramid_calc_max_levels_count(input->width, input->height, arg_->scale); |
| |
| ASSERT_VX_OBJECT(pyr = vxCreatePyramid(context, levels, arg_->scale, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_PYRAMID); |
| |
| ASSERT_NO_FAILURE(gaussian_pyramid_fill_reference(input, pyr, levels, arg_->scale, border)); |
| |
| CT_ASSERT_NO_FAILURE_(, gaussian_pyramid_check(input, pyr, levels, arg_->scale, arg_->border)); |
| |
| VX_CALL(vxReleasePyramid(&pyr)); |
| VX_CALL(vxReleaseImage(&input_image)); |
| ASSERT(pyr == 0); |
| ASSERT(input_image == 0); |
| } |
| |
| TESTCASE_TESTS(GaussianPyramid, |
| testNodeCreation, |
| testGraphProcessing, |
| testImmediateProcessing, |
| testReference |
| ) |
| |
| |
| |