91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于Python+OpenCV如何制作屏幕錄制工具

發布時間:2022-01-10 01:05:05 來源:億速云 閱讀:161 作者:柒染 欄目:開發技術

這篇文章跟大家分析一下“基于Python+OpenCV如何制作屏幕錄制工具”。內容詳細易懂,對“基于Python+OpenCV如何制作屏幕錄制工具”感興趣的朋友可以跟著小編的思路慢慢深入來閱讀一下,希望閱讀后能夠對大家有所幫助。下面跟著小編一起深入學習“基于Python+OpenCV如何制作屏幕錄制工具”的知識吧。

應用平臺

  • windows 10

  • python 3.7

屏幕錄制部分

屏幕錄制可以簡單地理解為將屏幕快照以動圖的形式播放,這里我選用PIL下的ImageGrab來截取屏幕畫面,首先

pip install Pillow

之后需要將截取到的快照數組合成為視頻,使用cv2模塊

pip install opencv-python

ImageGrab類不能直接存儲為視頻,使用numpy模塊進行數組化,再通過cv2.COLOR_BGR2RGB轉換為cv2色彩通道。

pip install numpy

屏幕錄制主要代碼:

import numpy as np
from PIL import ImageGrab
import cv2

im = ImageGrab.grab()
width, high = im.size  # 獲取屏幕的寬和高
fourcc = cv2.VideoWriter_fourcc(*'I420')  # 設置視頻編碼格式
fps = 15  # 設置幀率
video = cv2.VideoWriter('test.avi', fourcc, fps, (width, high))
while True:  # 開始錄制
    im = ImageGrab.grab()
    im_cv = cv2.cvtColor(np.array(im), cv2.COLOR_BGR2RGB)
    # 圖像寫入
    video.write(im_cv)
    if xx:  # 當某某條件滿足中斷循環
        break
video.release()  # 釋放緩存,持久化視頻

測試運行可以保存屏幕快照為視頻,但操作起來不優雅,也不利于后續的操作。

封裝成類,繼承線程父類,方便使用鍵盤來控制視頻錄制的結束。

from threading import Thread

class ScreenshotVideo(Thread):

    def __init__(self):
     """初始化參數"""
        super().__init__()

詳細代碼將在文末給出。

計算視頻最優fps及使用numpy計算中間幀數組

實際操作中視頻錄制在不同電腦中會出現不一樣的幀率,導致視頻播放或快或慢,需要根據不同的電腦計算出相應的最優fps值。

def video_best_fps(self, path):
    """獲取電腦錄制視頻的最優幀率"""
    video = cv2.VideoCapture(path)  # 讀取視頻
    fps = video.get(cv2.CAP_PROP_FPS)  # 獲取當前視頻的幀率
    count = video.get(cv2.CAP_PROP_FRAME_COUNT)  # 獲取視頻幀數,即該視頻有多少幅畫面
    self.best_fps = int(fps * ((int(count) / fps) / self.spend_time))   # 計算播放時間與錄制時間對比得到最優幀率
    video.release()

再調整幀率參數進行錄制視頻就減弱了視頻播放太快或者太慢。也可以給視頻增加幀數從而延長播放時間,這里我采用一種很簡單的方法增加視頻幀,僅供參考。

from numba import jit

# 使用numpy計算相鄰兩幀圖像且更接近于后一幀的圖像
# 調用jit方法加速數組計算
@jit(nopython=True)
def average_n(x, y):
    """Numpy計算趨近值"""
    return ((x + y + y) // 3).astype(x.dtype)

該方法僅針對于設置的fps比最優fps要高時,處理后的視頻觀感,視頻還是較為急促,但是細節幀增多,所以播放時長會比未處理前的要長,略有殘影。

使用pynput監聽鍵盤按鍵

在視頻錄制中,并不知道視頻何時結束,所以用while循環包裹錄制代碼,但也不可能讓代碼無休止的運行下去,在此使用監聽鍵盤模塊來中斷錄制代碼的運行。

from pynput import keyboard  # pip install pynput

def hotkey(self):
    """熱鍵監聽"""
    with keyboard.Listener(on_press=self.on_press) as listener:
        listener.join()

def on_press(self, key):
    try:
        if key.char == 't':  # 錄屏結束,保存視頻
            self.flag = True
        elif key.char == 'k':  # 錄屏中止,刪除文件
            self.flag = True
            self.kill = True
    except Exception as e:
        print(e)

按下鍵盤“T”鍵時,結束錄制,保存視頻。“K”鍵則是停止錄制,刪除緩存文件。

如何保存MP4格式視頻

視頻編碼格式應該為('a', 'v', 'c', '1'),文件后綴為'.mp4',在錄制前先去https://github.com/cisco/openh364/releases下下載對應平臺的dll.bz2文件,將壓縮包解壓放在項目文件夾下。再運行代碼,成功會出現一行編碼說明:

OpenH264 Video Codec provided by Cisco Systems, Inc.

源碼

本文實現的源碼如下:

import time
from PIL import ImageGrab
import cv2
from pathlib import Path
import numpy as np
from numba import jit
from pynput import keyboard
from threading import Thread


@jit(nopython=True)
def average_n(x, y):
    """Numpy計算趨近值"""
    return ((x + y + y) // 3).astype(x.dtype)


class ScreenshotVideo(Thread):

    def __init__(self, width, high, path='', fps=15):
        """初始化參數"""
        super().__init__()
        self.save_file = path
        self.best_fps = fps
        self.fps = fps
        self.width = width
        self.high = high
        self.spend_time = 1
        self.flag = False
        self.kill = False
        self.video = None

    def __call__(self, path):
        """重載視頻路徑,便于類的二次調用"""
        self.save_file = Path(path)
        self.video = self.init_videowriter(self.save_file)

    @staticmethod
    def screenshot():
        """靜態方法,屏幕截圖,并轉換為np.array數組"""
        return np.array(ImageGrab.grab())

    @staticmethod
    def get_fourcc(name):
        """視頻編碼字典"""
        fourcc_maps = {'.avi': 'I420',
                       '.m4v': 'mp4v',
                       '.mp4': 'avc1',
                       '.ogv': 'THEO',
                       '.flv': 'FLV1',
                       }
        return fourcc_maps.get(name)

    def init_videowriter(self, path):
        """獲取視頻編碼并新建視頻文件"""
        if not path:
            raise Exception('視頻路徑未設置,請設置\nvideo = ScreenshotVideo(fps,width,high)\nvideo = video(video_path)')
        path = Path(path) if isinstance(path, str) else path
        fourcc = cv2.VideoWriter_fourcc(*self.get_fourcc(path.suffix))
        return cv2.VideoWriter(path.as_posix(), fourcc, self.fps, (self.width, self.high))

    def video_record_doing(self, img):
        """將BGR數組轉換為RGB數組"""
        im_cv = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.video.write(im_cv)

    def video_record_end(self):
        """錄制結束,根據條件判斷文件是否保存"""
        self.video.release()
        cv2.destroyAllWindows()
        if self.save_file and self.kill:
            Path(self.save_file).unlink()

    def video_best_fps(self, path):
        """獲取電腦錄制視頻的最優幀率"""
        video = cv2.VideoCapture(path)
        fps = video.get(cv2.CAP_PROP_FPS)
        count = video.get(cv2.CAP_PROP_FRAME_COUNT)
        self.best_fps = int(fps * ((int(count) / fps) / self.spend_time))
        video.release()

    def pre_video_record(self):
        """預錄制,以獲取最佳fps值"""
        self.video = self.init_videowriter('test.mp4')
        start_time = time.time()
        for _ in range(10):
            im = self.screenshot()
            self.video_record_doing(im)
        self.spend_time = round(time.time() - start_time, 4)
        self.video_record_end()
        time.sleep(2)
        self.video_best_fps('test.mp4')
        Path('test.mp4').unlink()

    def insert_frame_array(self, frame_list):
        """Numpy增強截圖信息"""
        fps_n = round(self.fps / self.best_fps)
        if fps_n <= 0:
            return frame_list
        times = int(np.log2(fps_n))  # 倍率
        for _ in range(times):
            frame_list2 = map(average_n, [frame_list[0]] + frame_list[:-1], frame_list)
            frame_list = [[x, y] for x, y in zip(frame_list2, frame_list)]
            frame_list = [j for i in frame_list for j in i]
        return frame_list

    def frame2video_run(self):
        """使用opencv將連續型截圖轉換為視頻"""
        self.video = self.init_videowriter(self.save_file)
        start_time = time.time()
        frame_list = []
        while True:
            frame_list.append(self.screenshot())
            if self.flag:
                break
        self.spend_time = round(time.time() - start_time, 4)
        if not self.kill:  # 視頻錄制不被終止將逐幀處理圖像
            frame_list = self.insert_frame_array(frame_list)
            for im in frame_list:
                self.video_record_doing(im)
        self.video_record_end()

    def hotkey(self):
        """熱鍵監聽"""
        with keyboard.Listener(on_press=self.on_press) as listener:
            listener.join()

    def on_press(self, key):
        try:
            if key.char == 't':  # 錄屏結束,保存視頻
                self.flag = True
            elif key.char == 'k':  # 錄屏中止,刪除文件
                self.flag = True
                self.kill = True
        except Exception as e:
            print(e)

    def run(self):
        # 運行函數
        # 設置守護線程
        Thread(target=self.hotkey, daemon=True).start()
        # 運行截圖函數
        self.frame2video_run()


screen = ImageGrab.grab()
width, high = screen.size
video = ScreenshotVideo(width, high, fps=60)
video.pre_video_record()  # 預錄制獲取最優fps
video('test1.mp4')
video.run()

關于基于Python+OpenCV如何制作屏幕錄制工具就分享到這里啦,希望上述內容能夠讓大家有所提升。如果想要學習更多知識,請大家多多留意小編的更新。謝謝大家關注一下億速云網站!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

南康市| 宜丰县| 仪陇县| 平泉县| 桃江县| 鲁甸县| 洛南县| 麟游县| 正安县| 安岳县| 商水县| 枞阳县| 彰化县| 庆阳市| 平原县| 福州市| 永吉县| 水城县| 孝义市| 云龙县| 怀仁县| 临武县| 长岛县| 宁明县| 石屏县| 冷水江市| 德阳市| 全州县| 太仓市| 大同县| 志丹县| 桃江县| 阿瓦提县| 普定县| 海兴县| 永城市| 灵丘县| 寻乌县| 项城市| 丰宁| 正镶白旗|