CV2 仅在遮罩区域绘制椭圆

Yag*_*gel 0 python opencv numpy image-processing

我试图在足球场上的球员下方画一个圆圈,类似于:

在此输入图像描述

如果我只是绕着玩家的脚转一圈,看起来会很糟糕:

在此输入图像描述

我试图仅在场的绿色部分上绘制圆圈(以使其更具 3D 效果)。

首先,我使用以下代码仅掩盖了字段上的绿色部分:

def mask(img):
    ## convert to hsv
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    ## mask of green (36,25,25) ~ (86, 255,255)
    lower = (36, 25, 25)
    upper = (86, 255, 255)
    mask = cv2.inRange(hsv, lower, upper)
    ## slice the green
    imask = mask == 0
    green = np.zeros_like(img, np.uint8)
    green[imask] = img[imask]
    img = green
    return img
Run Code Online (Sandbox Code Playgroud)

这给出了以下结果:

在此输入图像描述

如何仅在绿色(遮罩后 - 黑色)部分绘制椭圆?

PS这是完整的代码:

import cv2
import numpy as np


def mask(img):
    ## convert to hsv
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    ## mask of green (36,25,25) ~ (86, 255,255)
    lower = (36, 25, 25)
    upper = (86, 255, 255)
    mask = cv2.inRange(hsv, lower, upper)
    ## slice the green
    imask = mask == 0
    green = np.zeros_like(img, np.uint8)
    # green.fill(255)
    green[imask] = img[imask]
    img = green
    return img


def player_ellipse(img, player_point):
    axesLength = (45, 20)
    angle = 0
    startAngle = 0
    endAngle = 360
    # Red color in BGR
    color = (0, 0, 255)
    # Line thickness of 5 px
    thickness = 5
    img = cv2.ellipse(img, player_point, axesLength, angle, startAngle, endAngle, color, thickness)
    return img


def main():
    img = cv2.imread('img.png')
    point = (160, 665)

    img = player_ellipse(img, point)
    img = mask(img)

    cv2.imshow("img", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


main()
Run Code Online (Sandbox Code Playgroud)

这是没有任何编辑的播放器: cccccccc

小智 5

你快到了。剩下要做的就是使用MickaChristoph Rackwitz在评论中回答的所建立的蒙版从原始图像(没有椭圆)复制像素。

您可以选择应用一些形态学操作来使蒙版更具吸引力。

所以步骤是:

  1. 画一个椭圆: 在此输入图像描述
  2. 使用绿色提取蒙版: 在此输入图像描述
  3. [可选]应用蒙版腐蚀: 在此输入图像描述
  4. 使用蒙版从原始图像复制像素:

img_with_ellipse[green_mask] = img[green_mask]

在此输入图像描述

完整示例:

import cv2
import numpy as np


def mask(img):
    ## convert to hsv
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    ## mask of green (36,25,25) ~ (86, 255,255)
    lower = (36, 25, 25)
    upper = (86, 255, 255)
    mask = cv2.inRange(hsv, lower, upper)
    mask = cv2.erode(mask, np.ones((3, 3), np.uint8), iterations=5) == 0
    return mask


def player_ellipse(img, player_point):
    axesLength = (45, 20)
    angle = 0
    startAngle = 0
    endAngle = 360
    # Red color in BGR
    color = (0, 0, 255)
    # Line thickness of 5 px
    thickness = 5
    img = cv2.ellipse(
        img.copy(),
        player_point,
        axesLength,
        angle,
        startAngle,
        endAngle,
        color,
        thickness,
    )
    return img


def main():
    img = cv2.imread("img.png")
    point = (160, 665)

    green_mask = mask(img)

    img_with_ellipse = player_ellipse(img, point)
    img_with_ellipse[green_mask] = img[green_mask]

    cv2.imshow("img", img_with_ellipse)
    cv2.waitKey(0)


main()
Run Code Online (Sandbox Code Playgroud)