OpenCV C++去除图像黑边并正确保存裁剪后图像求助
嗨,我来帮你解决这个问题!你现在保存的图像有黑边,核心原因是你的res变量其实还是原图像的完整尺寸——只是ROI以外的区域被mask变成了黑色,所以保存的时候整个大图像都被写进去了,自然带着黑边。
下面分两种常见情况给出解决方案:
情况1:你用的是矩形ROI(最常用场景)
如果你的ROI工具选的是矩形区域,那直接提取这个矩形区域的图像就行,根本不需要做mask与运算,步骤更简单:
修改后的代码:
Mat mask,draft,res; int nPixels; char c=0; while(true && c!='q') { imshow("SAMPLE", img); if(!roi.isSet()) roi.set("SAMPLE"); if (roi.isSet()) { // 获取你选中的矩形ROI范围 Rect roiRect = roi.getRect(); // 直接从原图像中提取ROI区域(clone避免原图像引用问题) res = img(roiRect).clone(); // 现在保存的就是纯裁剪后的图像,没有黑边 imwrite("cropped.png", res); imshow("draft", res); } c = waitKey(1); }
情况2:你用的是不规则形状的ROI
如果你的ROI是手绘的任意不规则形状,那需要先找到mask中非零区域的最小包围矩形,再把res裁剪到这个矩形里:
修改后的代码(记得先包含轮廓相关头文件):
#include <vector> // 必须包含这个头文件来使用轮廓相关函数 Mat mask,draft,res; int nPixels; char c=0; while(true && c!='q') { imshow("SAMPLE", img); if(!roi.isSet()) roi.set("SAMPLE"); if (roi.isSet()) { roi.createMask(img.size()); mask = roi.getMask(); res = mask & img.clone(); // 找到mask里非零区域的轮廓 vector<vector<Point>> contours; findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 确保找到轮廓后再执行裁剪 if(!contours.empty()){ // 获取轮廓的最小包围矩形 Rect cropRect = cv::boundingRect(contours[0]); // 裁剪res到这个矩形范围 res = res(cropRect).clone(); imwrite("cropped.png", res); imshow("draft", res); } } c = waitKey(1); }
补充说明:为什么原来的方法会有黑边?
你之前的res = mask & img.clone()操作,只是把原图像中ROI以外的像素置为黑色,但图像的宽高和原图像完全一致。imwrite会把整个图像(包括那些黑色区域)都保存下来,所以才会出现黑边。我们的目标是只保留ROI对应的那部分像素,因此需要主动裁剪出这个区域再保存。
内容的提问来源于stack exchange,提问作者Drex Signe
相关产品推荐
相关产品推荐

