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

为何OpenCV的resize与对应warpAffine方法输出结果不一致?

OpenCV中warpAffine与resize结果不一致的问题分析

问题背景

重构代码时尝试用warpAffine方法替代resize,却发现最终输出结果存在差异。以下是测试代码及差异表现:

测试代码

cv::Mat warp_resize(const cv::Mat& image, int newSizeX, int newSizeY)
{
    cv::Mat out = cv::Mat::zeros(newSizeY, newSizeX, image.type());
    auto kx     = static_cast<double>(newSizeX) / image.cols;
    auto ky     = static_cast<double>(newSizeY) / image.rows;
    cv::Mat mat = (cv::Mat_<double>(2, 3) << kx, 0, 0, 0, ky, 0);
    cv::warpAffine(image, out, mat, out.size(), cv::INTER_LINEAR);
    return out;
}

cv::Mat resize_func(const cv::Mat& image, int newSizeX, int newSizeY)
{
    cv::Mat out = cv::Mat::zeros(newSizeY, newSizeX, image.type());
    auto kx     = static_cast<double>(newSizeX) / image.cols;
    auto ky     = static_cast<double>(newSizeY) / image.rows;
    cv::resize(image, out, cv::Size(), kx, ky, cv::INTER_LINEAR);
    return out;
}

void test()
{
    auto image = cv::imread("c:/temp/resize_test/lena.png", cv::IMREAD_GRAYSCALE);
    const auto warped = warp_resize(image, 50, 100);
    const auto resized = resize_func(image, 50, 100);
    cv::Mat result;
    cv::subtract(warped, resized, result, cv::noArray());
    cv::imwrite("c:/temp/resize_test/diff.png", result);
 }

测试素材与差异

  • 初始测试图:
    lena.png
  • 结果差异图(可见明显轮廓差异):
    差异图

问题根源

核心差异来自OpenCV中resize与warpAffine的坐标映射逻辑不同:

  • resize函数在计算采样位置时,默认以像素中心作为坐标基准。比如输出图像中第(i,j)个像素的中心坐标是(j+0.5, i+0.5),反向映射到输入图像时会基于这个中心位置计算对应采样点。
  • 你当前使用的warpAffine变换矩阵直接对像素左上角坐标进行缩放(即输出图像的(j,i)像素左上角对应输入图像的(jkx, iky)位置),没有考虑像素中心的偏移,导致整体采样位置偏移了半个像素,最终输出出现轮廓差异。

修正方案

调整warpAffine的变换矩阵,加入中心对齐的偏移量,让其坐标映射逻辑与resize一致。修正后的warp_resize函数如下:

cv::Mat warp_resize(const cv::Mat& image, int newSizeX, int newSizeY)
{
    cv::Mat out = cv::Mat::zeros(newSizeY, newSizeX, image.type());
    auto kx     = static_cast<double>(newSizeX) / image.cols;
    auto ky     = static_cast<double>(newSizeY) / image.rows;
    
    // 计算中心对齐的偏移量
    double dx = (0.5 - kx * 0.5);
    double dy = (0.5 - ky * 0.5);
    
    // 构建包含偏移的变换矩阵
    cv::Mat mat = (cv::Mat_<double>(2, 3) << kx, 0, dx, 0, ky, dy);
    cv::warpAffine(image, out, mat, out.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0));
    return out;
}

修正后,warpAffine的坐标映射会先将输出像素中心反向映射到输入图像的中心位置,与resize的逻辑完全对齐,两者输出结果将无差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:25:18