|
|
|
@ -17,6 +17,7 @@ from utils import (
|
|
|
|
|
box_distance, |
|
|
|
|
get_heading, |
|
|
|
|
get_avg_heading, |
|
|
|
|
OBJ_LEAVING_COND, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
pp = pprint.PrettyPrinter(indent=2) |
|
|
|
@ -53,7 +54,7 @@ args = vars(ap.parse_args())
|
|
|
|
|
|
|
|
|
|
# load the COCO class labels our YOLO model was trained on |
|
|
|
|
# labelsPath = os.path.sep.join([args["yolo"], "coco.names"]) |
|
|
|
|
labelsPath = "/Users/sipp11/syncthing/dropbox/tracking-obj/mytrain.names" |
|
|
|
|
labelsPath = "../../syncthing/dropbox/tracking-obj/mytrain.names" |
|
|
|
|
LABELS = open(labelsPath).read().strip().split("\n") |
|
|
|
|
# 0 person, 1 wheelchair, 2 bicycle, 3 motorbike, 4 car, 5 bus, 6 truck |
|
|
|
|
|
|
|
|
@ -62,8 +63,8 @@ np.random.seed(42)
|
|
|
|
|
COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8") |
|
|
|
|
|
|
|
|
|
# derive the paths to the YOLO weights and model configuration |
|
|
|
|
weightsPath = "/Users/sipp11/syncthing/dropbox/tracking-obj/mytrain_final.weights" |
|
|
|
|
configPath = "/Users/sipp11/syncthing/dropbox/tracking-obj/mytrain.cfg" |
|
|
|
|
weightsPath = "../../syncthing/dropbox/tracking-obj/mytrain_final.weights" |
|
|
|
|
configPath = "../../syncthing/dropbox/tracking-obj/mytrain.cfg" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# load our YOLO object detector trained on COCO dataset (80 classes) |
|
|
|
@ -74,11 +75,11 @@ ln = net.getLayerNames()
|
|
|
|
|
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def detect_stuffs(frame): |
|
|
|
|
def detect_stuffs(_frame): |
|
|
|
|
# construct a blob from the input frame and then perform a forward |
|
|
|
|
# pass of the YOLO object detector, giving us our bounding boxes |
|
|
|
|
# and associated probabilities |
|
|
|
|
blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=True, crop=False) |
|
|
|
|
blob = cv2.dnn.blobFromImage(_frame, 1 / 255.0, (416, 416), swapRB=True, crop=False) |
|
|
|
|
net.setInput(blob) |
|
|
|
|
start = time.time() |
|
|
|
|
layerOutputs = net.forward(ln) |
|
|
|
@ -135,21 +136,6 @@ def detect_stuffs(frame):
|
|
|
|
|
if len(idxs) == 0: |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
# NOTE: we are not going to draw anything from DETECTION, |
|
|
|
|
# only from tracking one |
|
|
|
|
# loop over the indexes we are keeping |
|
|
|
|
# for i in idxs.flatten(): |
|
|
|
|
# # extract the bounding box coordinates |
|
|
|
|
# (x, y) = (boxes[i][0], boxes[i][1]) |
|
|
|
|
# (w, h) = (boxes[i][2], boxes[i][3]) |
|
|
|
|
|
|
|
|
|
# # draw a bounding box rectangle and label on the frame |
|
|
|
|
# color = [int(c) for c in COLORS[classIDs[i]]] |
|
|
|
|
# cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) |
|
|
|
|
# text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i]) |
|
|
|
|
# cv2.putText( |
|
|
|
|
# frame, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2 |
|
|
|
|
# ) |
|
|
|
|
return idxs, boxes, confidences, classIDs, start, end |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -196,15 +182,17 @@ while True:
|
|
|
|
|
# grab the updated bounding box coordinates (if any) for each |
|
|
|
|
# object that is being tracked |
|
|
|
|
(success, boxes) = cv_trackers.update(frame) |
|
|
|
|
print("success", success) |
|
|
|
|
print("boxes", boxes) |
|
|
|
|
# print("success", success) |
|
|
|
|
# print("boxes", boxes) |
|
|
|
|
|
|
|
|
|
untracking = [] |
|
|
|
|
# loop over the bounding boxes and draw then on the frame |
|
|
|
|
if success: |
|
|
|
|
obj_cnt = len(boxes) |
|
|
|
|
print(f"obj_cnt: ", obj_cnt, boxes) |
|
|
|
|
# print(f"obj_cnt: ", obj_cnt, ' | tracker #', len(trackers)) |
|
|
|
|
for idx in range(obj_cnt): |
|
|
|
|
GONE = False |
|
|
|
|
|
|
|
|
|
box = boxes[idx] |
|
|
|
|
(x, y, w, h) = [int(v) for v in box] |
|
|
|
|
_last_pos = trackers[idx]["curr_position"] |
|
|
|
@ -212,7 +200,7 @@ while True:
|
|
|
|
|
curr_distance = box_distance(box, _last_pos) |
|
|
|
|
last_distance = trackers[idx]["distance"] |
|
|
|
|
trackers[idx]["distance"] = curr_distance |
|
|
|
|
trackers[idx]["curr_position"] = [int(v) for v in box] |
|
|
|
|
trackers[idx]["curr_position"] = box # [int(v) for v in box] |
|
|
|
|
|
|
|
|
|
_heading = get_heading(_x, _y, x, y) |
|
|
|
|
|
|
|
|
@ -225,7 +213,7 @@ while True:
|
|
|
|
|
if trackers[idx]["still"] == 0: |
|
|
|
|
trackers[idx]["heading"] = [_heading] + trackers[idx]["heading"] |
|
|
|
|
|
|
|
|
|
trackers[idx]["heading"] = trackers[idx]["heading"][:30] |
|
|
|
|
trackers[idx]["heading"] = trackers[idx]["heading"][:20] |
|
|
|
|
|
|
|
|
|
if trackers[idx]["still"] > 30 or x < 5 or x > 1250: |
|
|
|
|
untracking.append(trackers[idx]) |
|
|
|
@ -233,29 +221,63 @@ while True:
|
|
|
|
|
tk = trackers[idx] |
|
|
|
|
# check if it's hit the first |
|
|
|
|
avg_heading = get_avg_heading(trackers[idx]["heading"]) |
|
|
|
|
print(f" ---> avg heading: ", avg_heading) |
|
|
|
|
if ( |
|
|
|
|
tk["first"]["id"] == 4 |
|
|
|
|
and avg_heading == "N" |
|
|
|
|
and (x > 140 or x + w > 175) |
|
|
|
|
): |
|
|
|
|
print("gone!") |
|
|
|
|
_nid = f"id_5" |
|
|
|
|
for lvng_cnd in OBJ_LEAVING_COND: |
|
|
|
|
_origin = tk["origin"]["id"] |
|
|
|
|
cond = dict(lvng_cnd) |
|
|
|
|
if cond["origin_id"] != _origin or avg_heading != cond["heading"]: |
|
|
|
|
continue |
|
|
|
|
REACH_condition = False |
|
|
|
|
if cond["x"] != -1: |
|
|
|
|
if (cond["heading"] in "NE" and x + w > cond["x"]) or ( |
|
|
|
|
cond["heading"] in "SW" and x < cond["x"] |
|
|
|
|
): |
|
|
|
|
print("REACH condition: X", x, cond["x"]) |
|
|
|
|
REACH_condition = True |
|
|
|
|
|
|
|
|
|
elif cond["y"] != -1: |
|
|
|
|
# Don't have one yet |
|
|
|
|
if (cond["heading"] in "NE" and x + w > cond["y"]) or ( |
|
|
|
|
cond["heading"] in "SW" and x < cond["y"] |
|
|
|
|
): |
|
|
|
|
print("REACH condition: Y") |
|
|
|
|
REACH_condition = True |
|
|
|
|
if not REACH_condition: |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
# print("MATCH COND") |
|
|
|
|
# pp.pprint(cond) |
|
|
|
|
# TODO: should be a loop here if next has > 1 |
|
|
|
|
_nid = f"id_{cond['next_area'][0]}" |
|
|
|
|
print(f"#{tk['id']} origin:#{_origin} to#{_nid}", end="") |
|
|
|
|
if _nid not in W4A: |
|
|
|
|
print(f">>add AREA {_nid} to W4A", end="") |
|
|
|
|
W4A[_nid] = {"objects": []} |
|
|
|
|
_expected_frame = 30 * 4 # at least 4 sec later |
|
|
|
|
# put this object to W4A for next area if doesn't exist |
|
|
|
|
has_this = [_ for _ in W4A[_nid]["objects"] if _[0]["id"] == tk["id"]] |
|
|
|
|
if not has_this: |
|
|
|
|
GONE = True |
|
|
|
|
# unit in frame |
|
|
|
|
_expected_frame = _frame_count + cond["duration_to_next"] |
|
|
|
|
W4A[_nid]["objects"].append((tk, _frame_count, _expected_frame)) |
|
|
|
|
untracking.append(trackers[idx]) |
|
|
|
|
untracking.append(tk) |
|
|
|
|
print(f'>>GONE - W#{len(W4A[_nid]["objects"])}') |
|
|
|
|
# print(f' {_nid} objs: ') |
|
|
|
|
# pp.pprint(W4A[_nid]["objects"]) |
|
|
|
|
# print(f' {_nid} untracking: ', [_['id'] for _ in untracking]) |
|
|
|
|
|
|
|
|
|
print( |
|
|
|
|
f"[{tk['id']}-{tk['type']}] (x,y)=({x},{y})" |
|
|
|
|
f" | still #{tk['still']} | distance: " |
|
|
|
|
f"{last_distance:.3f} -> {curr_distance:.3f}" |
|
|
|
|
) |
|
|
|
|
_htxt = ",".join(trackers[idx]["heading"]) |
|
|
|
|
print(f" ------ heading: {_htxt}") |
|
|
|
|
if GONE: |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
# print( |
|
|
|
|
# f"[{tk['id']}-{tk['type']}] (x,y)=({x},{y})" |
|
|
|
|
# f" | still #{tk['still']} | distance: " |
|
|
|
|
# f"{last_distance:.3f} -> {curr_distance:.3f}", |
|
|
|
|
# end="", |
|
|
|
|
# ) |
|
|
|
|
# _htxt = ",".join(trackers[idx]["heading"]) |
|
|
|
|
# print(f" ------ heading: {_htxt}", end='') |
|
|
|
|
# print(f" ------ avg heading: {avg_heading}", end="") |
|
|
|
|
# print("") |
|
|
|
|
|
|
|
|
|
# DRAW on FRAME |
|
|
|
|
color = [int(c) for c in COLORS[0]] |
|
|
|
@ -270,6 +292,20 @@ while True:
|
|
|
|
|
2, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
# Cleanup Tracker |
|
|
|
|
if untracking: |
|
|
|
|
ut_ids = [_["id"] for _ in untracking] # untracking ids |
|
|
|
|
cv_trackers.clear() |
|
|
|
|
cv_trackers = cv2.MultiTracker_create() |
|
|
|
|
# get rid of them in trackers too |
|
|
|
|
trackers = [_ for _ in trackers if _["id"] not in ut_ids] |
|
|
|
|
# add tracker again |
|
|
|
|
for _trckr in trackers: |
|
|
|
|
__tkr = OPENCV_OBJECT_TRACKERS["csrt"]() |
|
|
|
|
cv_trackers.add(__tkr, frame, tuple(_trckr["curr_position"])) |
|
|
|
|
print(f"=== AFTER CLEANUP ---- UNTRACKING ===") |
|
|
|
|
print(f" cv #{len(cv_trackers.getObjects())} trackers #{len(trackers)}") |
|
|
|
|
|
|
|
|
|
# only detect once a sec |
|
|
|
|
if _frame_count % 15 == 1: |
|
|
|
|
idxs, boxes, confidences, classIDs, start, end = detect_stuffs(frame) |
|
|
|
@ -291,31 +327,30 @@ while True:
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
_x, _y, _w, _h = t["curr_position"] |
|
|
|
|
print(f"[{t['id']}] - {t['type']}") |
|
|
|
|
# print(f"[{t['id']}] - {t['type']}") |
|
|
|
|
is_same = is_it_the_same_obj(x, y, w, h, _x, _y, _w, _h, id=t["id"]) |
|
|
|
|
if is_same: |
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
if not is_same: |
|
|
|
|
gid = None |
|
|
|
|
if found_at["id"] == 5: |
|
|
|
|
print(f"FOUND AT 5 ON {_frame_count}") |
|
|
|
|
_po = W4A["id_5"]["objects"] |
|
|
|
|
_po = [_ for _ in _po if _frame_count > _[2]] |
|
|
|
|
_po = sorted(_po, key=lambda kk: kk[2]) |
|
|
|
|
print(' ------ ', _po) |
|
|
|
|
_area_id = f"id_{found_at['id']}" |
|
|
|
|
if _area_id in W4A: |
|
|
|
|
# check candidates which has "matched" opportunity too |
|
|
|
|
_po = W4A[_area_id]["objects"] |
|
|
|
|
_po = [_ for _ in _po if _frame_count > _[2]] # opportunity |
|
|
|
|
_po = sorted(_po, key=lambda kk: kk[2]) # first one first |
|
|
|
|
if _po: |
|
|
|
|
gid = _po[0][0]["id"] |
|
|
|
|
# remove this id out of next W4A |
|
|
|
|
W4A["id_5"]["objects"] = [ |
|
|
|
|
_ for _ in W4A["id_5"]["objects"] if _[0]["id"] == gid |
|
|
|
|
W4A[_area_id]["objects"] = [ |
|
|
|
|
_ for _ in W4A[_area_id]["objects"] if _[0]["id"] != gid |
|
|
|
|
] |
|
|
|
|
print(f" >> possibly this obj: ", _po) |
|
|
|
|
# add tracker to this obj |
|
|
|
|
# create a new object tracker for the bounding box and add it |
|
|
|
|
# to our multi-object tracker |
|
|
|
|
# tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]() |
|
|
|
|
# trackers.add(tracker, frame, box) |
|
|
|
|
print(f" --- {len(_po)} candicate: picked id={gid}") |
|
|
|
|
else: |
|
|
|
|
print(f" --- no candidate") |
|
|
|
|
|
|
|
|
|
# create tracker and add to multi-object tracker |
|
|
|
|
_tracker = OPENCV_OBJECT_TRACKERS["csrt"]() |
|
|
|
|
bbox = (x, y, w, h) |
|
|
|
|
cv_trackers.add(_tracker, frame, bbox) |
|
|
|
@ -324,7 +359,7 @@ while True:
|
|
|
|
|
"type": _class, |
|
|
|
|
"curr_position": bbox, |
|
|
|
|
"heading": [], |
|
|
|
|
"first": found_at, |
|
|
|
|
"origin": found_at, |
|
|
|
|
"distance": -1, |
|
|
|
|
"last_position": bbox, |
|
|
|
|
"still": 0, |
|
|
|
@ -332,25 +367,22 @@ while True:
|
|
|
|
|
if gid is None: |
|
|
|
|
tracker_counter += 1 |
|
|
|
|
trackers.append(t) |
|
|
|
|
print(f"trackers ADD - now total #{len(trackers)}") |
|
|
|
|
print(f"trackers ADDED - now total #{len(trackers)}") |
|
|
|
|
pp.pprint(t) |
|
|
|
|
# print(f" i -> {i} ({x},{y}), {w},{h} ({x + w},{y + h})") |
|
|
|
|
|
|
|
|
|
_what = ",".join([LABELS[c] for c in classIDs]) |
|
|
|
|
print(f"[{_frame_count:08d}] :: {_what}") |
|
|
|
|
|
|
|
|
|
# untracking |
|
|
|
|
print("untracking: ", [ut["id"] for ut in untracking]) |
|
|
|
|
# untracking_ids = [ut["id"] for ut in untracking] |
|
|
|
|
# trackers = [tk for tk in trackers if tk["id"] not in untracking_ids] |
|
|
|
|
# finished += untracking |
|
|
|
|
|
|
|
|
|
if args["live"]: |
|
|
|
|
cv2.imshow("Frame", frame) |
|
|
|
|
key = cv2.waitKey(1) & 0xFF |
|
|
|
|
|
|
|
|
|
if key == ord("w"): |
|
|
|
|
while cv2.waitKey(1) & 0xFF != ord("w"): |
|
|
|
|
pass |
|
|
|
|
# if the `q` key was pressed, break from the loop |
|
|
|
|
if key == ord("q"): |
|
|
|
|
elif key == ord("q"): |
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
if args["output"]: |
|
|
|
|