LetterBox图像缩放一、技术背景在深度学习目标检测中不同尺寸的输入图像需要统一缩放到模型要求的固定尺寸。直接缩放会导致图像变形影响检测精度。LetterBox信箱框技术通过保持原始宽高比进行缩放并用灰色填充空白区域既保证了图像几何特性不变形又满足了模型输入尺寸要求。YOLO系列模型采用LetterBox预处理在缩放图像时保持原始宽高比不足部分用灰色114, 114, 114填充确保检测结果可以准确还原到原始图像坐标。二、数学原理2.1 缩放比例计算设原始图像尺寸为(Horig,Worig)(H_{orig}, W_{orig})(Horig​,Worig​)目标尺寸为(Htarget,Wtarget)(H_{target}, W_{target})(Htarget​,Wtarget​)缩放比例rrr取高度和宽度缩放比例的最小值rmin⁡(HtargetHorig,WtargetWorig)r \min\left(\frac{H_{target}}{H_{orig}}, \frac{W_{target}}{W_{orig}}\right)rmin(Horig​Htarget​​,Worig​Wtarget​​)2.2 新尺寸计算根据缩放比例计算缩放后的图像尺寸Wnew⌊Worig×r⌋W_{new} \lfloor W_{orig} \times r \rfloorWnew​⌊Worig​×r⌋Hnew⌊Horig×r⌋H_{new} \lfloor H_{orig} \times r \rfloorHnew​⌊Horig​×r⌋2.3 填充量计算计算需要在图像周围填充的灰色边框宽度dwWtarget−Wnewdw W_{target} - W_{new}dwWtarget​−Wnew​dhHtarget−Hnewdh H_{target} - H_{new}dhHtarget​−Hnew​填充分布在图像两侧左填充left⌊dw/2⌋left \lfloor dw / 2 \rfloorleft⌊dw/2⌋右填充rightdw−leftright dw - leftrightdw−left上填充top⌊dh/2⌋top \lfloor dh / 2 \rfloortop⌊dh/2⌋下填充bottomdh−topbottom dh - topbottomdh−top2.4 坐标还原公式将LetterBox后的坐标(x′,y′)(x, y)(x′,y′)还原到原始图像坐标(x,y)(x, y)(x,y)xx′−padxrx \frac{x - pad_x}{r}xrx′−padx​​yy′−padyry \frac{y - pad_y}{r}yry′−pady​​其中padxpad_xpadx​和padypad_ypady​为水平、垂直方向的填充偏移量。三、代码实现3.1 LetterBox缩放函数// 文件路径: e:\SEM\Yolo11_section\Utils.cs// 缩放并填充到要求输入大小publicstaticvoidSegLetterBox(Matimage,outMatoutImage,OpenCvSharp.SizenewShape,Scalarcolor,boolautoPadtrue,boolscaleFillfalse,boolscaleUptrue,intstride32){// 计算缩放比例取高度和宽度缩放比例的最小值floatrMath.Min((float)newShape.Height/image.Rows,(float)newShape.Width/image.Cols);// 如果不允许放大则限制比例不超过1.0if(!scaleUp)rMath.Min(r,1.0f);// 计算缩放后的新尺寸intnewW(int)Math.Round(image.Cols*r);intnewH(int)Math.Round(image.Rows*r);// 计算需要填充的空白区域intdwnewShape.Width-newW;intdhnewShape.Height-newH;// 自动填充确保填充量是stride的整数倍if(autoPad){dw%stride;dh%stride;}elseif(scaleFill){// 直接拉伸填充整个目标区域newWnewShape.Width;newHnewShape.Height;dwdh0;}// 使用线性插值缩放图像varresizednewMat();Cv2.Resize(image,resized,newOpenCvSharp.Size(newW,newH),0,0,InterpolationFlags.Linear);// 计算上下左右填充量均匀分布inttopdh/2;intbottomdh-top;intleftdw/2;intrightdw-left;// 使用指定颜色填充边框outImagenewMat();Cv2.CopyMakeBorder(resized,outImage,top,bottom,left,right,BorderTypes.Constant,color);}3.2 坐标还原函数// 文件路径: e:\SEM\Yolo11_section\Utils.cs// 将模型输出的坐标转换为原始图像的坐标publicstaticSegBoundingBoxScaleCoords(OpenCvSharp.SizeletterboxShape,SegBoundingBoxbox,OpenCvSharp.SizeorigShape,boolcliptrue){// 计算缩放增益floatgainMath.Min((float)letterboxShape.Height/origShape.Height,(float)letterboxShape.Width/origShape.Width);// 计算填充偏移量intpadX(int)Math.Round((letterboxShape.Width-origShape.Width*gain)/2.0);intpadY(int)Math.Round((letterboxShape.Height-origShape.Height*gain)/2.0);// 坐标还原公式intx(int)Math.Round((box.X-padX)/gain);inty(int)Math.Round((box.Y-padY)/gain);intw(int)Math.Round(box.Width/gain);inth(int)Math.Round(box.Height/gain);// 可选裁剪到原始图像边界if(clip){xClamp(x,0,origShape.Width);yClamp(y,0,origShape.Height);wClamp(w,0,origShape.Width-x);hClamp(h,0,origShape.Height-y);}returnnewSegBoundingBox(x,y,w,h,box.ClassId,box.Score,box.MaskCoefficients);}3.3 预处理调用// 文件路径: e:\SEM\Yolo11_section\Utils.cspublicstaticMatPreprocess(Matimage,OpenCvSharp.SizeinputSize,boolisDynamic,reffloat[]inputTensor,reflong[]inputShape){MatletterboxImage;// 调用LetterBox使用灰色(114,114,114)填充SegLetterBox(image,outletterboxImage,inputSize,newScalar(114,114,114),isDynamic,false,true,32);inputShape[2]letterboxImage.Rows;inputShape[3]letterboxImage.Cols;// 归一化到[0,1]letterboxImage.ConvertTo(letterboxImage,MatType.CV_32FC3,1.0/255.0);// ... 后续转换为CHW格式张量returnletterboxImage;}四、参数调优4.1 填充颜色选择颜色值适用场景特点(114, 114, 114)YOLO标准与图像内容区分明显(0, 0, 0)深色背景适合暗色图像(128, 128, 128)中性灰通用性较好(255, 255, 255)白色背景适合浅色图像4.2 stride参数影响stride参数确保输出尺寸是stride的整数倍这对某些需要下采样的网络结构很重要stride32适用于YOLO系列因为最大下采样倍数为32stride16适用于较浅层网络stride1不进行约束4.3 插值方法选择// 不同插值方法InterpolationFlags.Linear// 线性插值默认速度快InterpolationFlags.Area// 区域插值缩小时质量好InterpolationFlags.Cubic// 三次插值放大时质量好InterpolationFlags.Lanczos4// Lanczos插值质量最高五、常见问题5.1 坐标还原偏差问题描述检测框还原后位置不准确出现偏移。解决方案确保缩放增益计算正确使用Math.Min取最小比例填充偏移使用Round四舍五入检查clip参数是否正确裁剪边界5.2 填充区域检测问题问题描述模型在灰色填充区域产生误检测。解决方案使用与训练数据一致的填充颜色114, 114, 114在后处理阶段过滤掉完全位于填充区域的检测框训练时对数据进行LetterBox增强5.3 动态输入尺寸处理问题描述模型支持动态输入尺寸时如何处理解决方案// 动态模式下stride约束生效if(autoPad){dw%stride;// 确保尺寸是stride的整数倍dh%stride;}5.4 高宽比极端情况问题描述图像高宽比极端时填充区域过大。解决方案使用scaleFilltrue放弃宽高比约束会变形调整输入尺寸使其与图像宽高比接近分块处理极端尺寸图像5.5 内存管理问题描述LetterBox操作产生大量临时Mat对象。解决方案// 及时释放临时对象varresizednewMat();Cv2.Resize(image,resized,newOpenCvSharp.Size(newW,newH),0,0,InterpolationFlags.Linear);// ... 使用resizedresized.Dispose();// 手动释放