Create a polygon and save xy coordinates from video frame using OpenCV

Viewed 29

I am trying to create a script where I can 1) see each subsequent frame of a video via a keypress, and 2) draw a polygon in one of these frames, and save the x,y coordinates of the polygon.

I have managed to get 1) to work, but not 2). Basically, I cannot get it to work however I try to call the cv.SetMouseCallback() function from OpenCV and the draw_lines() function I have created. Another option is to just save the frame and then just cv.imread() to read in the image and then apply the polygon... But it would be neat if its possible to do from a video frame without having to save a .jpg of the frame. I just need some help figuring out how... Below is my code (currently it does not recognise the 'frame' input in the draw_lines() function - probably because cv.namedWindow or cv.SetMouseCallback is not in the correct place).

import os
import numpy as np
import cv2 as cv
from glob import glob

# mouse callback function
def draw_lines(event, x, y, flags, param):
    global ix,iy,sx,sy
    # if the left mouse button was clicked, record the starting
    if event == cv.EVENT_LBUTTONDOWN:

        # draw circle of 2px
        cv.circle(frame, (x, y), 3, (0, 0, 127), -1)

        if ix != -1: # if ix and iy are not first points, then draw a line
            cv.line(frame, (ix, iy), (x, y), (0, 0, 127), 2, cv.LINE_AA)
        else: # if ix and iy are first points, store as starting points
            sx, sy = x, y
        ix,iy = x, y
        
    elif event == cv.EVENT_LBUTTONDBLCLK:
        ix, iy = -1, -1 # reset ix and iy
        if flags == 33: # if alt key is pressed, create line between start and end points to create polygon
            cv.line(frame, (x, y), (sx, sy), (0, 0, 127), 2, cv.LINE_AA)
            

def play_video(vid_folder, vid_paths):
    # For each file (i.e., block) in the session
    for vid_name in vid_paths:
        
        video = cv.VideoCapture(os.path.join(vid_folder, vid_name))

        while video.isOpened():
            
            cv.namedWindow('frame', cv.WINDOW_NORMAL)
            cv.setMouseCallback('frame', draw_lines)
            
            # Read video capture
            ret, frame = video.read()
            # Display each frame
            cv.imshow("frame", frame)
            # show one frame at a time
            key = cv.waitKey(0)
            while key not in [ord('q'), ord('k')]:
                key = cv.waitKey(0)
            # Quit when 'q' is pressed
            if key == ord('q'):
                cv.imwrite(f"{vid_folder}/temp.jpg", frame)
                # Release capture object
                video.release()
                # Exit and distroy all windows
                cv.destroyAllWindows()
                break


vid_folder = "C:/Users/nyber/Documents/Videos_temp"
os.chdir("C:/Users/nyber/Documents/Videos_temp")
vid_paths = glob("*.avi")
play_video(vid_folder, vid_paths)
0 Answers
Related