【OPENVX】简单的图模式 vxFastCornersNode

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. 执行效果

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值