You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:18:40