vx_status vxConvolution3x3(vx_image src, vx_image dst, vx_int16 conv[3][3], const vx_border_mode_t *borders) { vx_uint32 y, x; void *src_base = NULL; void *dst_base = NULL; vx_imagepatch_addressing_t src_addr, dst_addr; vx_rectangle_t rect; vx_enum dst_format = VX_DF_IMAGE_VIRT; vx_status status = VX_SUCCESS; vx_uint32 low_x = 0, low_y = 0, high_x, high_y; 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); status |= vxQueryImage(dst, VX_IMAGE_ATTRIBUTE_FORMAT, &dst_format, sizeof(dst_format)); high_x = src_addr.dim_x; high_y = src_addr.dim_y; if (borders->mode == VX_BORDER_MODE_UNDEFINED) { ++low_x; --high_x; ++low_y; --high_y; vxAlterRectangle(&rect, 1, 1, -1, -1); } //printf("%s Rectangle = {%u,%u x %u,%u}\n",__FUNCTION__, rect.start_x, rect.start_y, rect.end_x, rect.end_y); for (y = low_y; y < high_y; y++) { for (x = low_x; x < high_x; x++) { vx_int32 value = vx_convolve8with16(src_base, x, y, &src_addr, conv, borders); if (dst_format == VX_DF_IMAGE_U8) { vx_uint8 *dst = vxFormatImagePatchAddress2d(dst_base, x, y, &dst_addr); *dst = vx_clamp_u8_i32(value); } else { vx_int16 *dst = vxFormatImagePatchAddress2d(dst_base, x, y, &dst_addr); *dst = vx_clamp_s16_i32(value); } } } status |= vxCommitImagePatch(src, NULL, 0, &src_addr, src_base); status |= vxCommitImagePatch(dst, &rect, 0, &dst_addr, dst_base); return status; }
// nodeless version of the Convolve kernel vx_status vxConvolve(vx_image src, vx_convolution conv, vx_image dst, vx_border_mode_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_ATTRIBUTE_FORMAT, &src_format, sizeof(src_format)); status |= vxQueryImage(dst, VX_IMAGE_ATTRIBUTE_FORMAT, &dst_format, sizeof(dst_format)); status |= vxQueryConvolution(conv, VX_CONVOLUTION_ATTRIBUTE_COLUMNS, &conv_width, sizeof(conv_width)); status |= vxQueryConvolution(conv, VX_CONVOLUTION_ATTRIBUTE_ROWS, &conv_height, sizeof(conv_height)); status |= vxQueryConvolution(conv, VX_CONVOLUTION_ATTRIBUTE_SCALE, &scale, sizeof(scale)); conv_radius_x = (vx_int32)conv_width / 2; conv_radius_y = (vx_int32)conv_height / 2; status |= vxReadConvolutionCoefficients(conv, conv_mat); 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); if (bordermode->mode == VX_BORDER_MODE_UNDEFINED) { low_x = conv_radius_x; high_x = ((src_addr.dim_x >= (vx_uint32)conv_radius_x) ? src_addr.dim_x - conv_radius_x : 0); low_y = conv_radius_y; high_y = ((src_addr.dim_y >= (vx_uint32)conv_radius_y) ? src_addr.dim_y - conv_radius_y : 0); vxAlterRectangle(&rect, conv_radius_x, conv_radius_y, -conv_radius_x, -conv_radius_y); } else { 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}; vxReadRectangle(src_base, &src_addr, bordermode, src_format, x, y, conv_radius_x, conv_radius_y, slice); for (i = 0; i < 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}; vxReadRectangle(src_base, &src_addr, bordermode, src_format, x, y, conv_radius_x, conv_radius_y, slice); for (i = 0; i < 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; }
// nodeless version of NonLinearFilter kernel vx_status vxNonLinearFilter(vx_scalar function, vx_image src, vx_matrix mask, vx_image dst, vx_border_t *border) { vx_uint32 y, x; void *src_base = NULL; void *dst_base = NULL; vx_imagepatch_addressing_t src_addr, dst_addr; vx_rectangle_t rect; vx_uint32 low_x = 0, low_y = 0, high_x, high_y; vx_uint8 m[C_MAX_NONLINEAR_DIM * C_MAX_NONLINEAR_DIM]; vx_uint8 v[C_MAX_NONLINEAR_DIM * C_MAX_NONLINEAR_DIM]; vx_status 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); vx_enum func = 0; status |= vxCopyScalar(function, &func, VX_READ_ONLY, VX_MEMORY_TYPE_HOST); vx_size mrows, mcols; vx_enum mtype = 0; status |= vxQueryMatrix(mask, VX_MATRIX_ROWS, &mrows, sizeof(mrows)); status |= vxQueryMatrix(mask, VX_MATRIX_COLUMNS, &mcols, sizeof(mcols)); status |= vxQueryMatrix(mask, VX_MATRIX_TYPE, &mtype, sizeof(mtype)); vx_coordinates2d_t origin; status |= vxQueryMatrix(mask, VX_MATRIX_ORIGIN, &origin, sizeof(origin)); if ((mtype != VX_TYPE_UINT8) || (sizeof(m) < mrows * mcols)) status = VX_ERROR_INVALID_PARAMETERS; status |= vxCopyMatrix(mask, m, VX_READ_ONLY, VX_MEMORY_TYPE_HOST); if (status == VX_SUCCESS) { vx_size rx0 = origin.x; vx_size ry0 = origin.y; vx_size rx1 = mcols - origin.x - 1; vx_size ry1 = mrows - origin.y - 1; high_x = src_addr.dim_x; high_y = src_addr.dim_y; if (border->mode == VX_BORDER_UNDEFINED) { low_x += rx0; low_y += ry0; high_x -= rx1; high_y -= ry1; vxAlterRectangle(&rect, (vx_int32)rx0, (vx_int32)ry0, -(vx_int32)rx1, -(vx_int32)ry1); } for (y = low_y; y < high_y; y++) { for (x = low_x; x < high_x; x++) { vx_uint8 *dst = vxFormatImagePatchAddress2d(dst_base, x, y, &dst_addr); vx_int32 count = readMaskedRectangle_U8(src_base, &src_addr, border, VX_DF_IMAGE_U8, x, y, rx0, ry0, rx1, ry1, m, v); qsort(v, count, sizeof(vx_uint8), vx_uint8_compare); switch (func) { case VX_NONLINEAR_FILTER_MIN: *dst = v[0]; break; /* minimal value */ case VX_NONLINEAR_FILTER_MAX: *dst = v[count - 1]; break; /* maximum value */ case VX_NONLINEAR_FILTER_MEDIAN: *dst = v[count / 2]; break; /* pick the middle value */ } } } } status |= vxCommitImagePatch(src, NULL, 0, &src_addr, src_base); status |= vxCommitImagePatch(dst, &rect, 0, &dst_addr, dst_base); return status; }