图像尺寸变换scalepadding方法

news/2025/3/11 15:50:26/文章来源:https://www.cnblogs.com/wancy/p/18538672

  在深度学习中,当需要将图像调整到特定尺寸时,直接resize可能会导致图像失真,特别是当目标尺寸与原始图像的宽高比不一致时。为了解决这个问题,一种最常见的方法是首先按照原始图像的宽高比将图像调整到与目标尺寸最接近的尺寸,然后在剩余的空间中使用padding进行填充,以得到目标尺寸的图像。或者先使用填充,再使用resize,其最终结果是一样的,但是往往使用前者。

1.先填充为正方形图后缩放

  1. 确定长边和短边:

    • 首先,确定图像的长边和短边。长边是图像的宽度和高度中较长的那个,短边是较短的那个。
  2. 将图像变为正方形:

    • 以长边的长度作为正方形的边长,这意味着如果原始图像是长方形,那么它的一边将被扩展以形成一个正方形。
    • 较短的一边将围绕其周围填充像素,通常是白色或黑色像素,以确保图像变为正方形。
  3. 填充像素:

    • 填充操作会在短边的两侧添加像素,直到图像的宽度和高度相等。填充的像素数量取决于原始图像的尺寸和目标正方形的尺寸。
  4. 缩放(如双线性插值,最近邻插值等):

    • 一旦图像被转换为正方形,下一步是使用插值法将图像缩放到所需的目标尺寸。
    • 双线性插值是一种平滑的缩放技术,它通过考虑周围四个像素的值来计算新像素的值,这样可以减少缩放过程中的失真。

示意图如下:

  原始图为宽为w,高为h,现在想要通过scalepadding这种方法变换为宽width,高为height的图。(这里假设w>h,h>w的情况与此类似)

 第一步:确定长边与短边,然后将原始图变为正方形,边长长度为长边长度,在短边的外侧填充,使得图变为宽为w,高为w的图。

第二步:缩放变换,将上一步中得到的宽为w,高为w的图经过缩放变换后就变为了宽为width,高为height的目标大小的图了。

   自此,变换就完成了,原始图宽w,高h,以及填充的其中一个部分(w-h)/2变换为目标图像后,很容易得到缩放关系如下:

  w乘以(width/w)后,就变为了width,

  h乘以(height/w)后,就变为了(h*height)/w了,图中未标注出来(第二步中间图的紫色区域的高度),

  (w-h)/2乘以(height/w)后,就变为了((w-h)*height)/(2w)。

  

注意,如果目标的width与height不相等,也就是目标不为正方形就会造成w与h不是同等比例缩放,就会变形失真。所以这种方法只适用于width等于height的情况。

 

 

2.先缩放再填充(通用)

  1. 计算缩放比例:首先,根据目标尺寸和原始图像的宽高比,计算出图像在保持宽高比的情况下应该被缩放到的尺寸。这通常涉及到计算缩放比例,即目标尺寸与原始图像尺寸的比值,并选择较小的那个比例作为最终的缩放比例,以确保图像不会被拉伸或压缩。
  2. 进行resize操作:使用计算出的缩放比例对原始图像进行resize操作,得到一个新的图像。这个新图像的尺寸将小于或等于目标尺寸,但会保持原始图像的宽高比。
  3. 进行padding操作:最后,在新的图像的周围添加padding,以使其达到目标尺寸。padding可以使用任何颜色或图案,但通常选择中性色(如灰色或白色)以避免对图像内容造成干扰。padding的大小将根据目标尺寸和新图像尺寸之间的差异来确。

  上图中实际上需要根据width/w与height/h两者的大小,决定ratio的值。为了防止在缩放过程中,某条边超过目标的长度,应该选择width/w与height/h的较小者作为ratio。看下面代码:

import cv2
import numpy as np
def resize_and_pad(image, target_height, target_width, padding_value=(0, 0, 0)):# 获取原始图像的高度和宽度height, width = image.shape[:2]# 计算缩放比例,使得图像的长宽比例保持不变scale = min(target_width / width, target_height / height)# 计算缩放后的尺寸new_width = int(width * scale)new_height = int(height * scale)# 先对图像进行缩放resized_image = cv2.resize(image, (new_width, new_height))# 创建一个目标大小的空白图像(填充背景为自定义颜色)padded_image = np.full((target_height, target_width, 3), padding_value, dtype=np.uint8)# 计算填充的上下左右边距top_padding = (target_height - new_height) // 2# bottom_padding = target_height - new_height - top_paddingleft_padding = (target_width - new_width) // 2# right_padding = target_width - new_width - left_padding# 将缩放后的图像放置到填充后的图像中心padded_image[top_padding:top_padding + new_height, left_padding:left_padding + new_width] = resized_imagereturn padded_image, resized_image, left_padding, top_paddingif __name__ == '__main__':# 示例使用image = cv2.imread('./img/lena2.png',1)  # 读取图像  (528, 532, 3)# image_resize=cv2.resize(image,None,fx=0.5,fy=0.5)# cv2.imwrite("img/lena_02.png", image_resize)print("image.shape",image.shape)#(400, 323, 3)target_height = 300  # 目标高度target_width = 400  # 目标宽度padding_value = (114, 114, 114)  # 自定义填充值(RGB)
padded_image, resized_image, left_padding, top_padding = resize_and_pad(image, target_height, target_width,padding_value)print("padded_image.shape", padded_image.shape)# 保存结果cv2.imwrite('result.jpg', padded_image)

  原图

                                    目标图

  如果将目标大小改为height=150,width=200,目标图比原图小,也是先缩放,再填充,如下:

 

小结:缩放填充是一种基本的操作,再图像预处理中,为了使得图片不因形变失真,往往采用这种方式,比如后面会介绍的YOLOV5的图片预处理的方法。

 

参考:

https://blog.csdn.net/weixin_51226647/article/details/139688302

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/841888.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

笔记本电脑复活记

0.前言 一次偶然的停电让我蒙受了巨大的损失。恢复供电之后发现笔记本电脑无法正常启动,经检查发现硬盘坏了。经过检查确认是硬件坏了,但没有损伤盘片。决定通过数据恢复拯救损失的数据。与此同时,电脑的散热风扇已经响了很久了,决定这一次也更换了它。 经过几天的折腾,笔…

某水准测量工具 vb6 程序注册分析

某水准测量工具 vb6 程序注册分析 目录某水准测量工具 vb6 程序注册分析文件信息VB Decompiler Pro注册点击事件 Command1_ClickRJZC.UncrypStrpypsvb 程序,接触不多,仅作记录文件信息 PE32操作系统: Windows(95)[I386, 32 位, GUI]链接程序: Microsoft Linker(6.0)编译器: M…

WinUI(WASDK)使用BotSharp框架开发多智能体桌面机器人管理助手(生图开关灯不在话下)

前言 大语言模型(Large Language Models, LLMs)近年来在各行各业中展现出了巨大的潜力和影响力。从自然语言处理到自动化客服,从内容生成到智能助手,LLMs正在改变我们与技术互动的方式。随着技术的不断进步,LLMs的应用场景也在不断扩展,成为未来发展的重要趋势。这篇文章…

【C++编程】五个分区: 堆、栈、静态(全区)区、 常量区 代码区

在C++中,程序的内存管理被分为几个区域,这些区域每个都有其特定的用途。下面是你提到的五个分区的详细描述: 一、栈区(Stack) 用途:用于存储局部变量和函数调用时的上下文(如返回地址与参数等)。 特点: 采用先进后出(LIFO)原则进行管理。 内存由编译器自动分配和释放…

突破自我

1.寻找红利 红利大抵有以下几种:城市红利、行业红利、时代红利。 城市红利,一个高速发展、人口长期净流入的城市就有城市红利,城市红利主要体现在两点:房产、认知信息、人脉差。有红利的城市在过去20年房价一路向上,安家了基本就等于资产不断升值。有红利的城市带来的认知…

【C++编程】五个分区 堆、栈、静态(全区)区、 常量区 代码区

在C++中,程序的内存管理被分为几个区域,这些区域每个都有其特定的用途。下面是你提到的五个分区的详细描述: 一、栈区(Stack) 用途:用于存储局部变量和函数调用时的上下文(如返回地址与参数等)。 特点: 采用先进后出(LIFO)原则进行管理。 内存由编译器自动分配和释放…

【原创】linux实时操作系统xenomai看门狗(watchdog)机制及作用介绍

本文介绍linux实时操作系统xenomai中的watchdog机制及用途。版权声明:本文为本文为博主原创文章,转载请注明出处 https://www.cnblogs.com/wsg1100。如有错误,欢迎指正。 目录一、前言PREEMPT-RT(RT Throttling)一、xenomai watchdog介绍二、xenomai watchdog工作原理三、…

Logisim-020-☆4位快速加法器

电路文件所在 电路/3-data.circ 中的 ☆4位快速加法器仓库地址 https://gitee.com/gitliang/logisim-to-cpu

基于Java+SpringBoot+Mysql在线简单拍卖竞价拍卖竞拍系统功能设计与实现九

运行环境:windows/Linux均可、jdk1.8、mysql5.7、redis3.0、idea/eclipse均可。 技术点:SpringBoot+SpringDataJPA+Mysql+Freemaker+Bootstrap+JS+CSS+HTML 部分功能:前台项目信息控制器Controller(商品列表、商品管理、商品审核、商品上下架)一、前言介绍: 免费学习:猿…

RGB/INT8 输入注意事项

01 技术背景 在大多数情况下,我们都推荐用户在编译处理图像任务的模型时,将 input_type_rt 参数配置 nv12,这是考虑到视频通路传来的数据通常都是 nv12 类型,这样配置可以最大化地节约耗时,提高全流程的处理效率。 但在前期的算法验证阶段,往往用户更希望模型能直接读取 …

海波龙系统HFM的数据表和各维度取值方法

数据表包括DCE表、DCN表、DCT表 DCE表格存储和值以及相关的日记账调整。 DCN表格存储价值维度剩余成员的数据。 DCT表格存储日记账调整。当日记账被过账时,数据值流向DCE和/或DCN表格。 表的命名格式:APPNAME_[表][场景][年份] 例如:APPNAME_DCE_1_2024, APPNAE应用,DCE表…

.NET9 - Swagger平替Scalar详解(四)

本文分享Swagger中常用功能在Scalar中的使用,包括版本说明、接口分类、接口及参数描述、枚举类型、文件上传和JWT认证等,并提供相关代码示例和效果展示,以及可能遇到的问题和解决方案。书接上回,上一章介绍了Swagger代替品Scalar,在使用中遇到不少问题,今天单独分享一下之…