OpencvSharp 算子学习教案之 - Cv2.BlendLinear OpencvSharp 算子学习教案之 - Cv2.BlendLinear大家好Opencv在很多工程项目中都会用到而OpencvSharp则是以C#开发与实现的Opencv操作库对.NET开发人员友好但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案供大家参考学习。Cv2.BlendLinear教案版本V1.0面向对象OpenCvSharp 初学者所属模块imgproc源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs:2414摘要Cv2.BlendLinear会按照两张同尺寸图像的逐像素权重做线性融合。它最适合讲清楚“每个像素都可以有自己的混合比例”这一点也很适合做渐变过渡、遮罩融合和拼接缝平滑处理。1. 函数名称带参数签名publicstaticvoidBlendLinear(InputArraysrc1,InputArraysrc2,InputArrayweights1,InputArrayweights2,OutputArraydst)2. 函数用途Cv2.BlendLinear用来把两张同尺寸、同类型的图像按像素权重融合成一张新图。它和AddWeighted的区别在于AddWeighted通常使用两个常量权重。BlendLinear使用的是两张权重图所以每个像素都能有自己的混合比例。当你想在图像左边更偏向图 A、右边更偏向图 B 时这个函数非常合适。它也常被用于图像拼接、遮罩过渡和局部混合。3. 函数公式对任意一个像素位置p ppBlendLinear 的核心关系可以写成d s t ( p ) w e i g h t s 1 ( p ) ⋅ s r c 1 ( p ) w e i g h t s 2 ( p ) ⋅ s r c 2 ( p ) dst(p) weights1(p) \cdot src1(p) weights2(p) \cdot src2(p)dst(p)weights1(p)⋅src1(p)weights2(p)⋅src2(p)如果你希望结果看起来“自然过渡”通常会让w e i g h t s 1 ( p ) w e i g h t s 2 ( p ) 1 weights1(p) weights2(p) 1weights1(p)weights2(p)1这样输出就相当于两张图按比例做线性插值。若权重和不等于 1输出就可能整体变亮或变暗。4. 函数原理说明这个函数的工作方式可以分成四步理解先检查两张输入图是否同尺寸、同类型。再检查两张权重图是否和输入图同尺寸。对每个像素点分别取出src1、src2、weights1、weights2的值。按照线性组合公式计算输出。对初学者来说最重要的是区分“常量权重”和“权重图”常量权重只会影响整张图。权重图会让图像在不同位置呈现不同的融合比例。如果两张权重图做成互补关系过渡区域会非常平滑。5. 参数含义解析参数名类型必填含义src1InputArray是第一张输入图像src2InputArray是第二张输入图像weights1InputArray是第一张权重图类型必须是CV_32FC1weights2InputArray是第二张权重图类型必须是CV_32FC1dstOutputArray是输出图像补充说明src1和src2必须尺寸相同类型也要相同。weights1和weights2必须和源图尺寸一致。权重图必须是单通道浮点数图像最常用的是CV_32FC1。输出图像会沿用源图的数据类型和通道数。6. 应用场景列表场景名场景说明典型用途场景A渐变过渡让左边更偏向第一张图右边更偏向第二张图渐变融合、图像过渡场景B拼接缝平滑在两张图重叠区域使用不同权重全景拼接、缝合线隐藏场景C局部叠加只在局部区域让某张图权重更高目标叠加、局部增强场景D教学演示把权重图本身可视化帮助初学者理解公式算法教学、调试验证7. 函数使用示例与 WPF 场景一一对应说明下面代码对应 WPF 示例里的“BlendLinear”场景。为了让初学者更容易理解这里用两张简单的彩色卡片和一张水平渐变权重图来演示。usingSystem;usingOpenCvSharp;internalstaticclassProgram{privatestaticvoidMain(){// 先构造两张同尺寸彩色图第一张偏暖色第二张偏冷色。usingvarsrc1CreateWarmCard();usingvarsrc2CreateCoolCard();// 这两张权重图都必须是 CV_32FC1并且尺寸要和源图一致。usingvarweights1CreateHorizontalWeights(src1.Size(),inverse:true);usingvarweights2CreateHorizontalWeights(src2.Size(),inverse:false);// 输出图像由 BlendLinear 生成。usingvarblendednewMat();Cv2.BlendLinear(src1,src2,weights1,weights2,blended);// 把结果保存到磁盘方便和原图对照观察。Cv2.ImWrite(blendlinear_src1.png,src1);Cv2.ImWrite(blendlinear_src2.png,src2);Cv2.ImWrite(blendlinear_weights.png,CreateHeatmapPreview(weights2));Cv2.ImWrite(blendlinear_blended.png,blended);Console.WriteLine(BlendLinear 演示已完成。);}privatestaticMatCreateWarmCard(){// 创建一张暖色背景图便于观察融合后的变化。varcanvasnewMat(240,360,MatType.CV_8UC3,newScalar(236,238,248));// 叠加几个简单图形让图像里有明显的颜色区域。Cv2.Rectangle(canvas,newRect(20,28,110,82),newScalar(46,150,240),-1,LineTypes.AntiAlias);Cv2.Circle(canvas,newPoint(198,88),48,newScalar(74,182,96),-1,LineTypes.AntiAlias);Cv2.Ellipse(canvas,newPoint(266,170),newSize(64,40),-15,0,360,newScalar(62,92,216),-1,LineTypes.AntiAlias);Cv2.PutText(canvas,Warm,newPoint(30,214),HersheyFonts.HersheySimplex,0.9,newScalar(40,40,40),2,LineTypes.AntiAlias);returncanvas;}privatestaticMatCreateCoolCard(){// 创建一张冷色背景图和第一张图形成鲜明对比。varcanvasnewMat(240,360,MatType.CV_8UC3,newScalar(246,242,236));Cv2.Rectangle(canvas,newRect(24,34,108,76),newScalar(232,120,88),-1,LineTypes.AntiAlias);Cv2.Circle(canvas,newPoint(202,92),50,newScalar(86,210,188),-1,LineTypes.AntiAlias);Cv2.Ellipse(canvas,newPoint(266,176),newSize(64,40),18,0,360,newScalar(142,92,238),-1,LineTypes.AntiAlias);Cv2.PutText(canvas,Cool,newPoint(270,214),HersheyFonts.HersheySimplex,0.9,newScalar(40,40,40),2,LineTypes.AntiAlias);returncanvas;}privatestaticMatCreateHorizontalWeights(Sizesize,boolinverse){// 创建一张从左到右变化的浮点权重图。varweightsnewMat(size.Height,size.Width,MatType.CV_32FC1);for(varrow0;rowsize.Height;row){for(varcol0;colsize.Width;col){varalphacol/(float)(size.Width-1);weights.Atfloat(row,col)inverse?1f-alpha:alpha;}}returnweights;}privatestaticMatCreateHeatmapPreview(Matsource){// 先把浮点权重图规范化到 0~255再用热力图显示出来。usingvarnormalizednewMat();source.ConvertTo(normalized,MatType.CV_8UC1,255.0);varpreviewnewMat();Cv2.ApplyColorMap(normalized,preview,ColormapTypes.Turbo);returnpreview;}}8. 常见错误与避坑weights1或weights2不是CV_32FC1会导致运行时异常。两张输入图尺寸不同函数无法直接处理。权重图尺寸和输入图不一致也会失败。权重和不接近 1 时结果可能整体偏亮或偏暗。把整数矩阵当作权重图使用会让比例计算失去精度。9. 进阶扩展可以用线性渐变权重图做“左右平滑过渡”的拼接缝。可以把权重图换成从分割结果生成的 mask实现更智能的融合。可以先对权重图做模糊处理再融合进一步减弱边界。可以把同样的思路扩展到多张图逐步完成全景拼接或区域混合。10. 小结Cv2.BlendLinear的本质是“逐像素线性插值”。只要记住三点就够了两张源图必须同尺寸、同类型。两张权重图必须是CV_32FC1并且和源图同尺寸。如果希望结果自然通常让两个权重互补也就是一高一低、总和接近 1。11. 相关链接WPF 教学控件Cv2BlendLinearControl.xaml.cs样例实现BlendLinearSample.cs官方文档源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs:2414