我想改变这个足球场的形象

Soccer Field w/o Black Lines

以鸟瞰视图,最初try 仅使用warpPerspective(python中的OpenCV),但结果是

warpPerspective image attempt

这表明原始图像中存在失真.

我已经研究了消除图像失真的方法,但据我目前所知,我需要进行相机校准.这里的问题是,我没有任何关于用于记录足球场画面的相机属性的信息(这是唯一一个使相机校准困难的Angular ).

我正在寻找关于如何在不知道相机属性的情况下,不失真图像以获得完美的鸟瞰视野的任何建议.我也非常感谢您提供我可以学习的任何后续步骤或资源.

这是迄今为止我在Python中使用的代码:

import cv2 as cv
import numpy as np

img = cv.imread("/Users/laulpee/Desktop/python/Screen Shot 2022-05-20 at 2.44.15 AM.png")
print(img.shape)

# Field Size 60' x 90'
h = 900
w = 1200


# 4 Points on Original Image
pt1 = np.float32([[2125,382],[1441,502],[3236,773],[3252,530]])

# 4 Corresponding Points of Desired Bird Eye View Image
pt2 = np.float32([[0,0],[0,h],[w,h],[w,0]])


matrix = cv.getPerspectiveTransform(pt1, pt2)
output = cv.warpPerspective(img,matrix,(w,h))

for i in range(0,4):
    cv.circle(img,(int(pt1[i][0]),int(pt1[i][1])),5,(0,0,255),cv.FILLED)

window1 = cv.namedWindow("w1")
cv.imshow(window1,img)
cv.waitKey(0)
cv.destroyWindow(window1)


window2 = cv.namedWindow("w2")
cv.imshow(window2,output)
cv.waitKey(0)
cv.destroyWindow(window2)

推荐答案

通常,您需要"校准"相机.这意味着要估计lens distortion个系数,光心,焦距,甚至剪切系数.所有这一切都取决于摄像头传感器和它前面的镜头(包括焦距和变焦).这通常是通过校准模式完成的.

为了代替正确的校准,您可以假定一些默认值.

im = cv.imread("L91xP.jpg")
(height, width) = im.shape[:2]
assert (width, height) == (1280, 720), "or whatever else"

K = np.eye(3)
K[0,0] = K[1,1] = 1000 # 500-5000 is common
K[0:2, 2] = (width-1)/2, (height-1)/2
# array([[1000. ,    0. ,  639.5],
#        [   0. , 1000. ,  359.5],
#        [   0. ,    0. ,    1. ]])

中心在中心,焦距是一些中等值.这里错误的焦距只会影响失真系数,并且是一个因素.

可以假设失真系数都为0.你可以调整它们,看看会发生什么.

dc = np.float32([-0.54,  0.28,  0.  ,  0.  ,  0.  ]) # k1, k2, p1, p2, k3

不失真...可以应用于整个图片或单个点.

要点:

  • 要么是cv.undistortImagePoints(impts, K, dc)(新的API,因为undistortPoints做的比一些人需要的多)
  • cv.perspectiveTransform(cv.undistortPoints(impts, K, dc), K)(perspectiveTransform撤销undistortPoints的部分工作)

图像:

  • im_undistorted = cv.undistort(im, K, dc)

现在你有image and points个镜头没有失真.

modelpts = np.float32([
    [45.,  0.],
    [90.,  0.],
    [90., 60.],
    [45., 60.]]) * 15 # 15 pixels per foot

impts = [
 [511.54881, 184.64497],
 [758.16124, 141.19525],
 [1159.37185, 191.21864],
 [1153.4168, 276.2696]
]

impts_undist = np.float32([
    [ 508.38733,  180.3246 ],
    [ 762.08234,  133.98148],
    [1271.5339 ,  154.91203],
    [1250.6611 ,  260.52057]]).reshape((-1, 1, 2))

透视变换至少需要四对点.在每一对中,一个点在一个透视图(字段的一侧)中定义,另一个点在另一个透视图(自顶向下/"模型")中定义.

H = cv.getPerspectiveTransform(impts_undist, modelpts)

您可以将更多变换链接到该单应性(H),如在任一图像空间中进行平移/zoom ,以将图片移动到您想要的位置.那只是矩阵乘法.

# add some in the X and Y dimension
Tscale = np.array([
    [  1.,   0.,  75.], # arbitrary values
    [  0.,   1.,  25.],
    [  0.,   0.,   1.]])

然后将单应性应用于未失真的输入图像:

topdown = cv.warpPerspective(im_undistorted, H, dsize=(90*15, 60*15))

这些都是构成要素.然后,您可以使用createTrackbar构建一些交互式的东西来处理失真系数,直到输出看起来很直.

不要期望它变得完美.除了畸变系数外,光学中心可能并不是它应该位于的位置.侧视图上拾取的点可能会偏离一个像素左右,但在如此浅的Angular 和穿过场的距离下,这会转化为几英尺.

最好得到一个校准模式并挥动它(好吧……保持静止!)在摄像机前面.我推荐"ChArUco"牌.它们最容易产生可用的结果,因为对于这些结果,您不需要查看整个电路板.

以下是一些图片:

  • 按您给定的方式输入...

  • undistorted: enter image description here

  • top-down view: topdown (to get some more of the surroundings, multiply some translation in front of the homography like H2 = T @ H to move that to the bottom right a little, and give warpPerspective a larger dsize)

Python相关问答推荐

创建带有二维码的Flask应用程序,可重定向到特定端点

在Python中管理多个OpenGVBO和VAO实例

如何在Python中使用ijson解析SON期间检索文件位置?

如何使用矩阵在sklearn中同时对每个列执行matthews_corrcoef?

使用SciPy进行曲线匹配未能给出正确的匹配

如何从.cgi网站刮一张表到rame?

我如何使法国在 map 中完全透明的代码?

为一个组的每个子组绘制,

如何使Matplotlib标题以图形为中心,而图例框则以图形为中心

调用decorator返回原始函数的输出

让函数调用方程

Django admin Csrf令牌未设置

如何在Python中使用另一个数据框更改列值(列表)

在Python中使用if else或使用regex将二进制数据如111转换为001""

提高算法效率的策略?

为什么我的sundaram筛这么低效

使用__json__的 pyramid 在客户端返回意外格式

Python pint将1/华氏度转换为1/摄氏度°°

如何过滤组s最大和最小行使用`transform`'

如何将返回引用的函数与pybind11绑定?