OpenCV:如何仅在视频文件的第一帧上绘制,然后继续显示整个视频

时间:2019-05-16 20:14:43

标签: python opencv video-capture

我正在python中使用opencv库。我打开了一个现有的视频文件,并编写了一个小脚本,该脚本使我可以在视频中的任何位置绘制一个矩形。问题是:我想在视频的第一帧上绘制此矩形,然后将其留在那里为我标记一个感兴趣的区域。

我正在使用cv2.imshow(winname, frame)来显示我的视频。由于这以每秒很高的帧率运行/显示视频(并且我不想更改它,因为我的视频很长),因此当我开始绘制矩形时,已经显示了很多帧。

因为我认为这可能会有所帮助,所以这是到目前为止的代码: 导入cv2

#mouse callback function#
def draw_rectangle(event, x, y, flags, param):

    global pt1, pt2, topLeft_clicked, bottomRight_clicked

    #mouse click
    if event == cv2.EVENT_LBUTTONDOWN:
        #reset
        if topLeft_clicked and bottomRight_clicked:
            topLeft_clicked = False
            bottomRight_clicked = False
            pt1 = (0,0)
            pt2 = (0,0)
        #get coordinates of top left corner
        if not topLeft_clicked:
            pt1 = (x,y)
            topLeft_clicked = True
        #get coordinates of bottom right corner
        elif not bottomRight_clicked:
            pt2 = (x,y)
            bottomRight_clicked = True

#start actual program 

#initially we haven't drawn anything
pt1 = (0,0)
pt2 = (0,0)
topLeft_clicked = False
bottomRight_clicked = False

#capture video
cap = cv2.VideoCapture('Path to video')
cv2.namedWindow(winname='myName')
cv2.setMouseCallback('myName', draw_rectangle)

firstFrame = True
while True: 
    ret, frame = cap.read()
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    while ret and firstFrame: 
        cv2.imshow('myName', gray_frame)

        if topLeft_clicked: 
            cv2.circle(gray_frame, center=pt1, radius=5, color=(255,0,0), thickness=-1)

        if topLeft_clicked and bottomRight_clicked: 
            cv2.rectangle(gray_frame, pt1, pt2, (255,0,0), 2)
            firstFrame = False

    cv2.imshow('Estimate_Velocity', gray_frame)

    if cv2.waitKey(1) &0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

2 个答案:

答案 0 :(得分:0)

我还没有测试过,但是您可以修改while循环中断条件:

if cv2.waitKey(1) &0xFF == ord('q'):
          break

if (topLeft_clicked and bottomRight_clicked):
    if cv2.waitKey(1)  &0xFF == ord('q'):
        break
else:
     # change 1 to 0
     cv2.waitKey(0)

绘制方框后,您需要按一个键。

答案 1 :(得分:0)

我做了一些实验,发现了以下解决问题的方法:

import cv2

#mouse callback function#
def draw_rectangle(event, x, y, flags, param):

    global pt1, pt2, topLeft_clicked, bottomRight_clicked

    #mouse click
    if event == cv2.EVENT_LBUTTONDOWN:
        #reset
        if topLeft_clicked and bottomRight_clicked:
            topLeft_clicked = False
            bottomRight_clicked = False
            pt1 = (0,0)
            pt2 = (0,0)
        #get coordinates of top left corner
        if not topLeft_clicked:
            pt1 = (x,y)
            topLeft_clicked = True
        #get coordinates of bottom right corner
        elif not bottomRight_clicked:
            pt2 = (x,y)
            bottomRight_clicked = True

#start actual program 

#initially we haven't drawn anything
pt1 = (0,0)
pt2 = (0,0)
topLeft_clicked = False
bottomRight_clicked = False

#capture video
cap = cv2.VideoCapture('Video path')
cv2.namedWindow(winname='myName')
cv2.setMouseCallback('myName', draw_rectangle)

firstFrame = True
while True: 
    ret, frame = cap.read()
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    while firstFrame: 
        cv2.imshow('myName', gray_frame)

        if topLeft_clicked: 
            cv2.circle(gray_frame, center=pt1, radius=5, color=(255,0,0), thickness=-1)

        if topLeft_clicked and bottomRight_clicked: 
            cv2.rectangle(gray_frame, pt1, pt2, (255,0,0), 2)

        if cv2.waitKey(1) &0xFF == ord('c'):
            firstFrame = False
            break

    if topLeft_clicked and bottomRight_clicked: 
        cv2.rectangle(gray_frame, pt1, pt2, (255,0,0), 2)

    cv2.imshow('myName', gray_frame)

    if cv2.waitKey(1) &0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()