Android OpenCV undistort 图像从看似相同的 python 实现中产生不同的结果

Android OpenCV undistort image produces different results from a seemingly identical python implementation

我们有一个简单的 python 例程,它拍摄图像并通过调用 cv2.fisheye.undistortImage() 来消除失真。它根据输入图像和提供的相机矩阵产生预期的结果。

我将 python 功能移植到 Android。当输入相同的图像时,Android 版本不会产生相同的结果,我不明白为什么。我在港口遗漏了什么吗?

Python 来源(按预期工作)

cx = 960 
cy = 540
val = 600   

K = np.array([[  val,     0.  ,  cx],
            [    0. ,   val   ,  cy],
            [    0. ,    0.   ,  1.  ]])

# zero distortion coefficients work well for this image
D = np.array([0., 0., 0., 0.])

# use Knew to scale the output
Knew = K.copy()
Knew[(0,1), (0,1)] = 0.4 * Knew[(0,1), (0,1)]

img = cv2.imread('fisheye_sample.jpg')

img_undistorted = cv2.fisheye.undistortImage(img, K, D=D, Knew=Knew)
cv2.imwrite('fisheye_sample_undistorted.jpg', img_undistorted)

现在,python代码移植到Android如下:

Android端口(未产生预期结果)

float fishVal = 600.0f;
float cX = 960;
float cY = 540;
Mat K = new Mat(3, 3, CvType.CV_32FC1);
K.put(0, 0, new float[]{fishVal, 0, cX});
K.put(1, 0, new float[]{0, fishVal, cY});
K.put(2, 0, new float[]{0, 0, 1});

Mat D = new Mat(1, 4, CvType.CV_32FC1);
D.put(0, 0, new float[]{0, 0, 0, 0});

Mat Knew = K.clone();
Knew.put(0, 0, new float[]{fishVal * 0.4f, 0.0f, cX});
Knew.put(1, 0, new float[]{0.0f, fishVal * 0.4f, cY});
Knew.put(2, 0, new float[]{0.0f, 0.0f, 1.0f});

Mat dst = new Mat(greyScaleMat.rows(), greyScaleMat.cols(), greyScaleMat.type());
Imgproc.undistort(greyScaleMat, dst, K, D, Knew);

给定一个恒定的输入,我希望这两个实现产生相同的输出。这没有发生。 Python 版本做了一些不失真,但 Android 版本似乎忽略了一些输入参数。我没有看到的 Android 端口有问题吗?

输入图像

Python 输出图像(正确!) 下图没有像预期的那样失真 Android 输出图像(不正确!) 当运行通过Android函数如上所述时,没有执行不失真。相反,图像根据 Knew 矩阵按比例缩小。关于如何解释这种差异的任何想法?

经过多方摸索、论坛搜索和源代码调查,我找到了答案。 原来 Imgproc.undistort() 的实现是 而不是 cv2.fisheye.UndistortImage()

一样

Java/JNI 世界中的等价物是 Calib3d.undistortImage()。调用该函数时,输出与 python 版本相同。

必须将 Android 的 OpenCV 升级到高于 3 的版本才能使用此功能。