使用Emgu CV C#创建轮廓掩码以仅显示原图ROI
解决方案:用掩码保留非矩形ROI内的原图内容
我明白你的需求啦——你想要保留那些非矩形轮廓内部的原图内容,把剩下的区域全部置零,而不是简单裁剪。这其实用掩码操作就能轻松实现,结合你现有的Emgu CV代码,我来一步步给你讲清楚怎么做:
核心思路
- 先创建一个和原图完全匹配的全黑掩码(初始时所有区域都是“无效”的)
- 把你检测到的轮廓填充到掩码上,让轮廓内部变成白色(标记为“有效”区域)
- 用掩码和原图做按位与操作,只有掩码白色区域的原图内容会被保留,其余区域自动置零
完整代码示例(结合你的现有代码)
// 你的原有代码:读取图像、检测轮廓 Mat img = CvInvoke.Imread(HttpContext.Current.Server.MapPath("IMAGELOCATION")); VectorOfMat contours = new VectorOfMat(); // ... 各种形态学变换代码 ... CvInvoke.FindContours(maskDilate, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxNone); // --- 新增掩码处理部分 --- // 1. 创建和原图大小、通道数、深度一致的全黑掩码 Mat mask = new Mat(img.Size, img.Depth, img.NumberOfChannels); mask.SetTo(new MCvScalar(0, 0, 0)); // 初始全黑 // 2. 在掩码上填充所有轮廓为白色(厚度-1表示填充内部) // 注意:这里contourIdx用-1表示绘制所有轮廓,如果你需要特定轮廓可以改对应索引 CvInvoke.DrawContours(mask, contours, -1, new MCvScalar(255, 255, 255), -1); // 3. 原图与掩码做按位与,保留轮廓内的内容,其余区域置零 Mat result = new Mat(); CvInvoke.BitwiseAnd(img, mask, result); // 之后你可以保存或显示result,就是你要的效果 // CvInvoke.Imwrite("RESULT_PATH", result);
关键细节说明
- 掩码匹配:一定要保证掩码的尺寸、通道数、深度和原图完全一致,否则
BitwiseAnd会报错。比如如果你的原图是灰度图(单通道),那掩码也要是单通道,此时MCvScalar只用传一个值:new MCvScalar(255) - 轮廓填充:
DrawContours的最后一个参数用-1表示填充轮廓内部,这是生成有效掩码的关键 - 按位与原理:
BitwiseAnd会逐像素对比原图和掩码,只有当两者对应像素都不为0时,结果才保留原图的像素值;掩码黑色区域(0)会把原图对应区域直接置零,完美满足你的需求
另外提一句:你原有代码里DrawContours的-6应该是笔误吧?正常contourIdx参数用-1表示绘制所有轮廓,如果你只需要特定轮廓,可以改成对应的索引~
内容的提问来源于stack exchange,提问作者TechnoloG
相关产品推荐
相关产品推荐

