OpenCV copyMakeBorder实践

简介

copyMakeBorder是OpenCV里一个边界填充的API,其API接口如下:

// OpenCV 4.5.2 源码
void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
                         int left, int right, int borderType, const Scalar& value )

大部分的贴子只介绍了其支持的填充类型,没有对输入的图像格式进行说明,这里主要是讲下后者。

填充类型:

// OpenCV 4.5.2 源码
//! Various border types, image boundaries are denoted with `|`
//! @see borderInterpolate, copyMakeBorder
enum BorderTypes {
    BORDER_CONSTANT    = 0, //!< `iiiiii|abcdefgh|iiiiiii`  with some specified `i`
    BORDER_REPLICATE   = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
    BORDER_REFLECT     = 2, //!< `fedcba|abcdefgh|hgfedcb`
    BORDER_WRAP        = 3, //!< `cdefgh|abcdefgh|abcdefg`
    BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
    BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`

    BORDER_REFLECT101  = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_DEFAULT     = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_ISOLATED    = 16 //!< do not look outside of ROI
};

图像类型:

这个API的实现就是在图像内存空间的四周填充像素,如果是RGB|BGR|GRAY这样的单平面类型,执行没有问题,但如果是YUV这样的多平面,这个填充逻辑就达不到预期效果,因为YUV类型图像需要分别对Y\U\V分量进行填充。实验代码如下:

  Mat image = cv::Mat(height, width, CV_8UC3);  // 默认像素全是0
  Mat yuv = convert_color(image, cv::COLOR_BGR2YUV_I420);
  Mat dst;
  int top = 2;
  int bottom = top;
  int left = 2;
  int right = left;
  cv::Scalar values(50, 150, 250);
  cv::copyMakeBorder(yuv, dst, top, bottom, left, right, cv::BorderTypes::BORDER_CONSTANT, values);

  save_mat_as_bin(dst, save_path);

输入:16x16,转成YUV后:16x24(24=16 + 16/2)

输出:20x28

预期结果:20x30(20 + 20/2)

将保存后的BIN用hex editor工具打开查看,发现只填充不对。

YUV类型处理思路:

将YUV分成Y、U、V三个分量单独处理,每个分量可以看成是一个Gray图像。如果是NV12图像类型,可以分成Y、UV分量,其中UV当成一个有2个通道的图像。

以NV12图像处理为例,DEMO代码如下:

cv::Mat image = CreateImage(fpath); // 读取图像并转成YUV420SP格式
cv::Mat nv12 = YUV420_SP_to_NV12(image);

cv::Mat gray = cv::Mat(image.rows, image.cols, CV_8UC1);
gray.data = nv12.data;
cv::copyMakeBorder();

cv::Mat uv = cv::Mat(image.rows / 2, image.cols / 2, CV_8UC2);
uv.data = nv12.data + (image.rows * image.cols);
cv::copyMakeBorder();

测试代码链接:linglx/OpenCV

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值