如何在我的录屏中显示鼠标指针

3

我正在制作一个桌面屏幕录像机,但当我录制屏幕时,鼠标指针(光标)不会在录像中显示。 有没有什么办法可以在我的录像中显示鼠标指针? 以下是我的当前代码:

import cv2
import numpy as np
import pyautogui
import datetime

date = datetime.datetime.now()

SCREEN_SIZE = (1366, 768)
framerate = 12

fourcc = cv2.VideoWriter_fourcc(*'XVID')
filename = 'E:/project/videos/rec_%s%s%s%s%s%s.avi' % (date.year, date.month, date.day, date.hour, date.minute, date.second)

out = cv2.VideoWriter(filename, fourcc,framerate, SCREEN_SIZE)

while True:
    img = pyautogui.screenshot()
    frame = np.array(img)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    out.write(frame)
    cv2.imshow('screenshot', frame)
    if cv2.waitKey(1) == ord("q"):
        break

cv2.destroyAllWindows()
out.release()
1个回答

3
我不认为用那种方法是可行的,但我很乐意接受纠正并学到新知识。我知道有一些解决方法。
第一个方法是继续使用pyautogui,调用它的mouseposition()函数并在截图上粘贴/绘制自己合成的鼠标指针。我使用了OpenCV的fillPoly()函数来实现:
#!/usr/bin/env python3

import cv2
import numpy as np
import pyautogui
import datetime

# X and Y coordinates of mouse pointer
Xs = [0,8,6,14,12,4,2,0]
Ys = [0,2,4,12,14,6,8,0]

while True:

    img = pyautogui.screenshot()
    mouseX,mouseY = pyautogui.position()
    mouseX *= 2
    mouseY *= 2

    frame = np.array(img)
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

    # Synthesize mouse pointer
    Xthis = [4*x+mouseX for x in Xs]
    Ythis = [4*y+mouseY for y in Ys]
    points = list(zip(Xthis,Ythis))
    points = np.array(points, 'int32')
    cv2.fillPoly(frame,[points],color=[255,255,255])

    # Make it a bit smaller for display
    frame = cv2.resize(frame,(960,540))

    cv2.imshow('Title', frame)
    if cv2.waitKey(1) == ord("q"):
        break

cv2.destroyAllWindows()
out.release()

enter image description here


第二种方法是使用ffmpeg,它可以捕获鼠标 - 您可以在当前应用程序的位置运行ffmpeg,或通过管道将ffmpeg的输出传输到您的应用程序中,并像现在一样继续处理它。可能看起来像这样:
#!/usr/bin/env python3

# ffmpeg -y -pix_fmt bgr0 -f avfoundation -r 20 -t 10 -i 1 -vf scale=w=3840:h=2160 -f rawvideo /dev/null

import sys
import cv2
import time
import subprocess
import numpy as np

w,h = 3840, 2160

def ffmpegGrab():
    """Generator to read frames from ffmpeg subprocess"""
    cmd = [
        'ffmpeg',
        '-pix_fmt', 'bgr0',
        '-f', 'avfoundation',
        '-capture_cursor', '1',
        '-capture_mouse_clicks', '1',
        '-r', '20',
        '-i', '1',
        '-vf','scale=w=3840:h=2160',
        '-f', 'rawvideo',
        'pipe:1'
    ]
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    while True:
        frame = proc.stdout.read(w*h*4)
        yield np.frombuffer(frame, dtype=np.uint8).reshape((h,w,4))

# Get frame generator
gen = ffmpegGrab()

# Get start time
start = time.time()

# Read video frames from ffmpeg in loop
nFrames = 0
while True:
    # Read next frame from ffmpeg
    frame = next(gen)
    nFrames += 1
    frame = cv2.resize(frame,(960,540))

    cv2.imshow('screenshot', frame)

    if cv2.waitKey(1) == ord("q"):
        break

    fps = nFrames/(time.time()-start)
    print(f'FPS: {fps}')


cv2.destroyAllWindows()
out.release()

enter image description here

注意,pyautogui 在我的 Mac 上捕获一帧需要约 600 毫秒的时间,而上面的 ffmpeg 实现了约 20fps,每帧约 50 毫秒。
关键词:Python、图像处理、ffmpeg、pyautogui、屏幕抓取、屏幕捕获、fps、速度、素数。

1
请注意,在 Windows 下,ffmpeg-f-i 参数将有所不同。 - Mark Setchell
我正在使用Windows操作系统,你展示的第一种使用pyautogui的方法不起作用。它只在由OpenCV创建的框架中显示光标,而在我最小化框架窗口时并没有在录制中显示。 - Cb9867
1
抱歉,我不使用Windows。我只能建议在获取鼠标位置后立即在终端上打印它,并在cv2.fillPoly()调用之前打印points数组。 - Mark Setchell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接