【问题标题】:how to start recording from click of a button in label in python如何通过单击python标签中的按钮开始录制
【发布时间】:2020-06-04 10:36:36
【问题描述】:

我想在这个标签中显示 opencv 的输出。 但在此我想通过单击开始按钮开始录制并通过停止按钮停止,如果可能的话,我想通过单击开始网络摄像头按钮启动我的网络摄像头(以前编码)。

import datetime
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk, ImageGrab
import cv2
import numpy as np
import threading
import win32api
from tkinter.filedialog import asksaveasfilename

VIDEO_SIZE = (960, 540)

cap = cv2.VideoCapture(0)

date = datetime.datetime.now()
#filename='E:/project/videos/rec_%s%s%s%s%s%s.avi' % (date.year, date.month, date.day,
                                                     #date.hour, date.minute, date.second)

fourcc = cv2.VideoWriter_fourcc(*'XVID')
frame_rate = 12

out = cv2.VideoWriter()
def change_r():
        if rec_btn['text'] == 'Start Recording':
            start_recording()

            rec_btn.config(text="Stop Recoding")
        else:
            stop_recording()

            rec_btn.config(text="Start Recording")
def change_w():
        if cap_btn['text'] == 'Open webcam':
            start_webcam()

            cap_btn.config(text="Close Webcam")
        else:
            stop_webcam(event)

            cap_btn.config(text="Open webcam")
# --- screen capture
def Cursor_pos(img,center,radius,color,thickness):
    center = tuple(map(int,center))
    rgb = [255*c for c in color[:3]] # convert to 0-255 scale for OpenCV
    alpha = color[-1]
    radius = int(radius)
    if thickness > 0:
        pad = radius + 2 + thickness
    else:
        pad = radius + 3
    roi = slice(center[1]-pad,center[1]+pad),slice(center[0]-pad,center[0]+pad)

    try:
        overlay = img[roi].copy()
        cv2.circle(img,center,radius,rgb, thickness=thickness, lineType=cv2.LINE_AA)
        opacity = alpha
        cv2.addWeighted(src1=img[roi], alpha=opacity, src2=overlay, beta=1. - opacity, gamma=0, dst=img[roi])
    except:
        logger.debug("transparent_circle would have been partially outside of img. Did not draw it.")

def recording_screen():
    global recording
    recording = True
    while recording:
        img = ImageGrab.grab()
        frame = np.array(img)
        _xs,_ys = win32api.GetCursorPos()
        #curpos = root.winfo_pointerx(), root.winfo_pointery()
        Cursor_pos(frame,(_xs,_ys),20,(255,255,0,0.5), -1)
        #cv2.circle(frame, curpos, 10, (0,255,255), 2)
        frame = cv2.resize(frame, VIDEO_SIZE)
        tkimage.paste(Image.fromarray(frame))
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        out.write(frame)

def start_recording():

    if not out.isOpened():
        filename = asksaveasfilename(initialdir = "/",title = "Save as",mode='wb',filetypes = (("Video file","*.avi"),("all files","*.*")),defaultextension=".avi")


        out.open(filename, fourcc, frame_rate, VIDEO_SIZE)
    threading.Thread(target=recording_screen, daemon=True).start()

def stop_recording():
    global recording
    recording = False
    #filename = asksaveasfilename(initialdir = "/",title = "Save as",mode='wb',filetypes = (("Video file","*.avi"),("all files","*.*")),defaultextension=".avi")



# --- webcam

webcam = None
WEBCAM_SIZE = (280, 200)

def read_frame(imgbox):
    if cap.isOpened():
        ret, frame = cap.read()
        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame, WEBCAM_SIZE)
            image = Image.fromarray(frame)
            imgbox.image.paste(image)
        webcam.after(20, read_frame, imgbox)

def stop_webcam(event):
    global webcam
    if webcam:
        webcam.destroy()
        webcam = None

def start_webcam():
    global webcam
    if webcam is None:
        webcam = tk.Toplevel()
        webcam.geometry('{}x{}+5+520'.format(WEBCAM_SIZE[0], WEBCAM_SIZE[1]))
        webcam.overrideredirect(1)
        imgbox = tk.Label(webcam)
        imgbox.pack()
        imgbox.image = ImageTk.PhotoImage(image=Image.new('RGB',WEBCAM_SIZE,(0,0,0)))
        imgbox.config(image=imgbox.image)
        webcam.bind('<F8>', stop_webcam)
        read_frame(imgbox)

# --- main

root = tk.Tk()

tkimage = ImageTk.PhotoImage(Image.new('RGB', VIDEO_SIZE, (0,0,0)))

w, h = VIDEO_SIZE
vbox = tk.Label(root, image=tkimage, width=w, height=h, bg='black')
vbox.pack()

frame = tk.Frame(root)
frame.pack()

rec_btn = ttk.Button(frame, text='Start Recording', width=20, command=change_r)
rec_btn.grid(row=0, column=0, padx=10, pady=10)

#stop_btn = ttk.Button(frame, text='stop recording', width=20, command=stop_recording, state='disabled')
#stop_btn.grid(row=0, column=1, padx=10, pady=10)

cap_btn = ttk.Button(frame, text='Open webcam', width=20, command=change_w)
cap_btn.grid(row=0, column=2, padx=10, pady=10)

root.mainloop()

out.release()
cap.release()



我想像 tkinter 的 gui 标签一样显示我的录音

新的和更新的它显示两个不同的帧,一个是 BGR,一个是 RGB(如何解决这个问题)

更新图片

【问题讨论】:

  • 寻求不同技术答案的问题被认为过于宽泛,因此我建议避免使用它。如果您想对 2 种技术做同样的事情,那么您必须发布 2 个问题

标签: python opencv user-interface tkinter


【解决方案1】:

这是一个tkinter 示例,用于将屏幕捕获到外部视频文件:

import datetime
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk, ImageGrab
import cv2
import numpy as np
import threading

VIDEO_SIZE = (960, 540)

cap = cv2.VideoCapture(0)

date = datetime.datetime.now()
filename='E:/project/videos/rec_%s%s%s%s%s%s.avi' % (date.year, date.month, date.day,
                                                     date.hour, date.minute, date.second)

fourcc = cv2.VideoWriter_fourcc(*'XVID')
frame_rate = 12

out = cv2.VideoWriter()

# --- screen capture

def recording_screen():
    global recording
    recording = True
    while recording:
        img = ImageGrab.grab()
        frame = np.array(img)
        curpos = root.winfo_pointerx(), root.winfo_pointery()
        cv2.circle(frame, curpos, 10, (0,255,255), 2)
        frame = cv2.resize(frame, VIDEO_SIZE)
        tkimage.paste(Image.fromarray(frame))
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        out.write(frame)

def start_recording():
    rec_btn.config(state='disabled')
    stop_btn.config(state='normal')
    if not out.isOpened():
        out.open(filename, fourcc, frame_rate, VIDEO_SIZE)
    threading.Thread(target=recording_screen, daemon=True).start()

def stop_recording():
    global recording
    recording = False
    rec_btn.config(state='normal')
    stop_btn.config(state='disabled')

# --- webcam

webcam = None
WEBCAM_SIZE = (280, 200)

def read_frame(imgbox):
    if cap.isOpened():
        ret, frame = cap.read()
        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame, WEBCAM_SIZE)
            image = Image.fromarray(frame)
            imgbox.image.paste(image)
        webcam.after(20, read_frame, imgbox)

def stop_webcam(event):
    global webcam
    if webcam:
        webcam.destroy()
        webcam = None

def start_webcam():
    global webcam
    if webcam is None:
        webcam = tk.Toplevel()
        webcam.geometry('{}x{}+5+520'.format(WEBCAM_SIZE[0], WEBCAM_SIZE[1]))
        webcam.overrideredirect(1)
        imgbox = tk.Label(webcam)
        imgbox.pack()
        imgbox.image = ImageTk.PhotoImage(image=Image.new('RGB',WEBCAM_SIZE,(0,0,0)))
        imgbox.config(image=imgbox.image)
        webcam.bind('q', stop_webcam)
        read_frame(imgbox)

# --- main

root = tk.Tk()

tkimage = ImageTk.PhotoImage(Image.new('RGB', VIDEO_SIZE, (0,0,0)))

w, h = VIDEO_SIZE
vbox = tk.Label(root, image=tkimage, width=w, height=h, bg='black')
vbox.pack()

frame = tk.Frame(root)
frame.pack()

rec_btn = ttk.Button(frame, text='start recording', width=20, command=start_recording)
rec_btn.grid(row=0, column=0, padx=10, pady=10)

stop_btn = ttk.Button(frame, text='stop recording', width=20, command=stop_recording, state='disabled')
stop_btn.grid(row=0, column=1, padx=10, pady=10)

cap_btn = ttk.Button(frame, text='start webcam', width=20, command=start_webcam)
cap_btn.grid(row=0, column=2, padx=10, pady=10)

root.mainloop()

out.release()
cap.release()

我还用ImageGrab.grab()截屏,winfo_pointerx()winfo_pointery()获取鼠标当前位置,因为我还没有安装pywin32pyautogui模块。

【讨论】:

  • 当我运行此代码时,网络摄像头会打开,但框架卡住并且无法捕获,顺便说一句,我不会在此捕获网络摄像头,我想捕获桌面屏幕并显示标签中的屏幕截图。我只想在单击(网络摄像头)按钮时获取网络摄像头,直到只显示桌面屏幕。我在这里要做的是创建一个带有网络摄像头功能的屏幕录像机。
  • 我想录制我的桌面屏幕,而不是我的网络摄像头。网络摄像头是我的次要目标。请看我上面的代码。它正在捕获屏幕。
  • 它正在录制屏幕,但它没有显示任何内容,它只是在窗口中出现黑屏,当我点击网络摄像头时,它会在我不想要的窗口内显示网络摄像头,我想要如图所示的网络摄像头窗口上面的问题(更新)
  • 请回复。如何通过单击网络摄像头按钮将我的网络摄像头作为小部件启动。 (你之前提供的代码)那个。
  • 你最好自己尝试一下,因为修改代码来做你想做的事情并不难。这对你有好处。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 2018-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多