I have a program using OpenCV that counts items as they pass down a conveyor belt. The problem is that the TrackerUpdate() function is creating the bottleneck when i define success and new_bbox:
success, new_bbox = tracker.update(cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR))
Can anybody help me figure out why this is happening as well as a workaround to make the video play at normal speed?
import cv2
import numpy as np
# Intersection over Union function
def iou(boxA, boxB):
xA = max(boxA[0], boxB[0])
yA = max(boxA[1], boxB[1])
xB = min(boxA[0] + boxA[2], boxB[0] + boxB[2])
yB = min(boxA[1] + boxA[3], boxB[1] + boxB[3])
interArea = max(xB - xA, 0) * max(yB - yA, 0)
boxAArea = boxA[2] * boxA[3]
boxBArea = boxB[2] * boxB[3]
iou = interArea / float(boxAArea + boxBArea - interArea)
return iou
# Check if the contour could be a pizza
def is_potential_pizza(contour):
(x, y), radius = cv2.minEnclosingCircle(contour)
area = cv2.contourArea(contour)
circularity = (4 * np.pi * area) / (cv2.arcLength(contour, True) ** 2) if cv2.arcLength(contour, True) else 0
if 0.2 < circularity < 1.5 and area > 200: # Adjust these values as necessary
return True
return False
cap = cv2.VideoCapture("path\\video.mp4")
video_writer = cv2.VideoWriter("output.avi", cv2.VideoWriter_fourcc(*'XVID'), int(cap.get(cv2.CAP_PROP_FPS)), (int(cap.get(3)), int(cap.get(4))))
trackers = {}
next_tracker_id = 0
LINE_POINTS_BACK = [(609, 140), (627, 158)] # back line points
LINE_POINTS_FRONT = [(900, 275), (1000, 400)] # front line points
start_set=set()
end_set=set()
crossed_pizza_back = 0
crossed_pizza_front = 0
while True:
ret, image = cap.read()
if not ret:
break
# Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply a threshold to get the white areas in the image (adjust the threshold value as needed)
_, thresh = cv2.threshold(gray, 190, 255, cv2.THRESH_BINARY)
# Erosion and dilation (morphological transformations)
kernel = np.ones((3,3), np.uint8)
thresh = cv2.erode(thresh, kernel, iterations=1)
#Dilation
kernel = np.ones((3,3), np.uint8)
thresh = cv2.dilate(thresh, kernel, iterations=1)
# Apply a morphological operation to fill in the gaps
kernel = np.ones((3,3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# Apply a morphological operation to remove small holes
kernel = np.ones((3,3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
# sharpen the image
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
thresh = cv2.filter2D(thresh, -1, kernel)
# Find contours
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Process new contours for potential new trackers
for contour in contours:
if is_potential_pizza(contour):
bbox = cv2.boundingRect(contour)
# Check if the new bounding box overlaps with any existing trackers
if not any(iou(bbox, tracked_bbox[1]) > 0.2 for (_, tracked_bbox) in trackers.items()):
new_tracker = cv2.TrackerKCF.create()
new_tracker.init(cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR), bbox)
trackers[next_tracker_id] = (new_tracker, bbox)
next_tracker_id += 1
# Update the trackers
trackers_to_delete = []
for tracker_id, (tracker, _) in trackers.items():
success, new_bbox = tracker.update(cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR))
if success:
trackers[tracker_id] = (tracker, new_bbox) # Update the tracker's bbox
else:
trackers_to_delete.append(tracker_id) # Mark this tracker for deletion
# Delete trackers that failed to update
for tracker_id in trackers_to_delete:
del trackers[tracker_id]
# Draw the bounding boxes for all trackers
for tracker_id, (_, bbox) in trackers.items():
p1 = (int(bbox[0]), int(bbox[1]))
p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
center_x,center_y=(p1[0]+p2[0])//2,(p1[1]+p2[1])//2
crossed_color=0
# Check if the pizza has crossed the line
if center_x>=LINE_POINTS_BACK[1][0] and center_y>=LINE_POINTS_BACK[0][1] and center_y<=LINE_POINTS_BACK[1][1]:
end_set.add(tracker_id)
if tracker_id in start_set:
crossed_pizza_back += 1
start_set.remove(tracker_id)
crossed_color=255
elif center_x<=LINE_POINTS_BACK[1][0] and center_y>=LINE_POINTS_BACK[0][1] and center_y<=LINE_POINTS_BACK[1][1]:
start_set.add(tracker_id)
if tracker_id in end_set:
crossed_pizza_back -= 1
end_set.remove(tracker_id)
if center_x>=LINE_POINTS_FRONT[1][0] and center_y>=LINE_POINTS_FRONT[0][1] and center_y<=LINE_POINTS_FRONT[1][1]:
end_set.add(tracker_id)
if tracker_id in start_set:
crossed_pizza_front += 1
start_set.remove(tracker_id)
crossed_color=255
elif center_x<=LINE_POINTS_FRONT[1][0] and center_y>=LINE_POINTS_FRONT[0][1] and center_y<=LINE_POINTS_FRONT[1][1]:
start_set.add(tracker_id)
if tracker_id in end_set:
crossed_pizza_front -= 1
end_set.remove(tracker_id)
cv2.rectangle(image, p1, p2, (0, crossed_color, 0), 2, 1)
cv2.putText(image, str(tracker_id), (center_x,center_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (crossed_color, 0, 1), 2)
# Displaying pizza counts for front & back line
cv2.line(image, LINE_POINTS_BACK[0], LINE_POINTS_BACK[1], (0, 255, 0), 2)
cv2.line(image, LINE_POINTS_FRONT[0], LINE_POINTS_FRONT[1], (0, 255, 0), 2)
cv2.putText(image, f"Back Line Pizza Count: {crossed_pizza_back}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
cv2.putText(image, f"Front Line Pizza Count: {crossed_pizza_front}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
cv2.imshow("Detected Pizzas", image)
cv2.imshow("Detected Pizzas 2", thresh)
video_writer.write(image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
cap.release()
video_writer.release()