• 【OPENVX】快速角点提取之 vxuFastCorners


    • openvx_utils.h
      #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(__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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125
      • 126
      • 127
      • 128
      • 129
      • 130
      • 131
      • 132
      • 133
      • 134
      • 135
      • 136
      • 137
      • 138
      • 139
      • 140
      • 141
      • 142
      • 143
      • 144
      • 145
      • 146
      • 147
      • 148
      • 149
      • 150
      • 151
      • 152
      • 153
      • 154
      • 155
      • 156
      • 157
      • 158
      • 159
      • 160
      • 161
      • 162
      • 163
      • 164
      • 165
      • 166
      • 167
      • 168
      • 169
      • 170
      • 171
      • 172
      • 173
      • 174
      • 175
      • 176
      • 177
      • 178
      • 179
      • 180
      • 181
      • 182
      • 183
      • 184
      • 185
      • 186
      • 187
      • 188
      • 189
      • 190
      • 191
      • 192
      • 193
      • 194
      • 195
      • 196
      • 197
      • 198
      • 199
      • 200
      • 201
      • 202
      • 203
      • 204
      • 205
      • 206
      • 207
      • 208
      • 209
      • 210
      • 211
      • 212
      • 213
    • openvx_vxu_fast_corner.cpp
      #include <stdio.h>
      #include <stdlib.h>
      #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;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125
      • 126
      • 127
      • 128
      • 129
      • 130
      • 131
      • 132
      • 133
      • 134
      • 135
    • 效果
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 相关阅读:
    动态规划:LeetCode第10题 正则表达式匹配
    maven学习: 使用Maven构建Web项目
    设计模式详解(九)——桥接模式
    CSS 文字溢出省略号显示
    【算法|前缀和系列No.3】leetcode LCR 012. 寻找数组的中心下标
    7个实用有效的shopify运营策略,跨境电商卖家必知
    记一次断电引起的CentOS引导失败
    苹果“欠”用户的承诺,何时会兑现?
    TypeScript学习日志-第二十六天(weakMap,weakSet,set,map)
    ES全文检索支持拼音和繁简检索
  • 原文地址:https://blog.csdn.net/zhy29563/article/details/125608926