打开 CV Python- 图像扭曲径向和透视-
Open CV Python- Image distortion radial and perspective-
我有一张扭曲的图片,在没有扭曲的情况下,点 A、B、C、D 形成一个 1 厘米 * 1 厘米的正方形。
我尝试使用单应性来校正它,但它扭曲了 AD 和 BC 线,如图所示。
你知道我该如何纠正吗?
非常感谢!
Marie- 编码初学者
PS:供参考,该图像是在管子中拍摄的,内窥镜相机具有大视野,几乎可以拍摄相机周围的管子。我将使用 1*1 平方厘米的正方形来估计根的生长情况,并随时间拍摄几张照片。
这是我的代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__' :
# Read source image.
im_src = cv2.imread('points2.jpg', cv2.IMREAD_COLOR)
# Four points of the miniR image
pts_src = np.array([[742,223],[806,255],[818,507],[753,517]], dtype=float)
# Read destination image.
im_dst = cv2.imread('rectangle.jpg', cv2.IMREAD_COLOR)
# Four points of the square
pts_dst = np.array([[200,200],[1000,200],[1000,1000],[200,1000]], dtype=float)
# Calculate Homography
h, status = cv2.findHomography(pts_src, pts_dst)
# Warp source image to destination based on homography
im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))
cv2.imwrite('corrected2.jpg', im_out)
# Display images
cv2.imshow("Source Image", im_src)
cv2.imshow("Destination Image", im_dst)
cv2.imshow("Warped Source Image", im_out)
cv2.waitKey(0)
单应性是一种投影变换。因此它只能将直线映射到直线。输入曲线四边形的直边已正确校正,但无法使用投影变换拉直弯曲边。
在您发布的照片中,可以合理地假设整体几何形状大致是一个圆柱体,并且 "vertical" 线平行于圆柱体的轴。所以它们大致是直的,投影变换(相机投影)会将它们映射为直线。 "horizontal" 行是圆的图像,如果圆柱体被压扁,则为椭圆。投影变换会将椭圆(特别是圆)映射为椭圆。所以你可以通过拟合椭圆来继续。有关提示,请参阅 this other answer。
我找到了一个使用 GDAL 的解决方案。我们可以使用两个棋盘图像。一张图像是用产生失真的设备成像的,并保持不变——因此没有失真。在 QGIS 的帮助下,您可以创建一个文件,将扭曲点与未扭曲点相关联。为此,您使用定义的网格间隔(例如 100 像素)在每个交叉点添加一个地面控制点,并将生成的 GCP 导出为 pointsfile.points
.
之后,您可以使用协作者创建的批处理文件 here。它正在使用 GDAL 对图像进行地理校正。
你只需要将你想要转换的图片(jpg格式)放到repo的根目录和运行 bash warp.sh。这会将重新转换后的图像输出到 out/ 目录中。
我有一张扭曲的图片,在没有扭曲的情况下,点 A、B、C、D 形成一个 1 厘米 * 1 厘米的正方形。
我尝试使用单应性来校正它,但它扭曲了 AD 和 BC 线,如图所示。
你知道我该如何纠正吗?
非常感谢!
Marie- 编码初学者
PS:供参考,该图像是在管子中拍摄的,内窥镜相机具有大视野,几乎可以拍摄相机周围的管子。我将使用 1*1 平方厘米的正方形来估计根的生长情况,并随时间拍摄几张照片。
这是我的代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__' :
# Read source image.
im_src = cv2.imread('points2.jpg', cv2.IMREAD_COLOR)
# Four points of the miniR image
pts_src = np.array([[742,223],[806,255],[818,507],[753,517]], dtype=float)
# Read destination image.
im_dst = cv2.imread('rectangle.jpg', cv2.IMREAD_COLOR)
# Four points of the square
pts_dst = np.array([[200,200],[1000,200],[1000,1000],[200,1000]], dtype=float)
# Calculate Homography
h, status = cv2.findHomography(pts_src, pts_dst)
# Warp source image to destination based on homography
im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))
cv2.imwrite('corrected2.jpg', im_out)
# Display images
cv2.imshow("Source Image", im_src)
cv2.imshow("Destination Image", im_dst)
cv2.imshow("Warped Source Image", im_out)
cv2.waitKey(0)
单应性是一种投影变换。因此它只能将直线映射到直线。输入曲线四边形的直边已正确校正,但无法使用投影变换拉直弯曲边。
在您发布的照片中,可以合理地假设整体几何形状大致是一个圆柱体,并且 "vertical" 线平行于圆柱体的轴。所以它们大致是直的,投影变换(相机投影)会将它们映射为直线。 "horizontal" 行是圆的图像,如果圆柱体被压扁,则为椭圆。投影变换会将椭圆(特别是圆)映射为椭圆。所以你可以通过拟合椭圆来继续。有关提示,请参阅 this other answer。
我找到了一个使用 GDAL 的解决方案。我们可以使用两个棋盘图像。一张图像是用产生失真的设备成像的,并保持不变——因此没有失真。在 QGIS 的帮助下,您可以创建一个文件,将扭曲点与未扭曲点相关联。为此,您使用定义的网格间隔(例如 100 像素)在每个交叉点添加一个地面控制点,并将生成的 GCP 导出为 pointsfile.points
.
之后,您可以使用协作者创建的批处理文件 here。它正在使用 GDAL 对图像进行地理校正。
你只需要将你想要转换的图片(jpg格式)放到repo的根目录和运行 bash warp.sh。这会将重新转换后的图像输出到 out/ 目录中。