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)