0

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).

0 Answers0