I'm trying to make a circle under the player on soccer field, similar to this:
If I just do a circle around the player's feet, it looks bad:
I'm trying to draw the circle only on the green part of the field (to make it more 3D).
First I masked only the green part on the field, using the following code:
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
This gives the following result:
How can I draw the ellipse only on the green (after the masking - black) part?
P.S. This is the full code:
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()
And this is player without any editing:
CodePudding user response:
You are almost there. All that lefts to do is to copy the pixels from the original image (without ellipse) using the founded mask as answered by Micka and Christoph Rackwitz in comments.
Optionally you may apply some morphological operations to make the mask more appealing.
So the steps are:
- Draw an ellipse:
- Extract a mask using green color:
- [Optional] Apply mask erode:
- Copy pixels from original image using the mask:
img_with_ellipse[green_mask] = img[green_mask]
Complete example:
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()