发布时间:2022-08-19 13:30
#ifndef OPENVX_UTILS_H
#define OPENVX_UTILS_H
#include
#include
#include
#include "VX/vx.h"
// 状态检查
#define ERROR_CHECK_STATUS(status) \
{ \
vx_status status_ = (status); \
if (status_ != VX_SUCCESS) \
{ \
printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
exit(1); \
} \
}
// 对象创建检查
#define ERROR_CHECK_OBJECT(obj, message) \
{ \
vx_status status_ = vxGetStatus((vx_reference)(obj)); \
if (status_ != VX_SUCCESS) \
{ \
printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
puts(message); \
exit(1); \
} \
}
// 函数名称
#ifdef DEBUG
#define DEBUG_FUNCTION_NAME(void) \
{ \
printf("================================================================\n"); \
printf(__func__); \
printf("\n"); \
}
#define DEBUG_LOG(format, ...) \
{ \
printf("[%s:%d->%s] " format, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
}
#else
#define DEBUG_FUNCTION_NAME(void)
#define DEBUG_LOG(format, ...)
#endif
static inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image)
{
DEBUG_FUNCTION_NAME();
// 图像类型
vx_df_image vx_image_type;
switch (cv_image.type())
{
case CV_8UC1:
vx_image_type = VX_DF_IMAGE_U8;
break;
case CV_8UC3:
vx_image_type = VX_DF_IMAGE_RGB;
break;
default:
DEBUG_LOG("Format %d not supported\n", vx_image_type);
return NULL;
}
// 图像属性
int width = cv_image.cols;
int height = cv_image.rows;
// 创建图像
vx_image image = vxCreateImage(context, width, height, vx_image_type);
// 区域
vx_rectangle_t patch;
patch.start_x = 0;
patch.start_y = 0;
patch.end_x = width;
patch.end_y = height;
vx_map_id map_id;
vx_imagepatch_addressing_t addr;
unsigned char *ptr;
vx_status status = vxMapImagePatch(image, &patch, 0, &map_id, &addr, (void **)&ptr, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X);
if (status != VX_SUCCESS)
{
DEBUG_LOG("vxMapImagePatch returned error with code %d\n", status);
return NULL;
}
if (addr.stride_x != 1 && addr.stride_x != 3)
{
DEBUG_LOG("addressing structure not supported, stride_x = %d\n", addr.stride_x);
return NULL;
}
for (int y = 0; y < height; y++)
{
unsigned char *ptr_y = ptr + y * addr.stride_y;
memcpy(ptr_y, cv_image.ptr(y), addr.stride_y);
}
status = vxUnmapImagePatch(image, map_id);
if (status != VX_SUCCESS)
{
DEBUG_LOG("vxUnmapImagePatch failed...\n");
return NULL;
}
return image;
}
static inline int vxVxImageToCvMat(const vx_image image, cv::Mat &cv_image)
{
DEBUG_FUNCTION_NAME();
// 图像属性
vx_uint32 width = 0;
vx_uint32 height = 0;
ERROR_CHECK_STATUS(vxQueryImage(image, VX_IMAGE_WIDTH, &width, sizeof(width)));
ERROR_CHECK_STATUS(vxQueryImage(image, VX_IMAGE_HEIGHT, &height, sizeof(height)));
// 图像类型
vx_df_image image_type;
ERROR_CHECK_STATUS(vxQueryImage(image, VX_IMAGE_FORMAT, &image_type, sizeof(image_type)));
int cv_image_type;
switch (image_type)
{
case VX_DF_IMAGE_U8:
cv_image_type = CV_8UC1;
break;
case VX_DF_IMAGE_RGB:
cv_image_type = CV_8UC3;
break;
default:
DEBUG_LOG("Format %d not supported\n", cv_image_type);
return -1;
}
// 区域
vx_rectangle_t patch = {0, 0, width, height};
vx_map_id map_id;
vx_imagepatch_addressing_t addr;
unsigned char *ptr;
vx_status status = vxMapImagePatch(image, &patch, 0, &map_id, &addr, (void **)&ptr, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X);
if (status != VX_SUCCESS)
{
DEBUG_LOG("vxMapImagePatch returned error with code %d\n", status);
return -1;
}
if (addr.stride_x != 1 && addr.stride_x != 3)
{
DEBUG_LOG("addressing structure not supported, stride_x = %d\n", addr.stride_x);
return -1;
}
cv_image = cv::Mat(height, width, cv_image_type);
for (int y = 0; y < height; y++)
{
unsigned char *ptr_y = ptr + y * addr.stride_y;
memcpy(cv_image.ptr(y), ptr_y, addr.stride_y);
}
status = vxUnmapImagePatch(image, map_id);
if (status != VX_SUCCESS)
{
DEBUG_LOG("vxUnmapImagePatch failed...\n");
return -1;
}
return 0;
}
static inline vx_image ReadImage(vx_context context, const char *file_name)
{
cv::Mat mat = cv::imread(file_name, cv::IMREAD_ANYCOLOR);
return vxCvMatToVxImage(context, mat);
}
static inline void SaveImage(vx_image image, const char *file_name)
{
cv::Mat mat;
int ret = vxVxImageToCvMat(image, mat);
if (!ret)
cv::imwrite(file_name, mat);
}
static inline void DisplayImage(vx_image image, const char *window_name, int time = 0, int width = 640, int height = 480)
{
cv::Mat mat;
int ret = vxVxImageToCvMat(image, mat);
if (!ret)
{
cv::namedWindow(window_name, cv::WINDOW_NORMAL);
cv::resizeWindow(window_name, width, 480);
cv::imshow(window_name, mat);
cv::waitKey(time);
}
}
static inline void DisplayImage(cv::Mat &image, const char *window_name, int time = 0, int width = 640, int height = 480)
{
cv::namedWindow(window_name, cv::WINDOW_NORMAL);
cv::resizeWindow(window_name, width, 480);
cv::imshow(window_name, image);
cv::waitKey(time);
}
#endif
#include
#include
#include "VX/vx.h"
#include "VX/vxu.h"
#include "openvx_utils.h"
/// 目的:
/// 1. 使用图像创建函数在黑色背景上创建一个白色矩形
/// 2. 使用Fast Corners算法计算角点数量
void errorCheck(vx_context context, vx_status status, const char *message)
{
if (status)
{
puts("ERROR! ");
puts(message);
vxReleaseContext(&context);
exit(EXIT_FAILURE);
}
}
vx_image makeInputImage(vx_context context)
{
DEBUG_FUNCTION_NAME();
/// 创建图像
vx_image image = vxCreateImage(context, 100U, 100U, VX_DF_IMAGE_U8);
/// 判断图像是否创建成功
if (VX_SUCCESS != vxGetStatus((vx_reference)image))
return image;
/// 定义矩形
vx_rectangle_t rect = {.start_x = 20, .start_y = 40, .end_x = 80, .end_y = 60};
/// 创建感兴趣区域
vx_image roi = vxCreateImageFromROI(image, &rect);
if(VX_SUCCESS != vxGetStatus((vx_reference)roi))
return roi;
vx_pixel_value_t pixel_white, pixel_black;
pixel_white.U8 = 255;
pixel_black.U8 = 0;
/// 设置背景像素
if ( VX_SUCCESS != vxSetImagePixelValues(image, &pixel_black))
vxReleaseImage(&image);
/// 设置前景像素
if (VX_SUCCESS != vxSetImagePixelValues(roi, &pixel_white))
vxReleaseImage(&roi);
return image;
}
void fastCorner(vx_context context, vx_image image, vx_bool is_use_nonmax_suppression)
{
DEBUG_FUNCTION_NAME();
/// 分割阈值
vx_float32 strength_thresh_value = 128.0f;
vx_scalar strength_thresh = vxCreateScalar(context, VX_TYPE_FLOAT32, &strength_thresh_value);
errorCheck(context, vxGetStatus((vx_reference) strength_thresh), "Could not create threshold scalar");
/// 创建用于储存角点结果的数组
vx_array corners = vxCreateArray(context, VX_TYPE_KEYPOINT, 100);
errorCheck(context, vxGetStatus((vx_reference) corners), "Could not create corner array");
/// 角点数量
vx_size num_corners_value = 0;
vx_scalar num_corners = vxCreateScalar(context, VX_TYPE_SIZE, &num_corners_value);
errorCheck(context, vxGetStatus((vx_reference) num_corners), "Could not create corner number scalar");
/// 用于显示角点而开辟的内存区
vx_keypoint_t *kp = (vx_keypoint_t *)calloc(100, sizeof(vx_keypoint_t));
errorCheck(context, kp == NULL, "Could not calloc memory");
/// 执行角点查找
vx_status status = vxuFastCorners(context, image, strength_thresh, is_use_nonmax_suppression, corners, num_corners);
errorCheck(context, status, "Fast Corners function failed");
/// 获取角点数量
status = vxCopyScalar(num_corners, &num_corners_value, VX_READ_ONLY, VX_MEMORY_TYPE_HOST);
errorCheck(context, status, "vxCopyScalar failed");
printf("Found %zu corners %s non-max suppression\n", num_corners_value, is_use_nonmax_suppression ? "with" : "without");
/// 获取角点数据
status = vxCopyArrayRange(corners, 0, num_corners_value, sizeof(vx_keypoint_t), kp, VX_READ_ONLY, VX_MEMORY_TYPE_HOST);
errorCheck(context, status, "vxCopyArrayRange failed");
for (int i = 0; i < num_corners_value; ++i)
{
printf("Entry %3d: x = %d, y = %d\n", i, kp[i].x, kp[i].y);
}
cv::Mat cv_image;
int ret = vxVxImageToCvMat(image, cv_image);
if (0 == ret)
{
cv::Mat cv_image_color;
cv::cvtColor(cv_image, cv_image_color, cv::COLOR_GRAY2BGR);
for (int i = 0; i < num_corners_value; ++i)
{
cv::circle(cv_image_color, cv::Point(kp[i].x, kp[i].y), 3, cv::Scalar(0, 255, 0), -1);
}
DisplayImage(cv_image_color, "KeyPoints");
}
free(kp);
}
int main(int argc, char *argv[])
{
(void) argc;
(void) argv;
/// 创建上下文
vx_context context = vxCreateContext();
errorCheck(context, vxGetStatus((vx_reference)context), "Could not create a vx_context");
/// 创建图像(黑色背景上带有白色矩形)
vx_image image = makeInputImage(context);
DisplayImage(image, "image");
errorCheck(context, vxGetStatus((vx_reference)image), "Could not create image1");
/// 使用非极大值抑制
fastCorner(context, image, vx_true_e);
/// 不使用非极大值抑制
fastCorner(context, image, vx_false_e);
vxReleaseContext(&context);
return EXIT_SUCCESS;
}