1. 辅助函数
#ifndef OPENVX_UTILS_H
#define OPENVX_UTILS_H
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
#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("%s\n", __func__); \
}
#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
2. 样例程序
#include <stdio.h>
#include <stdlib.h>
#include "VX/vx.h"
#include "VX/vxu.h"
#include "openvx_utils.h"
void errorCheck(vx_context context, vx_status status, const char *message)
{
if (status)
{
puts("ERROR! ");
puts(message);
vxReleaseContext(&context);
exit(EXIT_FAILURE);
}
}
vx_reference getGraphParameter(vx_graph graph, vx_uint32 index)
{
vx_parameter p = vxGetGraphParameterByIndex(graph, index);
vx_reference ref = NULL;
vxQueryParameter(p, VX_PARAMETER_REF, &ref, sizeof(ref));
vxReleaseParameter(&p);
return ref;
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
vx_context context = vxCreateContext();
vx_graph graph;
{
graph = vxCreateGraph(context);
vx_image input_image = vxCreateImage(context, 100U, 100U, VX_DF_IMAGE_U8);
vx_float32 strength_thresh_value = 128.0f;
vx_scalar strength_thresh = vxCreateScalar(context, VX_TYPE_FLOAT32, &strength_thresh_value);
vx_array corners = vxCreateArray(context, VX_TYPE_KEYPOINT, 100);
vx_size num_corners_value = 0;
vx_scalar num_corners = vxCreateScalar(context, VX_TYPE_SIZE, &num_corners_value);
vx_node node = vxFastCornersNode(graph, input_image, strength_thresh, vx_true_e, corners, num_corners);
vxAddParameterToGraph(graph, vxGetParameterByIndex(node, 0));
vxAddParameterToGraph(graph, vxGetParameterByIndex(node, 3));
vxAddParameterToGraph(graph, vxGetParameterByIndex(node, 4));
vxReleaseImage(&input_image);
vxReleaseArray(&corners);
vxReleaseScalar(&num_corners);
vxReleaseScalar(&strength_thresh);
}
{
errorCheck(context, vxVerifyGraph(graph), "Verify graph is fail.");
vx_uint32 num_params;
vxQueryGraph(graph, VX_GRAPH_NUMPARAMETERS, &num_params, sizeof(vx_uint32));
std::cout << "num_params: " << num_params << std::endl;
vx_graph_state_e graph_state;
vxQueryGraph(graph, VX_GRAPH_STATE, &graph_state, sizeof(vx_graph_state_e));
std::cout << "graph_state: " << graph_state << std::endl;
}
vx_image image;
{
{
image = vxCreateImage(context, 100U, 100U, VX_DF_IMAGE_U8);
errorCheck(context, vxGetStatus((vx_reference)image), "Create image is fail.");
vx_rectangle_t rect = {.start_x = 20, .start_y = 40, .end_x = 80, .end_y = 60};
vx_image roi = vxCreateImageFromROI(image, &rect);
errorCheck(context, vxGetStatus((vx_reference)roi), "Create roi is fail.");
vx_pixel_value_t pixel_white, pixel_black;
pixel_white.U8 = 255;
pixel_black.U8 = 0;
errorCheck(context, vxSetImagePixelValues(image, &pixel_black), "Set pixel value is fail.");
errorCheck(context, vxSetImagePixelValues(roi, &pixel_white), "Set pixel value is fail.");
}
vx_status status = vxSetGraphParameterByIndex(graph, 0, (vx_reference)image);
if (status != VX_SUCCESS)
{
if (status == VX_ERROR_INVALID_REFERENCE)
std::cout << "VX_ERROR_INVALID_REFERENCE" << std::endl;
if (status == VX_ERROR_INVALID_PARAMETERS)
std::cout << "VX_ERROR_INVALID_PARAMETERS" << std::endl;
printf("status = %d\n", status);
vxReleaseContext(&context);
return EXIT_FAILURE;
}
}
errorCheck(context, vxProcessGraph(graph), "Process graph is fail.");
{
vx_size num_corners_value = 0;
vxCopyScalar((vx_scalar)getGraphParameter(graph, 2), &num_corners_value, VX_READ_ONLY, VX_MEMORY_TYPE_HOST);
std::cout << "num_corners_value: " << num_corners_value << std::endl;
vx_keypoint_t *kp = (vx_keypoint_t *)calloc(100, sizeof(vx_keypoint_t));
vxCopyArrayRange((vx_array)getGraphParameter(graph, 1), 0, num_corners_value, sizeof(vx_keypoint_t), kp, VX_READ_ONLY, VX_MEMORY_TYPE_HOST);
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);
}
vxReleaseContext(&context);
return EXIT_SUCCESS;
}
3. 执行效果