blob: 1130214ccf47f99aa77a33569ca45fa326d3ec95 [file] [log] [blame]
/*
* 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 <math.h>
#include <string.h>
#include <VX/vx.h>
#include <VX/vxu.h>
#include "test_engine/test.h"
#include "shared_functions.h"
#define VX_GAUSSIAN_PYRAMID_TOLERANCE 1
TESTCASE(LaplacianPyramid, CT_VXContext, ct_setup_vx_context, 0)
TEST(LaplacianPyramid, testNodeCreation)
{
vx_context context = context_->vx_context_;
vx_image input = 0;
vx_pyramid laplacian = 0;
vx_image output = 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_S16;
vx_uint32 w = width;
vx_uint32 h = height;
vx_size L = levels - 1;
ASSERT_VX_OBJECT(input = vxCreateImage(context, width, height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(laplacian = vxCreatePyramid(context, levels, scale, width, height, format), VX_TYPE_PYRAMID);
while (L--)
{
w = (vx_uint32)(w * scale);
h = (vx_uint32)(h * scale);
}
ASSERT_VX_OBJECT(output = vxCreateImage(context, w * scale, h * scale, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH);
ASSERT_VX_OBJECT(node = vxLaplacianPyramidNode(graph, input, laplacian, output), VX_TYPE_NODE);
VX_CALL(vxVerifyGraph(graph));
VX_CALL(vxReleaseImage(&input));
VX_CALL(vxReleasePyramid(&laplacian));
VX_CALL(vxReleaseImage(&output));
VX_CALL(vxReleaseNode(&node));
VX_CALL(vxReleaseGraph(&graph));
ASSERT(input == 0);
ASSERT(laplacian == 0);
ASSERT(output == 0);
ASSERT(node == 0);
ASSERT(graph == 0);
}
#define LEVELS_COUNT_MAX 7
static CT_Image own_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 own_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 vx_size own_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;
}
static vx_status ownCopyImage(vx_image input, vx_image output)
{
vx_status status = VX_SUCCESS; // assume success until an error occurs.
vx_uint32 p = 0;
vx_uint32 y = 0, x = 0;
vx_size planes = 0;
void* src;
void* dst;
vx_imagepatch_addressing_t src_addr;
vx_imagepatch_addressing_t dst_addr;
vx_rectangle_t src_rect, dst_rect;
vx_map_id map_id1;
vx_map_id map_id2;
vx_df_image src_format = 0;
vx_df_image out_format = 0;
status |= vxQueryImage(input, VX_IMAGE_PLANES, &planes, sizeof(planes));
vxQueryImage(output, VX_IMAGE_FORMAT, &out_format, sizeof(out_format));
vxQueryImage(input, VX_IMAGE_FORMAT, &src_format, sizeof(src_format));
status |= vxGetValidRegionImage(input, &src_rect);
status |= vxGetValidRegionImage(output, &dst_rect);
for (p = 0; p < planes && status == VX_SUCCESS; p++)
{
status = VX_SUCCESS;
src = NULL;
dst = NULL;
status |= vxMapImagePatch(input, &src_rect, p, &map_id1, &src_addr, &src, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, 0);
status |= vxMapImagePatch(output, &dst_rect, p, &map_id2, &dst_addr, &dst, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, 0);
for (y = 0; y < src_addr.dim_y && status == VX_SUCCESS; y += src_addr.step_y)
{
for (x = 0; x < src_addr.dim_x && status == VX_SUCCESS; x += src_addr.step_x)
{
void* srcp = vxFormatImagePatchAddress2d(src, x, y, &src_addr);
void* dstp = vxFormatImagePatchAddress2d(dst, x, y, &dst_addr);
vx_int32 out0 = (src_format == VX_DF_IMAGE_U8) ? (*(vx_uint8 *)srcp) : (*(vx_int16 *)srcp);
if (out_format == VX_DF_IMAGE_U8)
{
if (out0 > UINT8_MAX)
out0 = UINT8_MAX;
else if (out0 < 0)
out0 = 0;
*(vx_uint8 *)dstp = (vx_uint8)out0;
}
else
{
if (out0 > INT16_MAX)
out0 = INT16_MAX;
else if (out0 < INT16_MIN)
out0 = INT16_MIN;
*(vx_int16 *)dstp = (vx_int16)out0;
}
}
}
if (status == VX_SUCCESS)
{
status |= vxUnmapImagePatch(input, map_id1);
status |= vxUnmapImagePatch(output, map_id2);
}
}
return status;
}
static vx_bool own_read_pixel_16s(void *base, vx_imagepatch_addressing_t *addr,
vx_int32 x, vx_int32 y, const vx_border_t *borders, vx_int16 *pixel)
{
vx_uint32 bx;
vx_uint32 by;
vx_int16* bpixel;
vx_bool out_of_bounds = (vx_bool)(x < 0 || y < 0 || x >= (vx_int32)addr->dim_x || y >= (vx_int32)addr->dim_y);
if (out_of_bounds)
{
if (borders->mode == VX_BORDER_UNDEFINED)
return vx_false_e;
if (borders->mode == VX_BORDER_CONSTANT)
{
*pixel = (vx_int16)borders->constant_value.S16;
return vx_true_e;
}
}
// bounded x/y
bx = x < 0 ? 0 : x >= (vx_int32)addr->dim_x ? addr->dim_x - 1 : (vx_uint32)x;
by = y < 0 ? 0 : y >= (vx_int32)addr->dim_y ? addr->dim_y - 1 : (vx_uint32)y;
bpixel = (vx_int16*)vxFormatImagePatchAddress2d(base, bx, by, addr);
*pixel = *bpixel;
return vx_true_e;
}
static vx_status ownScaleImageNearestS16(vx_image src_image, vx_image dst_image, const vx_border_t *borders)
{
vx_status status = VX_SUCCESS;
vx_int32 x1, y1, x2, y2;
void* src_base = NULL;
void* dst_base = NULL;
vx_rectangle_t src_rect;
vx_rectangle_t dst_rect;
vx_imagepatch_addressing_t src_addr;
vx_imagepatch_addressing_t dst_addr;
vx_uint32 w1 = 0, h1 = 0, w2 = 0, h2 = 0;
vx_float32 wr, hr;
vx_map_id map_id1;
vx_map_id map_id2;
vxQueryImage(src_image, VX_IMAGE_WIDTH, &w1, sizeof(w1));
vxQueryImage(src_image, VX_IMAGE_HEIGHT, &h1, sizeof(h1));
vxQueryImage(dst_image, VX_IMAGE_WIDTH, &w2, sizeof(w2));
vxQueryImage(dst_image, VX_IMAGE_HEIGHT, &h2, sizeof(h2));
src_rect.start_x = src_rect.start_y = 0;
src_rect.end_x = w1;
src_rect.end_y = h1;
dst_rect.start_x = dst_rect.start_y = 0;
dst_rect.end_x = w2;
dst_rect.end_y = h2;
status = VX_SUCCESS;
status |= vxMapImagePatch(src_image, &src_rect, 0, &map_id1, &src_addr, &src_base, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, 0);
status |= vxMapImagePatch(dst_image, &dst_rect, 0, &map_id2, &dst_addr, &dst_base, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, 0);
wr = (vx_float32)w1 / (vx_float32)w2;
hr = (vx_float32)h1 / (vx_float32)h2;
for (y2 = 0; y2 < (vx_int32)dst_addr.dim_y; y2 += dst_addr.step_y)
{
for (x2 = 0; x2 < (vx_int32)dst_addr.dim_x; x2 += dst_addr.step_x)
{
vx_int16 v = 0;
vx_int16* dst = vxFormatImagePatchAddress2d(dst_base, x2, y2, &dst_addr);
vx_float32 x_src = ((vx_float32)x2 + 0.5f)*wr - 0.5f;
vx_float32 y_src = ((vx_float32)y2 + 0.5f)*hr - 0.5f;
vx_float32 x_min = floorf(x_src);
vx_float32 y_min = floorf(y_src);
x1 = (vx_int32)x_min;
y1 = (vx_int32)y_min;
if (x_src - x_min >= 0.5f)
x1++;
if (y_src - y_min >= 0.5f)
y1++;
if (dst && vx_true_e == own_read_pixel_16s(src_base, &src_addr, x1, y1, borders, &v))
*dst = v;
}
}
status |= vxUnmapImagePatch(src_image, map_id1);
status |= vxUnmapImagePatch(dst_image, map_id2);
return VX_SUCCESS;
}
static const vx_uint32 gaussian5x5scale = 256;
static const vx_int16 gaussian5x5[5][5] =
{
{ 1, 4, 6, 4, 1 },
{ 4, 16, 24, 16, 4 },
{ 6, 24, 36, 24, 6 },
{ 4, 16, 24, 16, 4 },
{ 1, 4, 6, 4, 1 }
};
static vx_convolution vxCreateGaussian5x5Convolution(vx_context context)
{
vx_convolution conv = vxCreateConvolution(context, 5, 5);
vx_status status = vxCopyConvolutionCoefficients(conv, (vx_int16 *)gaussian5x5, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
if (status != VX_SUCCESS)
{
vxReleaseConvolution(&conv);
return NULL;
}
status = vxSetConvolutionAttribute(conv, VX_CONVOLUTION_SCALE, (void *)&gaussian5x5scale, sizeof(vx_uint32));
if (status != VX_SUCCESS)
{
vxReleaseConvolution(&conv);
return NULL;
}
return conv;
}
void readRect(const void *base, const vx_imagepatch_addressing_t *addr, const vx_border_t *borders, vx_df_image type,
vx_uint32 center_x, vx_uint32 center_y, vx_uint32 radius_x, vx_uint32 radius_y, void *destination)
{
vx_int32 width = (vx_int32)addr->dim_x, height = (vx_int32)addr->dim_y;
vx_int32 stride_y = addr->stride_y;
vx_int32 stride_x = addr->stride_x;
const vx_uint8 *ptr = (const vx_uint8 *)base;
vx_int32 ky, kx;
vx_uint32 dest_index = 0;
// kx, kx - kernel x and y
if (borders->mode == VX_BORDER_REPLICATE || borders->mode == VX_BORDER_UNDEFINED)
{
for (ky = -(int32_t)radius_y; ky <= (int32_t)radius_y; ++ky)
{
vx_int32 y = (vx_int32)(center_y + ky);
y = y < 0 ? 0 : (y >= height ? height - 1 : y);
for (kx = -(int32_t)radius_x; kx <= (int32_t)radius_x; ++kx, ++dest_index)
{
vx_int32 x = (int32_t)(center_x + kx);
x = x < 0 ? 0 : (x >= width ? width - 1 : x);
switch (type)
{
case VX_DF_IMAGE_U8:
((vx_uint8*)destination)[dest_index] = *(vx_uint8*)(ptr + y*stride_y + x*stride_x);
break;
case VX_DF_IMAGE_S16:
case VX_DF_IMAGE_U16:
((vx_uint16*)destination)[dest_index] = *(vx_uint16*)(ptr + y*stride_y + x*stride_x);
break;
case VX_DF_IMAGE_S32:
case VX_DF_IMAGE_U32:
((vx_uint32*)destination)[dest_index] = *(vx_uint32*)(ptr + y*stride_y + x*stride_x);
break;
default:
abort();
}
}
}
}
else if (borders->mode == VX_BORDER_CONSTANT)
{
vx_pixel_value_t cval = borders->constant_value;
for (ky = -(int32_t)radius_y; ky <= (int32_t)radius_y; ++ky)
{
vx_int32 y = (vx_int32)(center_y + ky);
int ccase_y = y < 0 || y >= height;
for (kx = -(int32_t)radius_x; kx <= (int32_t)radius_x; ++kx, ++dest_index)
{
vx_int32 x = (int32_t)(center_x + kx);
int ccase = ccase_y || x < 0 || x >= width;
switch (type)
{
case VX_DF_IMAGE_U8:
if (!ccase)
((vx_uint8*)destination)[dest_index] = *(vx_uint8*)(ptr + y*stride_y + x*stride_x);
else
((vx_uint8*)destination)[dest_index] = (vx_uint8)cval.U8;
break;
case VX_DF_IMAGE_S16:
case VX_DF_IMAGE_U16:
if (!ccase)
((vx_uint16*)destination)[dest_index] = *(vx_uint16*)(ptr + y*stride_y + x*stride_x);
else
((vx_uint16*)destination)[dest_index] = (vx_uint16)cval.U16;
break;
case VX_DF_IMAGE_S32:
case VX_DF_IMAGE_U32:
if (!ccase)
((vx_uint32*)destination)[dest_index] = *(vx_uint32*)(ptr + y*stride_y + x*stride_x);
else
((vx_uint32*)destination)[dest_index] = (vx_uint32)cval.U32;
break;
default:
abort();
}
}
}
}
else
abort();
}
#define CONV_DIM 5
#define CONV_DIM_HALF CONV_DIM / 2
#define INSERT_ZERO_Y(slice, y) for (int i=0; i<CONV_DIM; i++) slice[CONV_DIM*(1-y)+i] = 0;
#define INSERT_VALUES_Y(slice, y) for (int i=0; i<CONV_DIM; i++) slice[CONV_DIM*(high_y-y)+i+CONV_DIM_HALF*CONV_DIM] = slice[CONV_DIM*(high_y-y)+i];
#define INSERT_ZERO_X(slice, x) for (int i=0; i<CONV_DIM; i++) slice[CONV_DIM*i+1-x] = 0;
#define INSERT_VALUES_X(slice, x) for (int i=0; i<CONV_DIM; i++) slice[CONV_DIM*i+(high_x-x)+CONV_DIM_HALF] = slice[CONV_DIM*i+(high_x-x)];
#define C_MAX_CONVOLUTION_DIM 15
vx_status convolve(vx_image src, vx_convolution conv, vx_image dst, vx_border_t *bordermode)
{
vx_int32 y, x, i;
void *src_base = NULL;
void *dst_base = NULL;
vx_imagepatch_addressing_t src_addr, dst_addr;
vx_rectangle_t rect;
vx_size conv_width, conv_height;
vx_int32 conv_radius_x, conv_radius_y;
vx_int16 conv_mat[C_MAX_CONVOLUTION_DIM * C_MAX_CONVOLUTION_DIM] = { 0 };
vx_int32 sum = 0, value = 0;
vx_uint32 scale = 1;
vx_df_image src_format = 0;
vx_df_image dst_format = 0;
vx_status status = VX_SUCCESS;
vx_int32 low_x, low_y, high_x, high_y;
status |= vxQueryImage(src, VX_IMAGE_FORMAT, &src_format, sizeof(src_format));
status |= vxQueryImage(dst, VX_IMAGE_FORMAT, &dst_format, sizeof(dst_format));
status |= vxQueryConvolution(conv, VX_CONVOLUTION_COLUMNS, &conv_width, sizeof(conv_width));
status |= vxQueryConvolution(conv, VX_CONVOLUTION_ROWS, &conv_height, sizeof(conv_height));
status |= vxQueryConvolution(conv, VX_CONVOLUTION_SCALE, &scale, sizeof(scale));
conv_radius_x = (vx_int32)conv_width / 2;
conv_radius_y = (vx_int32)conv_height / 2;
status |= vxCopyConvolutionCoefficients(conv, conv_mat, VX_READ_ONLY, VX_MEMORY_TYPE_HOST);
status |= vxGetValidRegionImage(src, &rect);
status |= vxAccessImagePatch(src, &rect, 0, &src_addr, &src_base, VX_READ_ONLY);
status |= vxAccessImagePatch(dst, &rect, 0, &dst_addr, &dst_base, VX_WRITE_ONLY);
low_x = 0;
high_x = src_addr.dim_x;
low_y = 0;
high_y = src_addr.dim_y;
for (y = low_y; y < high_y; ++y)
{
for (x = low_x; x < high_x; ++x)
{
sum = 0;
if (src_format == VX_DF_IMAGE_U8)
{
vx_uint8 slice[C_MAX_CONVOLUTION_DIM * C_MAX_CONVOLUTION_DIM] = { 0 };
readRect(src_base, &src_addr, bordermode, src_format, x, y, conv_radius_x, conv_radius_y, slice);
// purpose of this section is to compensate extra terms caused by replicate border mode (it is the only one allowed)
if (y < CONV_DIM_HALF)
{
INSERT_ZERO_Y(slice, y)
}
else if (y >= high_y - CONV_DIM_HALF)
{
INSERT_VALUES_Y(slice, y)
}
if (x < CONV_DIM_HALF)
{
INSERT_ZERO_X(slice, x)
}
else if (x >= high_x - CONV_DIM_HALF)
{
INSERT_VALUES_X(slice, x)
}
for (i = 0; i < (vx_int32)(conv_width * conv_height); ++i)
sum += conv_mat[conv_width * conv_height - 1 - i] * slice[i];
}
else if (src_format == VX_DF_IMAGE_S16)
{
vx_int16 slice[C_MAX_CONVOLUTION_DIM * C_MAX_CONVOLUTION_DIM] = { 0 };
readRect(src_base, &src_addr, bordermode, src_format, x, y, conv_radius_x, conv_radius_y, slice);
if (y < CONV_DIM_HALF)
{
INSERT_ZERO_Y(slice, y)
}
else if (y >= high_y - CONV_DIM_HALF)
{
INSERT_VALUES_Y(slice, y)
}
if (x < CONV_DIM_HALF)
{
INSERT_ZERO_X(slice, x)
}
else if (x >= high_x - CONV_DIM_HALF)
{
INSERT_VALUES_X(slice, x)
}
for (i = 0; i < (vx_int32)(conv_width * conv_height); ++i)
sum += conv_mat[conv_width * conv_height - 1 - i] * slice[i];
}
value = sum / (vx_int32)scale;
if (dst_format == VX_DF_IMAGE_U8)
{
vx_uint8 *dstp = vxFormatImagePatchAddress2d(dst_base, x, y, &dst_addr);
if (value < 0) *dstp = 0;
else if (value > UINT8_MAX) *dstp = UINT8_MAX;
else *dstp = value;
}
else if (dst_format == VX_DF_IMAGE_S16)
{
vx_int16 *dstp = vxFormatImagePatchAddress2d(dst_base, x, y, &dst_addr);
if (value < INT16_MIN) *dstp = INT16_MIN;
else if (value > INT16_MAX) *dstp = INT16_MAX;
else *dstp = value;
}
}
}
status |= vxCommitImagePatch(src, NULL, 0, &src_addr, src_base);
status |= vxCommitImagePatch(dst, &rect, 0, &dst_addr, dst_base);
return status;
}
static vx_status upsampleImage(vx_context context, vx_uint32 width, vx_uint32 height, vx_image filling, vx_convolution conv, vx_image upsample, vx_border_t *border)
{
vx_status status = VX_SUCCESS;
vx_df_image format, filling_format;
format = VX_DF_IMAGE_U8;
vx_image tmp = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
status |= vxQueryImage(filling, VX_IMAGE_FORMAT, &filling_format, sizeof(filling_format));
vx_rectangle_t tmp_rect, filling_rect;
vx_imagepatch_addressing_t tmp_addr = VX_IMAGEPATCH_ADDR_INIT;
vx_imagepatch_addressing_t filling_addr = VX_IMAGEPATCH_ADDR_INIT;
vx_map_id tmp_map_id, filling_map_id;
void *tmp_base = NULL;
void *filling_base = NULL;
status = vxGetValidRegionImage(tmp, &tmp_rect);
status |= vxMapImagePatch(tmp, &tmp_rect, 0, &tmp_map_id, &tmp_addr, (void **)&tmp_base, VX_READ_AND_WRITE, VX_MEMORY_TYPE_HOST, 0);
status = vxGetValidRegionImage(filling, &filling_rect);
status |= vxMapImagePatch(filling, &filling_rect, 0, &filling_map_id, &filling_addr, (void **)&filling_base, VX_READ_AND_WRITE, VX_MEMORY_TYPE_HOST, 0);
for (vx_uint32 ix = 0; ix < width; ix++)
{
for (vx_uint32 iy = 0; iy < height; iy++)
{
void* tmp_datap = vxFormatImagePatchAddress2d(tmp_base, ix, iy, &tmp_addr);
if (iy % 2 != 0 || ix % 2 != 0)
{
if (format == VX_DF_IMAGE_U8)
*(vx_uint8 *)tmp_datap = (vx_uint8)0;
else
*(vx_int16 *)tmp_datap = (vx_int16)0;
}
else
{
void* filling_tmp = vxFormatImagePatchAddress2d(filling_base, ix / 2, iy / 2, &filling_addr);
vx_int32 filling_data = filling_format == VX_DF_IMAGE_U8 ? *(vx_uint8 *)filling_tmp : *(vx_int16 *)filling_tmp;
if (format == VX_DF_IMAGE_U8)
{
if (filling_data > UINT8_MAX)
filling_data = UINT8_MAX;
else if (filling_data < 0)
filling_data = 0;
*(vx_uint8 *)tmp_datap = (vx_uint8)filling_data;
}
else
{
if (filling_data > INT16_MAX)
filling_data = INT16_MAX;
else if (filling_data < INT16_MIN)
filling_data = INT16_MIN;
*(vx_int16 *)tmp_datap = (vx_int16)filling_data;
}
}
}
}
status |= vxUnmapImagePatch(tmp, tmp_map_id);
status |= vxUnmapImagePatch(filling, filling_map_id);
status |= convolve(tmp, conv, upsample, border);
vx_rectangle_t upsample_rect;
vx_imagepatch_addressing_t upsample_addr = VX_IMAGEPATCH_ADDR_INIT;
vx_map_id upsample_map_id;
void * upsample_base = NULL;
vx_df_image upsample_format;
status |= vxQueryImage(upsample, VX_IMAGE_FORMAT, &upsample_format, sizeof(upsample_format));
status = vxGetValidRegionImage(upsample, &upsample_rect);
status |= vxMapImagePatch(upsample, &upsample_rect, 0, &upsample_map_id, &upsample_addr, (void **)&upsample_base, VX_READ_AND_WRITE, VX_MEMORY_TYPE_HOST, 0);
for (vx_uint32 ix = 0; ix < width; ix++)
{
for (vx_uint32 iy = 0; iy < height; iy++)
{
void* upsample_p = vxFormatImagePatchAddress2d(upsample_base, ix, iy, &upsample_addr);
vx_int32 upsample_data = upsample_format == VX_DF_IMAGE_U8 ? *(vx_uint8 *)upsample_p : *(vx_int16 *)upsample_p;
upsample_data *= 4;
if (upsample_format == VX_DF_IMAGE_U8)
{
if (upsample_data > UINT8_MAX)
upsample_data = UINT8_MAX;
else if (upsample_data < 0)
upsample_data = 0;
*(vx_uint8 *)upsample_p = (vx_uint8)upsample_data;
}
else
{
if (upsample_data > INT16_MAX)
upsample_data = INT16_MAX;
else if (upsample_data < INT16_MIN)
upsample_data = INT16_MIN;
*(vx_int16 *)upsample_p = (vx_int16)upsample_data;
}
}
}
status |= vxUnmapImagePatch(upsample, upsample_map_id);
status |= vxReleaseImage(&tmp);
return status;
}
static void own_laplacian_pyramid_reference(vx_context context, vx_border_t border, vx_image input, vx_pyramid laplacian, vx_image output)
{
vx_uint32 i;
vx_size levels = 0;
vx_uint32 width = 0;
vx_uint32 height = 0;
vx_df_image format = 0;
vx_pyramid gaussian = 0;
vx_convolution conv = 0;
border.mode = VX_BORDER_REPLICATE;
VX_CALL(vxSetContextAttribute(context, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border)));
VX_CALL(vxQueryPyramid(laplacian, VX_PYRAMID_LEVELS, &levels, sizeof(levels)));
VX_CALL(vxQueryImage(input, VX_IMAGE_WIDTH, &width, sizeof(width)));
VX_CALL(vxQueryImage(input, VX_IMAGE_HEIGHT, &height, sizeof(height)));
VX_CALL(vxQueryImage(input, VX_IMAGE_FORMAT, &format, sizeof(format)));
ASSERT_VX_OBJECT(gaussian = vxCreatePyramid(context, levels + 1, VX_SCALE_PYRAMID_HALF, width, height, VX_DF_IMAGE_U8), VX_TYPE_PYRAMID);
VX_CALL(vxuGaussianPyramid(context, input, gaussian));
ASSERT_VX_OBJECT(conv = vxCreateConvolution(context, 5, 5), VX_TYPE_CONVOLUTION);
VX_CALL(vxCopyConvolutionCoefficients(conv, (vx_int16*)gaussian5x5, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST));
VX_CALL(vxSetConvolutionAttribute(conv, VX_CONVOLUTION_SCALE, (void*)&gaussian5x5scale, sizeof(gaussian5x5scale)));
for (i = 0; i < levels; i++)
{
vx_uint32 w = 0;
vx_uint32 h = 0;
vx_image in1 = 0;
vx_image in2 = 0;
vx_image filter = 0;
vx_image out = 0;
ASSERT_VX_OBJECT(in1 = vxGetPyramidLevel(gaussian, i), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(in2 = vxGetPyramidLevel(gaussian, i + 1), VX_TYPE_IMAGE);
VX_CALL(vxQueryImage(in1, VX_IMAGE_WIDTH, &w, sizeof(vx_uint32)));
VX_CALL(vxQueryImage(in1, VX_IMAGE_HEIGHT, &h, sizeof(vx_uint32)));
ASSERT_VX_OBJECT(filter = vxCreateImage(context, w, h, VX_DF_IMAGE_S16), VX_TYPE_IMAGE);
border.mode = VX_BORDER_REPLICATE;
upsampleImage(context, w, h, in2, conv, filter, &border);
/* laplacian is S16 format */
ASSERT_VX_OBJECT(out = vxGetPyramidLevel(laplacian, i), VX_TYPE_IMAGE);
VX_CALL(vxuSubtract(context, in1, filter, VX_CONVERT_POLICY_SATURATE, out));
if (i == levels - 1)
{
vx_image tmp = vxGetPyramidLevel(gaussian, levels);
ownCopyImage(tmp, output);
VX_CALL(vxReleaseImage(&tmp));
}
VX_CALL(vxReleaseImage(&filter));
VX_CALL(vxReleaseImage(&in1));
VX_CALL(vxReleaseImage(&in2));
VX_CALL(vxReleaseImage(&out));
}
VX_CALL(vxReleasePyramid(&gaussian));
VX_CALL(vxReleaseConvolution(&conv));
ASSERT(conv == 0);
ASSERT(gaussian == 0);
return;
}
static void own_laplacian_pyramid_openvx(vx_context context, vx_border_t border, vx_image input, vx_pyramid laplacian, vx_image output)
{
vx_graph graph = 0;
vx_node node = 0;
ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH);
ASSERT_VX_OBJECT(node = vxLaplacianPyramidNode(graph, input, laplacian, output), VX_TYPE_NODE);
VX_CALL(vxSetNodeAttribute(node, VX_NODE_BORDER, &border, sizeof(border)));
VX_CALL(vxVerifyGraph(graph));
VX_CALL(vxProcessGraph(graph));
VX_CALL(vxReleaseNode(&node));
VX_CALL(vxReleaseGraph(&graph));
ASSERT(node == 0);
ASSERT(graph == 0);
return;
}
typedef struct
{
const char* testName;
CT_Image(*generator)(const char* fileName, int width, int height);
const char* fileName;
vx_border_t border;
int width;
int height;
} Arg;
#define ADD_SIZE_OWN_SET(testArgName, nextmacro, ...) \
CT_EXPAND(nextmacro(testArgName "/sz=128x128", __VA_ARGS__, 128, 128)), \
CT_EXPAND(nextmacro(testArgName "/sz=256x256", __VA_ARGS__, 256, 256)), \
CT_EXPAND(nextmacro(testArgName "/sz=640x480", __VA_ARGS__, 640, 480))
#define LAPLACIAN_PYRAMID_PARAMETERS \
CT_GENERATE_PARAMETERS("randomInput", ADD_VX_BORDERS_REQUIRE_UNDEFINED_ONLY, ADD_SIZE_OWN_SET, ARG, own_generate_random, NULL), \
CT_GENERATE_PARAMETERS("lena", ADD_VX_BORDERS_REQUIRE_UNDEFINED_ONLY, ADD_SIZE_NONE, ARG, own_read_image, "lena.bmp")
TEST_WITH_ARG(LaplacianPyramid, testGraphProcessing, Arg, LAPLACIAN_PYRAMID_PARAMETERS)
{
vx_context context = context_->vx_context_;
vx_size levels = 0;
vx_uint32 i;
vx_image src = 0;
vx_image ref_dst = 0;
vx_image tst_dst = 0;
vx_pyramid ref_pyr = 0;
vx_pyramid tst_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(src = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE);
levels = own_pyramid_calc_max_levels_count(input->width, input->height, VX_SCALE_PYRAMID_HALF) - 1;
{
vx_uint32 next_lev_width = input->width;
vx_uint32 next_lev_height = input->height;
ASSERT_VX_OBJECT(ref_pyr = vxCreatePyramid(context, levels, VX_SCALE_PYRAMID_HALF, input->width, input->height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
ASSERT_VX_OBJECT(tst_pyr = vxCreatePyramid(context, levels, VX_SCALE_PYRAMID_HALF, input->width, input->height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
for (i = 1; i < levels + 1; i++)
{
next_lev_width = (vx_uint32)ceilf(next_lev_width * VX_SCALE_PYRAMID_HALF);
next_lev_height = (vx_uint32)ceilf(next_lev_height * VX_SCALE_PYRAMID_HALF);
}
ASSERT_VX_OBJECT(ref_dst = vxCreateImage(context, next_lev_width, next_lev_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(tst_dst = vxCreateImage(context, next_lev_width, next_lev_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
}
own_laplacian_pyramid_reference(context, border, src, ref_pyr, ref_dst);
own_laplacian_pyramid_openvx(context, border, src, tst_pyr, tst_dst);
{
CT_Image ct_ref_dst = 0;
CT_Image ct_tst_dst = 0;
ASSERT_NO_FAILURE(ct_ref_dst = ct_image_from_vx_image(ref_dst));
ASSERT_NO_FAILURE(ct_tst_dst = ct_image_from_vx_image(tst_dst));
EXPECT_CTIMAGE_NEAR(ct_ref_dst, ct_tst_dst, 1);
for (i = 0; i < levels; i++)
{
CT_Image ct_ref_lev = 0;
CT_Image ct_tst_lev = 0;
vx_image ref_lev = 0;
vx_image tst_lev = 0;
ASSERT_VX_OBJECT(ref_lev = vxGetPyramidLevel(ref_pyr, i), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(tst_lev = vxGetPyramidLevel(tst_pyr, i), VX_TYPE_IMAGE);
ASSERT_NO_FAILURE(ct_ref_lev = ct_image_from_vx_image(ref_lev));
ASSERT_NO_FAILURE(ct_tst_lev = ct_image_from_vx_image(tst_lev));
EXPECT_CTIMAGE_NEAR(ct_ref_lev, ct_tst_lev, 1);
VX_CALL(vxReleaseImage(&ref_lev));
VX_CALL(vxReleaseImage(&tst_lev));
}
}
VX_CALL(vxReleaseImage(&src));
VX_CALL(vxReleasePyramid(&ref_pyr));
VX_CALL(vxReleasePyramid(&tst_pyr));
VX_CALL(vxReleaseImage(&ref_dst));
VX_CALL(vxReleaseImage(&tst_dst));
ASSERT(src == 0);
ASSERT(ref_pyr == 0);
ASSERT(tst_pyr == 0);
ASSERT(ref_dst == 0);
ASSERT(tst_dst == 0);
}
TEST_WITH_ARG(LaplacianPyramid, testImmediateProcessing, Arg, LAPLACIAN_PYRAMID_PARAMETERS)
{
vx_context context = context_->vx_context_;
vx_size levels = 0;
vx_uint32 i;
vx_image src = 0;
vx_image ref_dst = 0;
vx_image tst_dst = 0;
vx_pyramid ref_pyr = 0;
vx_pyramid tst_pyr = 0;
int undefined_border = 2; // 5x5 kernel border
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(src = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE);
levels = own_pyramid_calc_max_levels_count(input->width, input->height, VX_SCALE_PYRAMID_HALF) - 1;
{
vx_uint32 next_lev_width = input->width;
vx_uint32 next_lev_height = input->height;
ASSERT_VX_OBJECT(ref_pyr = vxCreatePyramid(context, levels, VX_SCALE_PYRAMID_HALF, input->width, input->height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
ASSERT_VX_OBJECT(tst_pyr = vxCreatePyramid(context, levels, VX_SCALE_PYRAMID_HALF, input->width, input->height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
for (i = 1; i < levels + 1; i++)
{
next_lev_width = (vx_uint32)ceilf(next_lev_width * VX_SCALE_PYRAMID_HALF);
next_lev_height = (vx_uint32)ceilf(next_lev_height * VX_SCALE_PYRAMID_HALF);
}
ASSERT_VX_OBJECT(ref_dst = vxCreateImage(context, next_lev_width, next_lev_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(tst_dst = vxCreateImage(context, next_lev_width, next_lev_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
}
own_laplacian_pyramid_reference(context, border, src, ref_pyr, ref_dst);
border.mode = VX_BORDER_REPLICATE;
VX_CALL(vxSetContextAttribute(context, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border)));
VX_CALL(vxuLaplacianPyramid(context, src, tst_pyr, tst_dst));
{
CT_Image ct_ref_dst = 0;
CT_Image ct_tst_dst = 0;
ASSERT_NO_FAILURE(ct_ref_dst = ct_image_from_vx_image(ref_dst));
ASSERT_NO_FAILURE(ct_tst_dst = ct_image_from_vx_image(tst_dst));
ASSERT_NO_FAILURE(ct_adjust_roi(ct_ref_dst, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border));
ASSERT_NO_FAILURE(ct_adjust_roi(ct_tst_dst, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border));
EXPECT_CTIMAGE_NEAR(ct_ref_dst, ct_tst_dst, 1);
for (i = 0; i < levels; i++)
{
CT_Image ct_ref_lev = 0;
CT_Image ct_tst_lev = 0;
vx_image ref_lev = 0;
vx_image tst_lev = 0;
ASSERT_VX_OBJECT(ref_lev = vxGetPyramidLevel(ref_pyr, i), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(tst_lev = vxGetPyramidLevel(tst_pyr, i), VX_TYPE_IMAGE);
ASSERT_NO_FAILURE(ct_ref_lev = ct_image_from_vx_image(ref_lev));
ASSERT_NO_FAILURE(ct_tst_lev = ct_image_from_vx_image(tst_lev));
ASSERT_NO_FAILURE(ct_adjust_roi(ct_ref_lev, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border));
ASSERT_NO_FAILURE(ct_adjust_roi(ct_tst_lev, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border, 2 * undefined_border));
EXPECT_CTIMAGE_NEAR(ct_ref_lev, ct_tst_lev, 1);
VX_CALL(vxReleaseImage(&ref_lev));
VX_CALL(vxReleaseImage(&tst_lev));
}
}
VX_CALL(vxReleaseImage(&src));
VX_CALL(vxReleasePyramid(&ref_pyr));
VX_CALL(vxReleasePyramid(&tst_pyr));
VX_CALL(vxReleaseImage(&ref_dst));
VX_CALL(vxReleaseImage(&tst_dst));
ASSERT(src == 0);
ASSERT(ref_pyr == 0);
ASSERT(tst_pyr == 0);
ASSERT(ref_dst == 0);
ASSERT(tst_dst == 0);
}
TESTCASE_TESTS(LaplacianPyramid,
testNodeCreation,
testGraphProcessing,
testImmediateProcessing
)
/* reconstruct image from laplacian pyramid */
#define VX_SCALE_PYRAMID_DOUBLE (2.0f)
TESTCASE(LaplacianReconstruct, CT_VXContext, ct_setup_vx_context, 0)
TEST(LaplacianReconstruct, testNodeCreation)
{
vx_context context = context_->vx_context_;
vx_pyramid laplacian = 0;
vx_image input = 0;
vx_image output = 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;
vx_size num_levels = levels;
vx_uint32 w = width;
vx_uint32 h = height;
while (num_levels--)
{
w = (vx_uint32)ceilf(w * scale);
h = (vx_uint32)ceilf(h * scale);
}
ASSERT_VX_OBJECT(input = vxCreateImage(context, w, h, VX_DF_IMAGE_S16), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(output = vxCreateImage(context, width, height, VX_DF_IMAGE_S16), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(laplacian = vxCreatePyramid(context, levels, scale, width, height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH);
ASSERT_VX_OBJECT(node = vxLaplacianReconstructNode(graph, laplacian, input, output), VX_TYPE_NODE);
VX_CALL(vxVerifyGraph(graph));
VX_CALL(vxReleaseImage(&input));
VX_CALL(vxReleasePyramid(&laplacian));
VX_CALL(vxReleaseImage(&output));
VX_CALL(vxReleaseNode(&node));
VX_CALL(vxReleaseGraph(&graph));
ASSERT(laplacian == 0);
ASSERT(input == 0);
ASSERT(output == 0);
ASSERT(node == 0);
ASSERT(graph == 0);
}
static void own_laplacian_reconstruct_reference(vx_context context, vx_border_t border, vx_pyramid laplacian, vx_image input, vx_image output)
{
vx_size i;
vx_size levels = 0;
vx_uint32 width = 0;
vx_uint32 height = 0;
vx_uint32 prev_lev_width = 0;
vx_uint32 prev_lev_height = 0;
vx_df_image format = 0;
vx_image pyr_level = 0;
vx_image filling = 0;
vx_image filter = 0;
vx_image out = 0;
vx_convolution conv;
VX_CALL(vxSetContextAttribute(context, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border)));
VX_CALL(vxQueryPyramid(laplacian, VX_PYRAMID_LEVELS, &levels, sizeof(vx_size)));
VX_CALL(vxQueryPyramid(laplacian, VX_PYRAMID_FORMAT, &format, sizeof(vx_df_image)));
VX_CALL(vxQueryImage(input, VX_IMAGE_WIDTH, &width, sizeof(vx_uint32)));
VX_CALL(vxQueryImage(input, VX_IMAGE_HEIGHT, &height, sizeof(vx_uint32)));
conv = vxCreateGaussian5x5Convolution(context);
prev_lev_width = (vx_uint32)ceilf(width * VX_SCALE_PYRAMID_DOUBLE);
prev_lev_height = (vx_uint32)ceilf(height * VX_SCALE_PYRAMID_DOUBLE);
ASSERT_VX_OBJECT(filling = vxCreateImage(context, width, height, format), VX_TYPE_IMAGE);
VX_CALL(ownCopyImage(input, filling));
for (i = 0; i < levels; i++)
{
ASSERT_VX_OBJECT(pyr_level = vxGetPyramidLevel(laplacian, (vx_uint32)((levels - 1) - i)), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(out = vxCreateImage(context, prev_lev_width, prev_lev_height, format), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(filter = vxCreateImage(context, prev_lev_width, prev_lev_height, format), VX_TYPE_IMAGE);
upsampleImage(context, prev_lev_width, prev_lev_height, filling, conv, filter, &border);
VX_CALL(vxuAdd(context, filter, pyr_level, VX_CONVERT_POLICY_SATURATE, out));
VX_CALL(vxReleaseImage(&pyr_level));
if ((levels - 1) - i == 0)
{
VX_CALL(ownCopyImage(out, output));
VX_CALL(vxReleaseImage(&filling));
}
else
{
VX_CALL(vxReleaseImage(&filling));
ASSERT_VX_OBJECT(filling = vxCreateImage(context, prev_lev_width, prev_lev_height, format), VX_TYPE_IMAGE);
VX_CALL(ownCopyImage(out, filling));
/* compute dimensions for the prev level */
prev_lev_width = (vx_uint32)ceilf(prev_lev_width * VX_SCALE_PYRAMID_DOUBLE);
prev_lev_height = (vx_uint32)ceilf(prev_lev_height * VX_SCALE_PYRAMID_DOUBLE);
}
VX_CALL(vxReleaseImage(&out));
VX_CALL(vxReleaseImage(&filter));
}
VX_CALL(vxReleaseConvolution(&conv));
return;
}
static void own_laplacian_reconstruct_openvx(vx_context context, vx_border_t border, vx_pyramid laplacian, vx_image input, vx_image output)
{
vx_graph graph = 0;
vx_node node = 0;
ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH);
ASSERT_VX_OBJECT(node = vxLaplacianReconstructNode(graph, laplacian, input, output), VX_TYPE_NODE);
VX_CALL(vxSetNodeAttribute(node, VX_NODE_BORDER, &border, sizeof(border)));
VX_CALL(vxVerifyGraph(graph));
VX_CALL(vxProcessGraph(graph));
VX_CALL(vxReleaseNode(&node));
VX_CALL(vxReleaseGraph(&graph));
ASSERT(node == 0);
ASSERT(graph == 0);
return;
}
#define LAPLACIAN_RECONSTRUCT_PARAMETERS \
CT_GENERATE_PARAMETERS("randomInput", ADD_VX_BORDERS_REQUIRE_UNDEFINED_ONLY, ADD_SIZE_OWN_SET, ARG, own_generate_random, NULL), \
CT_GENERATE_PARAMETERS("lena", ADD_VX_BORDERS_REQUIRE_UNDEFINED_ONLY, ADD_SIZE_NONE, ARG, own_read_image, "lena.bmp")
TEST_WITH_ARG(LaplacianReconstruct, testGraphProcessing, Arg, LAPLACIAN_RECONSTRUCT_PARAMETERS)
{
vx_uint32 i;
vx_context context = context_->vx_context_;
vx_size levels = 0;
vx_image src = 0;
vx_image ref_lowest_res = 0;
vx_image ref_dst = 0;
vx_image tst_dst = 0;
vx_pyramid ref_pyr = 0;
CT_Image input = NULL;
//vx_border_t border = arg_->border;
vx_border_t build_border = { VX_BORDER_REPLICATE };
ASSERT_NO_FAILURE(input = arg_->generator(arg_->fileName, arg_->width, arg_->height));
ASSERT_VX_OBJECT(src = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE);
levels = own_pyramid_calc_max_levels_count(input->width, input->height, VX_SCALE_PYRAMID_HALF) - 1;
{
vx_uint32 lowest_res_width = input->width;
vx_uint32 lowest_res_height = input->height;
for (i = 0; i < levels; i++)
{
lowest_res_width = (vx_uint32)ceilf(lowest_res_width * VX_SCALE_PYRAMID_HALF);
lowest_res_height = (vx_uint32)ceilf(lowest_res_height * VX_SCALE_PYRAMID_HALF);
}
ASSERT_VX_OBJECT(ref_pyr = vxCreatePyramid(context, levels, VX_SCALE_PYRAMID_HALF, input->width, input->height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
ASSERT_VX_OBJECT(ref_lowest_res = vxCreateImage(context, lowest_res_width, lowest_res_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(ref_dst = vxCreateImage(context, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(tst_dst = vxCreateImage(context, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
}
own_laplacian_pyramid_reference(context, build_border, src, ref_pyr, ref_lowest_res);
own_laplacian_reconstruct_reference(context, build_border, ref_pyr, ref_lowest_res, ref_dst);
own_laplacian_reconstruct_openvx(context, build_border, ref_pyr, ref_lowest_res, tst_dst);
{
CT_Image ct_ref_dst = 0;
CT_Image ct_tst_dst = 0;
ASSERT_NO_FAILURE(ct_ref_dst = ct_image_from_vx_image(ref_dst));
ASSERT_NO_FAILURE(ct_tst_dst = ct_image_from_vx_image(tst_dst));
EXPECT_CTIMAGE_NEAR(ct_ref_dst, ct_tst_dst, 1);
}
VX_CALL(vxReleaseImage(&src));
VX_CALL(vxReleasePyramid(&ref_pyr));
VX_CALL(vxReleaseImage(&ref_lowest_res));
VX_CALL(vxReleaseImage(&ref_dst));
VX_CALL(vxReleaseImage(&tst_dst));
ASSERT(src == 0);
ASSERT(ref_pyr == 0);
ASSERT(ref_lowest_res == 0);
ASSERT(ref_dst == 0);
ASSERT(tst_dst == 0);
}
TEST_WITH_ARG(LaplacianReconstruct, testImmediateProcessing, Arg, LAPLACIAN_RECONSTRUCT_PARAMETERS)
{
vx_uint32 i;
vx_context context = context_->vx_context_;
vx_size levels = 0;
vx_image src = 0;
vx_image ref_lovest_res = 0;
vx_image ref_dst = 0;
vx_image tst_dst = 0;
vx_pyramid ref_pyr = 0;
CT_Image input = NULL;
//vx_border_t border = arg_->border;
vx_border_t build_border = { VX_BORDER_REPLICATE };
ASSERT_NO_FAILURE(input = arg_->generator(arg_->fileName, arg_->width, arg_->height));
ASSERT_VX_OBJECT(src = ct_image_to_vx_image(input, context), VX_TYPE_IMAGE);
levels = own_pyramid_calc_max_levels_count(input->width, input->height, VX_SCALE_PYRAMID_HALF) - 1;
{
vx_uint32 lowest_res_width = input->width;
vx_uint32 lowest_res_height = input->height;
for (i = 0; i < levels; i++)
{
lowest_res_width = (vx_uint32)ceilf(lowest_res_width * VX_SCALE_PYRAMID_HALF);
lowest_res_height = (vx_uint32)ceilf(lowest_res_height * VX_SCALE_PYRAMID_HALF);
}
ASSERT_VX_OBJECT(ref_pyr = vxCreatePyramid(context, levels, VX_SCALE_PYRAMID_HALF, input->width, input->height, VX_DF_IMAGE_S16), VX_TYPE_PYRAMID);
ASSERT_VX_OBJECT(ref_lovest_res = vxCreateImage(context, lowest_res_width, lowest_res_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(ref_dst = vxCreateImage(context, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
ASSERT_VX_OBJECT(tst_dst = vxCreateImage(context, input->width, input->height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE);
}
own_laplacian_pyramid_reference(context, build_border, src, ref_pyr, ref_lovest_res);
own_laplacian_reconstruct_reference(context, build_border, ref_pyr, ref_lovest_res, ref_dst);
VX_CALL(vxSetContextAttribute(context, VX_CONTEXT_IMMEDIATE_BORDER, &build_border, sizeof(build_border)));
VX_CALL(vxuLaplacianReconstruct(context, ref_pyr, ref_lovest_res, tst_dst));
{
CT_Image ct_ref_dst = 0;
CT_Image ct_tst_dst = 0;
ASSERT_NO_FAILURE(ct_ref_dst = ct_image_from_vx_image(ref_dst));
ASSERT_NO_FAILURE(ct_tst_dst = ct_image_from_vx_image(tst_dst));
EXPECT_CTIMAGE_NEAR(ct_ref_dst, ct_tst_dst, 1);
}
VX_CALL(vxReleaseImage(&src));
VX_CALL(vxReleasePyramid(&ref_pyr));
VX_CALL(vxReleaseImage(&ref_lovest_res));
VX_CALL(vxReleaseImage(&ref_dst));
VX_CALL(vxReleaseImage(&tst_dst));
ASSERT(src == 0);
ASSERT(ref_pyr == 0);
ASSERT(ref_lovest_res == 0);
ASSERT(ref_dst == 0);
ASSERT(tst_dst == 0);
}
TESTCASE_TESTS(LaplacianReconstruct,
testNodeCreation,
testGraphProcessing,
testImmediateProcessing
)