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

OpenCV C++如何自定义位置拼接两张图片并保存为单张图片

问题解答

完全可以实现,OpenCV的ROI(感兴趣区域)机制刚好匹配自定义位置拼接图片的需求,你描述的场景实现逻辑非常清晰。

实现思路

  • 先读取两张PNG原图,若需要保留PNG的透明通道,读取时需携带cv::IMREAD_UNCHANGED参数
  • 计算合成画布的尺寸:宽度取「第一张图宽度」和「第二张图X偏移值+第二张图宽度」的最大值,高度取「第一张图高度」和「第二张图Y偏移值+第二张图高度」的最大值,确保两张图都能完整显示在画布内
  • 初始化和画布尺寸一致的空白底图,背景可根据需求设置为透明、白色或其他自定义颜色
  • 将第一张图拷贝到画布从(0,0)坐标开始的对应ROI区域
  • 将第二张图拷贝到画布从(50,50)坐标开始的对应ROI区域,若图片携带透明通道需要额外做alpha融合,避免透明区域直接覆盖画布内容
  • 最后调用cv::imwrite导出合成后的单张图片

可直接运行的示例代码

#include <opencv2/opencv.hpp>

int main() {
    // 读取两张PNG图,保留透明通道
    cv::Mat img1 = cv::imread("img1.png", cv::IMREAD_UNCHANGED);
    cv::Mat img2 = cv::imread("img2.png", cv::IMREAD_UNCHANGED);
    
    if (img1.empty() || img2.empty()) {
        printf("图片读取失败,请检查文件路径是否正确\n");
        return -1;
    }

    // 计算画布尺寸
    int canvas_width = std::max(img1.cols, 50 + img2.cols);
    int canvas_height = std::max(img1.rows, 50 + img2.rows);

    // 初始化四通道空白画布,默认背景全透明
    cv::Mat canvas(canvas_height, canvas_width, CV_8UC4, cv::Scalar(0, 0, 0, 0));

    // 拷贝第一张图到(0,0)位置
    cv::Rect roi1(0, 0, img1.cols, img1.rows);
    img1.copyTo(canvas(roi1));

    // 拷贝第二张图到(50,50)位置,兼容透明通道融合
    cv::Rect roi2(50, 50, img2.cols, img2.rows);
    if (img2.channels() == 4) {
        // 带透明通道的融合逻辑
        for (int y = 0; y < img2.rows; y++) {
            for (int x = 0; x < img2.cols; x++) {
                cv::Vec4b &pixel_canvas = canvas.at<cv::Vec4b>(y + 50, x + 50);
                cv::Vec4b &pixel_img2 = img2.at<cv::Vec4b>(y, x);
                double alpha = pixel_img2[3] / 255.0;
                // 融合RGB通道
                pixel_canvas[0] = pixel_img2[0] * alpha + pixel_canvas[0] * (1 - alpha);
                pixel_canvas[1] = pixel_img2[1] * alpha + pixel_canvas[1] * (1 - alpha);
                pixel_canvas[2] = pixel_img2[2] * alpha + pixel_canvas[2] * (1 - alpha);
                // 更新alpha通道
                pixel_canvas[3] = std::max(pixel_canvas[3], pixel_img2[3]);
            }
        }
    } else {
        // 无透明通道直接拷贝
        img2.copyTo(canvas(roi2));
    }

    // 导出合成结果
    cv::imwrite("merged.png", canvas);
    return 0;
}

注意事项

  • 若不需要保留透明通道,读取图片时可以省略cv::IMREAD_UNCHANGED参数,画布也可以改为三通道CV_8UC3
  • 偏移坐标可根据需求任意调整,需要保证ROI区域不超出画布边界,否则OpenCV会直接抛出异常
  • 如果需要调整单张图的尺寸再拼接,可以先调用cv::resize处理原图,再拷贝到画布对应位置

内容的提问来源于stack exchange,提问作者curiousJorgeXX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:42:03