I made a yolo model, not relevant for this topic. It is working fine. I wanted to add the template matching for detecting arrows on detected object with yolo.
Here is my function for template matching which returns coordinates of an arrow. (NOTE: I tested it on a small (cropped) image because there might be many arrows on picture, but I am only interested on the arrows inside my firstly detected object with yolo algorithm.)
def detect_arrows(img_path, template_paths):
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
arrow_coords = []
for temp_path in template_paths:
arrow_template = cv2.imread(temp_path)
arrow_template = cv2.cvtColor(arrow_template, cv2.COLOR_BGR2RGB)
height, width, channels = arrow_template.shape
res = cv2.matchTemplate(img, arrow_template, cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc
bottom_right = (top_left[0] + width, top_left[1] + height)
arrow_coords.append((top_left, bottom_right))
return arrow_coords
When I test that function on a single image, it works perfectly. But now, when I want to add it to my yolo algorithm, it doesnt draw arrow bounding box on the correct spot.
This is my current code:
for *xyxy, conf, cls in reversed(det):
object_coordinates = [int(xyxy[0]),int(xyxy[1]),int(xyxy[2]),int(xyxy[3])]
cropobj = im0[int(xyxy[1]):int(xyxy[3]),int(xyxy[0]):int(xyxy[2])]
gray_cropobj = cv2.cvtColor(cropobj, cv2.COLOR_BGR2GRAY)
gray_cropobj = cv2.bitwise_not(gray_cropobj)
crop_file_path = os.path.join("crop",str(crop_count)+".jpg")
cv2.imwrite(crop_file_path, gray_cropobj)
crop_count = crop_count + 1
up_path = r'C:\Users\qwe\Desktop\up.jpg'
up_right_path = r'C:\Users\qwe\Desktop\up_right.jpg'
img_path = crop_file_path
arrow_coords = detect_arrows(crop_file_path, template_paths=[up_path, up_right_path])
if save_txt: # Write to file
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
line = (cls, *xywh, conf) if opt.save_conf else (cls, *xywh) # label format
with open(txt_path + '.txt', 'a') as f:
f.write(('%g ' * len(line)).rstrip() % line + '\n')
if save_img or view_img: # Add bbox to image
label = f'{names[int(cls)]} {conf:.2f}'
plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=1)
for arrow_coord in arrow_coords:
top_left, bottom_right = arrow_coord
arrow_top_left = (int(xyxy[0]) + top_left[0], int(xyxy[1]) + top_left[1])
arrow_bottom_right = (int(xyxy[0]) + bottom_right[0], int(xyxy[1]) + bottom_right[1])
cv2.rectangle(im0, arrow_top_left, arrow_bottom_right, (0, 255,255), 1, cv2.LINE_AA)
it draws inside firstly detected object, but not around the arrow, it draws on the wrong spot. I tried with scaling between the cropped picture, adding offset, printing the coordinates to debug it, but nothing seems to be working.
So, I want to detect arrows on the cropped picture and plot it on the first original image (inside of firstly detected object, its coordinates).