尝试使用 opencv 和 tkinter 录制视频时获取 6kb avi 文件
getting a 6kb avi file while trying to record video with opencv and tkinter
我有一个多 frame/pages Tkinter 应用程序,在一个 page/frame 我有一个相机框架,当我导航到该页面时,它会启动相机和星星捕捉,现在我想录制该视频,但是当我试图记录它时,我得到一个 6kb 的 ```avi`` 文件,它根本无法工作并且似乎已损坏。
我的代码
class FrontCameraPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.label = tk.Label(self, text="FRONT CAMERA", font=MediumFont, bg="white").grid(row=0, column=0, columnspan=2, sticky="nsew")
self.cameraFrame = tk.Frame(self, bg=gray)
self.cameraFrame.grid(row=1, column=0, sticky="nsew")
self.buttonFrame = tk.Frame(self, bg="white")
self.buttonFrame.grid(row=1, column=1, sticky="nsew", padx=(10, 0))
#creating buttons and frames --
self.end= tk.Button(self.buttonFrame, text="STOP", font=small_Font, bg=dark_blue, fg="White")
self.end.grid(row=2, column=0, ipadx=10, pady=(0, 5))
self.end['command'] = self.stop_capture
self.cancelButton = tk.Button(self.buttonFrame, text="Cancel", font=small_Font, bg=dark_blue, fg="white")
self.cancelButton.grid(row=3, column=0, ipadx=10)
self.cancelButton['command'] = lambda: controller.show_frame(someOtherPage)
#----------------------------------------------------------------------------------------------
# setup callbacks for switching in and out events starts and stops when I change frames
self.bind('<<SwitchIn>>', self.start_capture)
self.bind('<<SwitchOut>>', self.stop_capture)
self.capture = None # task id for the capture loop
width, height = 200, 200
self.cap = cv2.VideoCapture(0)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
self.fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
self.out = cv2.VideoWriter('output.avi', self.fourcc, 20.0, (width, height))
self.lmain = tk.Label(self.cameraFrame)
self.lmain.pack()
def start_capture(self, event=None):
if self.capture is None:
self.show_frame()
print('capture started')
def stop_capture(self, event=None):
if self.capture:
self.after_cancel(self.capture)
self.out.release()
self.capture = None
print('capture stopped')
def show_frame(self):
ret, frame = self.cap.read()
if ret:
frame = cv2.flip(frame, 1)
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
#----------------------------------------------------------------
self.out.write(cv2image)
#----------------------------------------------------------------
self.imgtk = ImageTk.PhotoImage(image=img)
self.lmain.configure(image=self.imgtk)
self.capture = self.after(10, self.show_frame)
因为self.cap.read()
返回的实际帧大小与创建视频编写器时的大小不符
您需要在调用 self.cap.set(...)
后使用 self.cap.get(...)
获取实际帧大小:
class FrontCameraPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
...
width, height = 200, 200
self.cap = cv2.VideoCapture(0)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
# get the final frame size
width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
self.out = cv2.VideoWriter('output.avi', self.fourcc, 20.0, (width, height))
...
我有一个多 frame/pages Tkinter 应用程序,在一个 page/frame 我有一个相机框架,当我导航到该页面时,它会启动相机和星星捕捉,现在我想录制该视频,但是当我试图记录它时,我得到一个 6kb 的 ```avi`` 文件,它根本无法工作并且似乎已损坏。
我的代码
class FrontCameraPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.label = tk.Label(self, text="FRONT CAMERA", font=MediumFont, bg="white").grid(row=0, column=0, columnspan=2, sticky="nsew")
self.cameraFrame = tk.Frame(self, bg=gray)
self.cameraFrame.grid(row=1, column=0, sticky="nsew")
self.buttonFrame = tk.Frame(self, bg="white")
self.buttonFrame.grid(row=1, column=1, sticky="nsew", padx=(10, 0))
#creating buttons and frames --
self.end= tk.Button(self.buttonFrame, text="STOP", font=small_Font, bg=dark_blue, fg="White")
self.end.grid(row=2, column=0, ipadx=10, pady=(0, 5))
self.end['command'] = self.stop_capture
self.cancelButton = tk.Button(self.buttonFrame, text="Cancel", font=small_Font, bg=dark_blue, fg="white")
self.cancelButton.grid(row=3, column=0, ipadx=10)
self.cancelButton['command'] = lambda: controller.show_frame(someOtherPage)
#----------------------------------------------------------------------------------------------
# setup callbacks for switching in and out events starts and stops when I change frames
self.bind('<<SwitchIn>>', self.start_capture)
self.bind('<<SwitchOut>>', self.stop_capture)
self.capture = None # task id for the capture loop
width, height = 200, 200
self.cap = cv2.VideoCapture(0)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
self.fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
self.out = cv2.VideoWriter('output.avi', self.fourcc, 20.0, (width, height))
self.lmain = tk.Label(self.cameraFrame)
self.lmain.pack()
def start_capture(self, event=None):
if self.capture is None:
self.show_frame()
print('capture started')
def stop_capture(self, event=None):
if self.capture:
self.after_cancel(self.capture)
self.out.release()
self.capture = None
print('capture stopped')
def show_frame(self):
ret, frame = self.cap.read()
if ret:
frame = cv2.flip(frame, 1)
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
#----------------------------------------------------------------
self.out.write(cv2image)
#----------------------------------------------------------------
self.imgtk = ImageTk.PhotoImage(image=img)
self.lmain.configure(image=self.imgtk)
self.capture = self.after(10, self.show_frame)
因为self.cap.read()
返回的实际帧大小与创建视频编写器时的大小不符
您需要在调用 self.cap.set(...)
后使用 self.cap.get(...)
获取实际帧大小:
class FrontCameraPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
...
width, height = 200, 200
self.cap = cv2.VideoCapture(0)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
# get the final frame size
width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
self.out = cv2.VideoWriter('output.avi', self.fourcc, 20.0, (width, height))
...