i want to display mouse pointer in my recording

拈花ヽ惹草 提交于 2020-02-29 08:02:43

问题


i am making an screen recorder that records the screen of the desktop. but when i record the screen the mouse pointer (cursor) is not visible in the recording. so is there any way i can show the mouse pointer in my recording. this is my code..

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:


I don't think it's possible with that approach - but am always happy to be corrected and learn something new. I know of a couple of workarounds.

The first is to continue to use pyautogui and to call its mouseposition() function and paste/draw your own synthetic mouse pointer onto the grab. I did that with OpenCV's fillPoly() function:

#!/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()


The second is to use ffmpeg which can capture the mouse - you can either run ffmpeg in place of your current app, or pipe the output from ffmpeg into your app through a pipe and continue to process it as you are now. That might look like this:

#!/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()

Note that pyautogui takes around 600ms to capture one frame on my Mac, whereas the ffmpeg above achieves around 20fps, or 50ms per frame.

Keywords: Python. image processing, ffmpeg, pyautogui, screen-grab, screen-capture, screengrab, screencapture, fps. speed, prime.



来源:https://stackoverflow.com/questions/60264704/i-want-to-display-mouse-pointer-in-my-recording

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!