为何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); }
测试素材与差异
- 初始测试图:

- 结果差异图(可见明显轮廓差异):

问题根源
核心差异来自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
相关产品推荐
相关产品推荐

