去除 Python 中的枕形镜头失真

问题描述 投票:0回答:2

我有以下图片是电脑生成的

它作为光学实验的输入输入,结果如下图:

正如您所见,由于使用了镜头系统,图像具有双凹效果。

我需要能够不失真地还原图像,并与原始图像进行比较。我是图像处理的新手,遇到了两个有用的 python 包:

https://pypi.org/project/defisheye/

defisheye
对我来说使用起来非常简单(下面的脚本),但到目前为止我无法获得最佳结果。

from defisheye import Defisheye

dtype = 'linear'
format = 'fullframe'
fov = 11
pfov = 10

img = "input_distorted.jpg"
img_out = "input_distorted_corrected.jpg"

obj = Defisheye(img, dtype=dtype, format=format, fov=fov, pfov=pfov)

# To save image locally 
obj.convert(outfile=img_out)

来自 opencv:https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html 相机校准教程超出了我的知识范围。如果有人可以向我保证这是否可行,我可以开始更深入地挖掘。非常感谢任何建议。

python opencv camera-calibration fisheye
2个回答
3
投票

如果您可以使用相机简单地校准它,但如果您别无选择,最好的方法是使用软件手动进行。这里我用 GIMP 去除了镜头效果。

如果你必须务实地去做,你有两种方法。

首先: 您可以自动化 GIMP 并编写脚本来完成这件事。

第二: 在 OpenCV 中为您的相机找到最佳系数。在这里,我写了一个脚本,可以帮助您通过测试和试验找到系数。

import cv2
import numpy as np
import matplotlib.pyplot as plt

src = cv2.imread("camera.jpg")

# convert image to graysclae
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
height, width = src_gray.shape

# set camera matrix ceofs
focal_lenght_x = 1000
focal_lenght_y = 1000
optical_center_x = 500
optical_center_y = 1000

# set distortion ceofs
k1 = k2 = 0.02
p1 = p2 = 0
k3 = 0

# create camera, distortion and new camera matrix
cameraMatrix = np.array([[focal_lenght_x,0,optical_center_x],[0,focal_lenght_y,optical_center_y], [0,0,1]])
distCoeffs = np.array([[k1, k2, p1, p2, k3]])
newcameramatrix, _ = cv2.getOptimalNewCameraMatrix(
    cameraMatrix, distCoeffs, (width, height), 1, (width, height)
)

# blur image and find contours
src_blur = cv2.blur(src_gray,(13,13))
ret, thresh = cv2.threshold(src_blur, 2, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# find the biggest contour by area
c = max(contours, key = cv2.contourArea)
# reduce number of points in contour
epsilon = 0.003*cv2.arcLength(c,True)
approx = cv2.approxPolyDP(c,epsilon,True)
# draw biggest contour
cv2.drawContours(src, [approx], -1, (255,0,0), 3)

# undistor image
undistorted_image = cv2.undistort(
    src, cameraMatrix, distCoeffs, None, newcameramatrix
)

# show original image and undistorted image with contour
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
ax1.imshow(src)
ax2 = fig.add_subplot(1,2,2)
ax2.imshow(undistorted_image)
plt.show()

此代码绘制了图像中最大的轮廓,并显示了去畸变前后的图像。您必须找到最佳值才能使轮廓看起来像矩形。

只需改变焦距、光心、k1、k2、k3、p1、p2即可达到最佳效果。

当您找到最佳值时,使用它们来制作您的最终图像。

undistorted_image = cv2.undistort(
    src_gray, cameraMatrix, distCoeffs, None, newcameramatrix
)
src_blur = cv2.blur(undistorted_image,(3,3))
ret, thresh = cv2.threshold(src_blur, 70, 255, 0)
cv2.imwrite("calibrated.png", thresh)

这是我用当前系数得到的输出。


0
投票

我将做出以下假设:

  • 您可以完全控制输入图像
  • 显示图像并捕获其输出相对较快
  • 显示器中的每个“像素”只能完全打开或完全关闭
  • 您的目标是验证显示的图像是否与数据匹配

避免大量计算或镜头模型的解决方案可以通过分别校准每个输入像素和输出图像之间的关系来实现。执行此操作的过程可能如下所示:

  1. 为每个像素生成一个完全关闭的校准图像,除了被校准的像素
  2. 捕获输出图像
  3. 使用该图像确定输入像素在输出图像中的显示位置 这可以使用几种方法:
    • 找到像素的位置(输出图像中亮像素位置的平均值)
    • 在输出图像中找到输入像素出现的区域(每个校准图像中所有亮输出像素的列表,或包含它们的多边形)
    • 存储所有标定图像并根据标定图像的加法组合分解未来图像
© www.soinside.com 2019 - 2024. All rights reserved.