I want to detect the contour of a ball and the object will always be a ball, but i have an object in the middle that can obstruct part of the ball, here’s my current situation :
enter image description here
I made it so it works just fine in this case where theres a good amount of the ball on both sides, but when it reduces its not as good:
enter image description here
I know I can change the parameters of my code where I just concatenate both parts when they are of a good enough size, but it gets very situational when it works because of the noise, so I can’t reduce the parameters that much:
import cv2
import numpy as np
from pyfirmata2 import Arduino, SERVO
import time
import serial
# Camera Connection/Setup
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read()
hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#Blue color
low_blue = np.array([100, 100, 20])
high_blue = np.array([200, 255, 255])
blue_mask = cv2.inRange(hsv_frame, low_blue, high_blue)
#blue_mask = cv2.GaussianBlur(blue_mask,(5,5),0)
contours, hierarchy = cv2.findContours(blue_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=lambda x:cv2.contourArea(x), reverse=True)
sum = 0
emptymask = []
for cnt in contours:
if cv2.contourArea(cnt) > 300: #If the parts are big enough it assumes its a part of the ball
sum += cv2.contourArea(cnt)
emptymask.append(cnt)
#print(sum)
emptymask = cv2.vconcat(emptymask)
(x, y, w, h) = cv2.boundingRect(emptymask)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Frame", frame)
cv2.imshow("Mask", blue_mask)
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()
So I was thinking wether I can sort of deduce the ball based on its size of something like that, since its always the same ball.
I did do something like that in another code where if its not the size expected, it “guesses” the whole ball and makes a square there, but it became incredibly hard to calibrate:
if reference > 6000: #See if the object is cropped or not
cv2.rectangle(frame, (x, y), (x + w, y + w), (0, 255, 0), 2)
elif ((x>180 and x<230) and (y>170 and y<240) or (y<5 and x<225)): #If it is, it will calculate the rest of the area
cv2.rectangle(frame, (x+ball_diameter, y+h), (x, y+h - ball_diameter), (0, 255, 0), 2)
elif (x>230 and x<290) and (y>140 and y<170): #If it is, it will calculate the rest of the area
cv2.rectangle(frame, (x+w, y+ball_diameter), (x+w - ball_diameter, y), (0, 255, 0), 2)
elif (x>270 and x<300 and (y<140 or y>230)) or (y>220 and y<250) or (y<5 and x>225): #If it is, it will calculate the rest of the area
cv2.rectangle(frame, (x+w, y+h), (x+w - ball_diameter, y+h - ball_diameter), (0, 255, 0), 2)
else:
cv2.rectangle(frame, (x, y), (x + ball_diameter, y + ball_diameter), (0, 255, 0), 2)
Finally, my question is : I know theres a function that searches for a circle object, so is there a way to detect the arch from either side and just fill the missing circle gap ? Or an even better way ?
Klaidon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.