I have a computer vision algorithm on my Pi 3B+ that uses the following function, myVision()
, that takes in a frame and outputs the pixel coordinates of a certain colored dot (tuned according to the HSV range at the top of the function). The function is contained within a processor class that contains the attribute frame
, and so myVision()
accesses the current frame in the object.
The problem is, myVision()
is incredibly slow despite doing all we can to optimize it - profiling the code and timing each line, performing a medianBlur instead of GaussianBlur, etc, but the function usually takes 2-4 seconds to complete, with medianBlur() usually taking the longest (~2 sec). The other openCV functions each take around 20-70ms. The code takes ~10ms to run on a somewhat old laptop with 4GB of RAM. We also upped the GPU capacity of the Pi to 256 (the max), and that didn't seem to do much. We have the camera IO relegated to its own separate thread, and tried to create a thread dedicated to processing frames, but that ran into syncronization issues and didn't seem to speed things up.
Any ideas for how we can speed up the algorithm?
def myVision(self):
t0=time.time()
h_min = 150
h_max = 179
s_min = 100
s_max = 255
v_min = 32
v_max = 255
lower = np.array([h_min,s_min,v_min])
upper = np.array([h_max,s_max,v_max])
blurred = cv2.medianBlur(self.frame,5) # blurs the image to remove noise
hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV) # Converts BGR to HSV
mask = cv2.inRange(hsv, lower, upper) # defines the masks color Range
mask = cv2.erode(mask, None, iterations=2) # erode/dilate filters out colors not in range
mask = cv2.dilate(mask, None, iterations=2)
cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # find countours
cnts = imutils.grab_contours(cnts) # grab contours
center = None
# If a countour is found...
x0=999 # set to junk in case no contours found
y0=999
r0=999
if len(cnts) > 0:
c = max(cnts, key=cv2.contourArea) # finds contour with largest area
((x0, y0), r0) = cv2.minEnclosingCircle(c) # draw a circle around it
print(f'process time: {time.time()-t0}')
return x0,y0,r0