OpenCV 鱼眼校准 C++ 输出不同于 Python
OpenCV fisheye calibration C++ output differs from Python
我目前正在研究有鱼眼的相机(虽然不多但仍然如此),我正在努力消除它的失真。
作为初学者:我对 opencv 不是很熟悉,在尝试做任何事情时我总是喜欢看文档。 (and/or 在这里寻找我的问题的答案)。
所以我在网上看到了一些例子,我尝试了解决方案并得到了一些结果。
这是我的发现:
DIM=(1094, 729)
K=np.array([
[1307.2807020496643, 0.0, 530.3754311563506],
[0.0, 1318.342691460933, 354.98352268131123],
[0.0, 0.0, 1.0]
])
D=np.array([
[-0.2994762856767568],
[0.5036082961388784],
[-4.231072729639434],
[3.8646397788794578]
])
def undistort(img_path):
img = cv2.imread(img_path)
h,w = img.shape[:2]
print(K)
print(D)
print(np.eye(3))
print(DIM)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
cv2.imshow("undistorted", undistorted_img)
cv2.imwrite("test.jpg", undistorted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
for p in sys.argv[1:]:
undistort(p)
这是我用来消除图像失真的 python 脚本。顶部的数据 (K & D) 是通过另一个脚本生成的。我没有提到它,因为我有一个 C++ 翻译,它显示相同 base_picture
的相同结果
对于这个函数,如果我给出一个扭曲的图像,比如:
我得到了这个结果:
所以我可以看到微小的失真已经解决了。
但是当我尝试在 C++ 中实现相同的功能时,如下所示:
src = cv::imread(“path/to/image.jpg");
cv::Size size = {src.cols, src.rows};
cv::Mat K(3, 3, cv::DataType<double>::type);
K.at<double>(0, 0) = 1307.2807020496643;
K.at<double>(0, 1) = 0.0;
K.at<double>(0, 2) = 530.3754311563506;
K.at<double>(1, 0) = 0.0;
K.at<double>(1, 1) = 1318.342691460933;
K.at<double>(1, 2) = 354.98352268131123;
K.at<double>(2, 0) = 0.0;
K.at<double>(2, 1) = 0.0;
K.at<double>(2, 2) = 1.0;
cv::Mat D(4, 1, cv::DataType<double>::type);
D.at<double>(0, 0) = -0.2994762856767568;
D.at<double>(1, 0) = 0.5036082961388784;
D.at<double>(2, 0) = -4.231072729639434;
D.at<double>(3, 0) = 3.8646397788794578;
cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);
cv::Mat map1;
cv::Mat map2;
std::cout << K << std::endl;
std::cout << D << std::endl;
std::cout << E << std::endl;
std::cout << size << std::endl;
cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::Mat undistort;
cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
CV_HAL_BORDER_CONSTANT);
基本图像仍然相同,但我得到的结果是:
如您所知,情况变得更糟了……
我在我的 python 脚本和 C++ 程序中丢弃了 K、D 和 E(对于相同的基本图片,两者给出相同的结果)(我的意思是当我计算数据时)
从 initUndistortRectifyMap 到重新映射都出错,最后 imshow 完全不是我所期望的。
我尝试在 python 脚本和 C++ 程序中转储 map1 和 map2(没有查看所有数据),我注意到其中一张地图的末尾(没有两者都看)结果不同。
由于我使用相同的参数调用该函数(据我所知),我希望两个程序之间的映射相等。
我做错了什么吗?喜欢弄乱类型之类的吗?
从 cv::imread 或从相机获取的帧计算图像会改变什么吗?
(只是让你知道,进行计算的帧(.jpg)是来自相机帧采集的cv::imwrite,那么我打算不再使用图像而只是工作cv::Mat 填充了相机采集的数据。)
(我知道最后枚举不一样,但即使使用 cv::BORDER_CONSTANT
我仍然有同样的问题。)
您使用了 cv::initUndistortRectifyMap
而不是 cv::fisheye::initUndistortRectifyMap
使用这段代码我得到了正确的结果:
int main()
{
cv::Mat src = cv::imread("C:/Whosebug/Input/fisheyeCalib.jpg");
cv::Size size = { src.cols, src.rows };
cv::Mat K(3, 3, cv::DataType<double>::type);
K.at<double>(0, 0) = 1307.2807020496643;
K.at<double>(0, 1) = 0.0;
K.at<double>(0, 2) = 530.3754311563506;
K.at<double>(1, 0) = 0.0;
K.at<double>(1, 1) = 1318.342691460933;
K.at<double>(1, 2) = 354.98352268131123;
K.at<double>(2, 0) = 0.0;
K.at<double>(2, 1) = 0.0;
K.at<double>(2, 2) = 1.0;
cv::Mat D(4, 1, cv::DataType<double>::type);
D.at<double>(0, 0) = -0.2994762856767568;
D.at<double>(1, 0) = 0.5036082961388784;
D.at<double>(2, 0) = -4.231072729639434;
D.at<double>(3, 0) = 3.8646397788794578;
cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);
cv::Mat map1;
cv::Mat map2;
std::cout << K << std::endl;
std::cout << D << std::endl;
std::cout << E << std::endl;
std::cout << size << std::endl;
// Here's the error:
//cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::fisheye::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::Mat undistort;
cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
CV_HAL_BORDER_CONSTANT);
cv::imwrite("C:/Whosebug/Input/fisheyeCalib_output.jpg", undistort);
cv::imshow("undist", undistort);
cv::waitKey(0);
}
我目前正在研究有鱼眼的相机(虽然不多但仍然如此),我正在努力消除它的失真。
作为初学者:我对 opencv 不是很熟悉,在尝试做任何事情时我总是喜欢看文档。 (and/or 在这里寻找我的问题的答案)。
所以我在网上看到了一些例子,我尝试了解决方案并得到了一些结果。
这是我的发现:
DIM=(1094, 729)
K=np.array([
[1307.2807020496643, 0.0, 530.3754311563506],
[0.0, 1318.342691460933, 354.98352268131123],
[0.0, 0.0, 1.0]
])
D=np.array([
[-0.2994762856767568],
[0.5036082961388784],
[-4.231072729639434],
[3.8646397788794578]
])
def undistort(img_path):
img = cv2.imread(img_path)
h,w = img.shape[:2]
print(K)
print(D)
print(np.eye(3))
print(DIM)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
cv2.imshow("undistorted", undistorted_img)
cv2.imwrite("test.jpg", undistorted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
for p in sys.argv[1:]:
undistort(p)
这是我用来消除图像失真的 python 脚本。顶部的数据 (K & D) 是通过另一个脚本生成的。我没有提到它,因为我有一个 C++ 翻译,它显示相同 base_picture
的相同结果对于这个函数,如果我给出一个扭曲的图像,比如:
所以我可以看到微小的失真已经解决了。
但是当我尝试在 C++ 中实现相同的功能时,如下所示:
src = cv::imread(“path/to/image.jpg");
cv::Size size = {src.cols, src.rows};
cv::Mat K(3, 3, cv::DataType<double>::type);
K.at<double>(0, 0) = 1307.2807020496643;
K.at<double>(0, 1) = 0.0;
K.at<double>(0, 2) = 530.3754311563506;
K.at<double>(1, 0) = 0.0;
K.at<double>(1, 1) = 1318.342691460933;
K.at<double>(1, 2) = 354.98352268131123;
K.at<double>(2, 0) = 0.0;
K.at<double>(2, 1) = 0.0;
K.at<double>(2, 2) = 1.0;
cv::Mat D(4, 1, cv::DataType<double>::type);
D.at<double>(0, 0) = -0.2994762856767568;
D.at<double>(1, 0) = 0.5036082961388784;
D.at<double>(2, 0) = -4.231072729639434;
D.at<double>(3, 0) = 3.8646397788794578;
cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);
cv::Mat map1;
cv::Mat map2;
std::cout << K << std::endl;
std::cout << D << std::endl;
std::cout << E << std::endl;
std::cout << size << std::endl;
cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::Mat undistort;
cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
CV_HAL_BORDER_CONSTANT);
基本图像仍然相同,但我得到的结果是:
如您所知,情况变得更糟了……
我在我的 python 脚本和 C++ 程序中丢弃了 K、D 和 E(对于相同的基本图片,两者给出相同的结果)(我的意思是当我计算数据时)
从 initUndistortRectifyMap 到重新映射都出错,最后 imshow 完全不是我所期望的。
我尝试在 python 脚本和 C++ 程序中转储 map1 和 map2(没有查看所有数据),我注意到其中一张地图的末尾(没有两者都看)结果不同。
由于我使用相同的参数调用该函数(据我所知),我希望两个程序之间的映射相等。
我做错了什么吗?喜欢弄乱类型之类的吗?
从 cv::imread 或从相机获取的帧计算图像会改变什么吗?
(只是让你知道,进行计算的帧(.jpg)是来自相机帧采集的cv::imwrite,那么我打算不再使用图像而只是工作cv::Mat 填充了相机采集的数据。)
(我知道最后枚举不一样,但即使使用 cv::BORDER_CONSTANT
我仍然有同样的问题。)
您使用了 cv::initUndistortRectifyMap
而不是 cv::fisheye::initUndistortRectifyMap
使用这段代码我得到了正确的结果:
int main()
{
cv::Mat src = cv::imread("C:/Whosebug/Input/fisheyeCalib.jpg");
cv::Size size = { src.cols, src.rows };
cv::Mat K(3, 3, cv::DataType<double>::type);
K.at<double>(0, 0) = 1307.2807020496643;
K.at<double>(0, 1) = 0.0;
K.at<double>(0, 2) = 530.3754311563506;
K.at<double>(1, 0) = 0.0;
K.at<double>(1, 1) = 1318.342691460933;
K.at<double>(1, 2) = 354.98352268131123;
K.at<double>(2, 0) = 0.0;
K.at<double>(2, 1) = 0.0;
K.at<double>(2, 2) = 1.0;
cv::Mat D(4, 1, cv::DataType<double>::type);
D.at<double>(0, 0) = -0.2994762856767568;
D.at<double>(1, 0) = 0.5036082961388784;
D.at<double>(2, 0) = -4.231072729639434;
D.at<double>(3, 0) = 3.8646397788794578;
cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);
cv::Mat map1;
cv::Mat map2;
std::cout << K << std::endl;
std::cout << D << std::endl;
std::cout << E << std::endl;
std::cout << size << std::endl;
// Here's the error:
//cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::fisheye::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
cv::Mat undistort;
cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
CV_HAL_BORDER_CONSTANT);
cv::imwrite("C:/Whosebug/Input/fisheyeCalib_output.jpg", undistort);
cv::imshow("undist", undistort);
cv::waitKey(0);
}