0

I'm working on a computer vision project and I want to draw lines from the junction point to endpoints of the skeleton image. In my code I get the endpoints using Harris corner detector. I have attached two images as well.

The above image shows the contour with the skeleton image overlayed along with all the endpoints

enter image description here

I want to draw lines from the junction point to endpoints of the skeleton image (marked in red circles). Please any help would be appreciated. Please find the code below

import cv2
import numpy as np
import skimage.morphology
import skimage.feature

cap = cv2.VideoCapture('test1.mp4')

while True:
   ret, frame = cap.read()
   if not ret:
      break
   gray = cv2.cvtColor(frame, cv2.COLOR.BGR2GRAY)
   blur = cv2.GaussianBlur(gray, (5, 5), 0)
   _, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
   contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
   threshSkeleton = (thresh / 255).astype(np.float64)
   skeleton = skimage.morphology.skeletonize(threshSkeleton)
   skeleton = (255 * skeleton).clip(0, 255).astype(np.uint8)
   skeleton_contours, _ = cv2.findContours(skeleton, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
   
   for i in range(len(contours)):
       new_c = contours[i]
       x, y, w, h = cv2.boundingRect(new_c)
       cv2.drawContours(frame, [new_c], 0, (255, 0, 255), 1)
       cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 255), 1)
       endpoints = skimage.feature.corner_peaks(skimage.feature.corner_harris(255 - skeleton), min_distance=10)
       for i, endpoint in enumerate(endpoints):
           if x <= endpoint[1] <= x + w and y <= endpoint[0] <= y + h:
               # find the two closest endpoints to the current one
               distances = np.linalg.norm(endpoints - endpoint, axis=1)
               sorted_indices = np.argsort(distances)
               closest_indices = sorted_indices[1:3]
               # draw a circle at the current endpoint
               cv2.circle(nFrame, tuple(endpoint[::-1]), 3, (0, 0, 255), -1)
               # draw a line between the current endpoint and the two closest endpoints
               for closest_index in closest_indices:
                    closest_endpoint = endpoints[closest_index]
                    if x <= closest_endpoint[1] <= x + w and y <= closest_endpoint[0] <= y + h:
                        cv2.line(nFrame, tuple(endpoint[::-1]), tuple(closest_endpoint[::-1]), (255, 255, 0), 1)
    
    cv2.imshow("frame", frame)
    if cv2.waitkey(0) and 0xFF == ord('q'):
          break
cap.release()

The above code is what I've tried, but the lines draw are all between the closest endpoints and not between the junction point and endpoints.

  • Why not just use the skeleton lines? Why do you need to extract points and then draw lines between them? – fmw42 May 17 '23 at 01:29
  • @fmw42 I want to determine the angle between them. – user2381342 May 17 '23 at 01:34
  • "I get the endpoints using Harris corner detector" This is overkill. All you need to do is find skeleton points with a single neighbor, which is a trivial operation. Harris is far from a trivial computation. You also shouldn't be getting the contours of the skeleton, just work in the skeleton image directly. Branch points are skeleton points with more than two neighbors. Simply "walk" from each end point, going from neighbor to neighbor, until you hit either a branch point or another end point. That gives you the connectivity. Now you can draw lines between connected points. – Cris Luengo May 17 '23 at 03:36
  • @CrisLuengo I would appreciate it if you please provide an example code as I'm still learning Thank you. – user2381342 Jun 19 '23 at 04:00

0 Answers0