技术专栏
letterbox的两种实现
以前经常觉得resize你的图像成模型宽高, 送进去, 对推理精度影响不大, 最近发现, 还真的挺大.
这里涉及一个概念, 就是letterbox.
因为我们的模型放入yolov5做推理的时候, 模型输入是640x640的正方形, 你需要把图片做一个预处理:
例如这张图
比较宽, 那么有两种做法, 一种粗暴的, 直接跟揉面一样, 两边一夹:
这个就叫做resize, 就是直接变形成了640x640
这样会导致最终精度的下降,所以最推荐的做法是:
首先他图片的宽高中大的那一个, 缩放成640, 然后等比例, 缩放另一个方向, 然后空余部分填充灰色或者黑色, 比如这种扁扁的图片, 就处理成:
再送入模型中做推理.
首先, 在目前不纠结速度跟效率的前提下, 有两个方法实现:
- opencv
- 纯手搓
当然还有用rga,vpss等等做法, 回头再一一列举, 先说说这两种
先说说opencv的做法:
rk的npu2 example中就有这个函数:
void letterbox(const cv::Mat &image, cv::Mat &padded_image, BOX_RECT &pads, const float scale, const cv::Size &target_size, const cv::Scalar &pad_color)
{
// 调整图像大小
cv::Mat resized_image;
cv::resize(image, resized_image, cv::Size(), scale, scale);
// 计算填充大小
int pad_width = target_size.width - resized_image.cols;
int pad_height = target_size.height - resized_image.rows;
pads.left = pad_width / 2;
pads.right = pad_width - pads.left;
pads.top = pad_height / 2;
pads.bottom = pad_height - pads.top;
// 在图像周围添加填充
cv::copyMakeBorder(resized_image, padded_image, pads.top, pads.bottom, pads.left, pads.right, cv::BORDER_CONSTANT, pad_color);
}
简单吧..
如果手搓的话, 分三步:
- 缩小为640x360,
- 新建一个画布640x640, 填充灰边,
- 在画面中间填入数据
void VideoChannel::resize_from_1080p_to_640_square(char *input, char *output) {
char *resizedData = (char *) malloc(TARGET_WIDTH * TARGET_HEIGHT * ORIGINAL_CHANNELS);
// LOGD("resize from 1080p to 640 square");
// 缩小图片
resizeImage(input, resizedData);
// 128就是灰色, 全部像素设置为灰色
memset(output, 128, OUTPUT_WIDTH * OUTPUT_HEIGHT * RGB_CHANNELS);
// 填充到640x640的灰度图中
fillGrayImage(output, resizedData, OUTPUT_WIDTH, OUTPUT_HEIGHT);
// 申请的内存释放掉
free(resizedData);
}
缩放图像:
// 缩放图像
void VideoChannel::resizeImage(char *input, char *output) {
int channel = 3;
for (int y = 0; y < TARGET_HEIGHT; y++) {
for (int x = 0; x < TARGET_WIDTH; x++) {
int origX = x * channel * ORIGINAL_WIDTH / (channel * TARGET_WIDTH);
int origY = y * ORIGINAL_HEIGHT / TARGET_HEIGHT;
for (int c = 0; c < channel; c++) {
output[(y * TARGET_WIDTH + x) * channel + c] = input[(origY * ORIGINAL_WIDTH + origX) * ORIGINAL_CHANNELS + c];
}
}
}
}
// 将缩小后的图像填充到全灰色图像中
void VideoChannel::fillGrayImage(char *grayData, char *resizedData, int width, int height) {
// 从140行开始填充, 因为上面要留下灰边
char *grayDataPtr = grayData + BORDER_SIZE * width * RGB_CHANNELS;
char *resizedDataPtr = resizedData;
for (int i = 0; i < TARGET_WIDTH * TARGET_HEIGHT; i++) {
memcpy(grayDataPtr, resizedDataPtr, RGB_CHANNELS);
grayDataPtr = grayDataPtr + RGB_CHANNELS;
resizedDataPtr = resizedDataPtr + RGB_CHANNELS;
}
}
最后再多嘴一句, 1106上面已经抄了海思的vpss了, 估计也是拿rga的核心, 做了这类转换工作, 所以它可以从vi->vpss, 然后从vpss拿到一个640x360的图像, 只需要简单的复制内存到640x640的灰色内存中即可.
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包
12
6
评论
打赏
- 分享
- 举报
评论
4个
手气红包
-
来自远方 2023-11-06 11:01:445.00元回复 举报不错哦~
-
automan 2023-11-03 15:53:12回复 举报收藏加关注,追番不迷路
-
Stranger 2023-11-03 15:52:11回复 举报文章不错
-
亮仔 工作微信[呲牙] 2023-11-03 11:00:38回复 举报收藏加关注,追番不迷路
相关专栏
-
浏览量:7991次2020-11-24 23:06:59
-
浏览量:3309次2022-08-17 09:00:12
-
浏览量:3465次2018-01-02 15:38:45
-
浏览量:4814次2021-06-30 10:41:01
-
浏览量:3336次2021-01-18 17:57:51
-
2020-12-09 13:43:37
-
浏览量:1601次2019-06-25 08:57:10
-
2022-01-07 09:00:27
-
浏览量:1154次2024-01-12 13:47:40
-
浏览量:1265次2023-12-19 16:06:28
-
浏览量:1965次2019-07-15 11:28:28
-
浏览量:1941次2023-03-16 09:42:49
-
浏览量:1089次2023-02-22 09:08:28
-
浏览量:2004次2019-11-28 18:23:26
-
浏览量:669次2023-08-22 13:38:20
-
浏览量:1340次2020-03-18 10:09:53
-
浏览量:4810次2020-09-23 22:47:30
-
浏览量:9058次2021-03-21 22:58:26
-
浏览量:1732次2020-02-28 09:50:55
置顶时间设置
结束时间
删除原因
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
打赏作者
Marc
您的支持将鼓励我继续创作!
打赏金额:
¥1
¥5
¥10
¥50
¥100
支付方式:
微信支付
打赏成功!
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
审核成功
发布时间设置
发布时间:
请选择发布时间设置
是否关联周任务-专栏模块
审核失败
失败原因
请选择失败原因
备注
请输入备注