我正在尝试识别足球场的中场椭圆。我尝试过在网上找到的不同解决方案,例如霍夫变换和模板匹配,但不幸的是我无法使它们起作用。 图片取自真实的足球比赛,因此有不同的镜头和方向。
目前,我获得了最好的结果,过滤掉音高之外的像素(使用颜色掩模)并使用一些变换,如高斯模糊、Canny,以及边缘轮廓和openCV中的fitEllipse()等技术 .
这里我执行了边缘轮廓并使用aspect_ratio过滤掉不相关的边缘:
contours, _ = cv2.findContours(canny_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
min_aspect_ratio = 3 # Minimum aspect ratio threshold (adjust as needed)
max_aspect_ratio = 50 # Maximum aspect ratio threshold (adjust as needed)
# Create a copy of the original image to draw bounding rectangles
image_with_rectangles = image.copy()
# Iterate through the contours
for contour in contours:
# Calculate the aspect ratio of the bounding rectangle
x, y, w, h = cv2.boundingRect(contour)
aspect_ratio = float(w) / h
# Check if the aspect ratio falls within the specified range
if min_aspect_ratio < aspect_ratio < max_aspect_ratio:
# Draw a green bounding rectangle around the contour
cv2.rectangle(image_with_rectangles, (x, y), (x + w, y + h), (255, 255, 0), 2)
# Display the image with the bounding rectangles
print("Image with Bounding Rectangles")
cv2_imshow(image_with_rectangles)
filtered_contours = [
cnt for cnt in contours
if min_aspect_ratio < (float(cv2.boundingRect(cnt)[2]) / cv2.boundingRect(cnt)[3]) < max_aspect_ratio
]
result_image = np.zeros_like(original_image) # Create a blank canvas
cv2.drawContours(result_image, filtered_contours, -1, (0, 255, 0), 2) # Draw the filtered contours in green
# Display or save the result_image as needed
cv2_imshow(result_image)
最后一步包括尝试拟合椭圆,我遇到了很多问题以使 cv2.fitEllipse() 起作用,这是我的解决方案:
gray_image = cv2.cvtColor(result_image, cv2.COLOR_BGR2GRAY)
cv2_imshow(gray_image)
# find the contours
contours,hierarchy = cv2.findContours(gray_image, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print("\nNumber of contours detected:", len(contours))
ellipse_image = original_image.copy()
ellipses = []
orientations = []
for c in filtered_contours:
#if it contains at least 5 points (higher the value lower the number of ellipses)
if len(c) >= 10:
print(len(c))
ellipse = cv2.fitEllipse(c)
# Get the major and minor axes of the ellipse
major_axis, minor_axis = ellipse[1]
# Calculate the aspect ratio of the ellipse
aspect_ratio = major_axis / minor_axis
#we want a high aspect ratio, meaning that is much wider then taller
if 0.1 <= aspect_ratio <= 0.2:
print("\nRatio: ", aspect_ratio)
print("M and m axes: ", major_axis, minor_axis)
if major_axis < minor_axis:
ellipses.append(ellipse)
orientations.append(int(ellipse[2]))
for e in ellipses:
cv2.ellipse(ellipse_image, e, (255, 255, 0), 2)
print("\nMiddlefield contour:")
cv2_imshow(ellipse_image)
如何只保留一个椭圆(正确的椭圆)?
我所做的是用形态算子闭合椭圆。并选择最大的椭圆(面积最大)。
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread('K8hNf.png',0)
kernel_square = cv.getStructuringElement(cv.MORPH_ELLIPSE,(50,50))
img = cv.morphologyEx(img,cv.MORPH_CLOSE,kernel_square,iterations=1)
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
img = cv.cvtColor(img,cv.COLOR_GRAY2RGB)
cv2.contourArea
。largest_ellipse = None
max_area = 0
for contour in contours:
if len(contour) >= 5:
ellipse = cv.fitEllipse(contour)
area = ellipse[1][0] * ellipse[1][1] * np.pi # Calculate the area of the fitted ellipse
if area > max_area:
max_area = area
largest_ellipse = ellipse
if largest_ellipse is not None:
cv.ellipse(img, largest_ellipse, (0,255,0),2)
else:
print('No ellipses found')
plt.imshow(img,cmap='gray')
通过删除图像顶部不需要的线条并删除玩家骨骼,您可以改善椭圆的拟合。
由于相机角度失真,贴合可能永远不会完美。