You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

标准Python中如何对memoryview对象使用ctypes.memmove

解决PySide6中处理后numpy数组转回QVideoFrame的内存复制问题

问题背景

使用PySide6捕获屏幕并拦截视频流,通过OpenCV处理帧后,需要将处理后的numpy数组转回QVideoFrame以输出视频流。目前已完成numpy转QImage的步骤,但在将QImage字节复制到QVideoFrame内存时遇到问题:QImage.bits()和QVideoFrame.bits()返回memoryview对象,无法通过bits()[0]获取内存指针,导致ctypes.memmove调用出错。

解决方案

无需依赖内存指针操作,直接利用Python标准的memoryview切片赋值即可完成字节复制,完全兼容标准Python环境(无需CPython特定API)。具体实现步骤如下:

  • 确保QVideoFrame已通过map(QVideoFrame.ReadWrite)完成内存映射
  • 获取QVideoFrame和QImage对应的memoryview对象
  • 通过切片赋值将QImage的字节数据直接复制到QVideoFrame的内存区域
  • 完成复制后必须调用unmap()解除内存映射,避免资源泄漏

完整代码示例

import cv2
import numpy as np
from PySide6.QtMultimedia import QVideoFrame, QVideoFrameFormat
from PySide6.QtGui import QImage

# 假设arr是OpenCV处理后的numpy数组
arr = cv2.cvtColor(arr, cv2.COLOR_BGR2RGBA)
# 从numpy数组创建QImage
image = QImage(arr.data, arr.shape[1], arr.shape[0], QImage.Format.Format_RGBA8888)

# 创建与QImage匹配的QVideoFrame格式
format_ = QVideoFrameFormat(
    image.size(),
    QVideoFrameFormat.pixelFormatFromImageFormat(image.format())
)
frame2 = QVideoFrame(format_)

# 映射QVideoFrame到可读写内存
if frame2.map(QVideoFrame.ReadWrite):
    try:
        # 获取两个对象的memoryview
        frame_memory = frame2.bits()
        image_memory = image.bits()
        
        # 直接复制字节数据
        frame_memory[:image.sizeInBytes()] = image_memory[:image.sizeInBytes()]
    finally:
        # 务必解除映射,释放资源
        frame2.unmap()

# 处理后的frame2可用于视频流输出

注意事项

  • 确保QVideoFrame的像素格式与QImage完全一致,否则会导致画面显示异常
  • 必须在try...finally块中执行unmap(),即使复制过程中出现异常也能正确释放内存
  • memoryview的切片赋值是Python标准操作,无需依赖任何第三方库或CPython私有API

内容的提问来源于stack exchange,提问作者Edward Spencer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:01:02