【OPENVX】快速角点提取之 vxuFastCorners

发布时间:2022-08-19 13:30

  • openvx_utils.h
    #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
    
  • openvx_vxu_fast_corner.cpp
    #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;
    }
    
  • 效果
    【OPENVX】快速角点提取之 vxuFastCorners_第1张图片
    【OPENVX】快速角点提取之 vxuFastCorners_第2张图片
    【OPENVX】快速角点提取之 vxuFastCorners_第3张图片

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号