解决pyuvc无法读取yuv格式的问题

问题描述

我使用pyuvc访问uvc摄像头,但是发现pyuvc只支持了MJPEG的格式和GRAY格式。我在linux下通过v4l2-ctl查看,发现摄像头本身还支持YUV的格式,但是pyuvc解析出的帧格式则没有。后面通过阅读pyuvc的代码,发现libuvc本身没有限制YUV的格式,是pyuvc限制的。修改代码后重新编译whl,重新安装就可以了。

如何让pyuvc支持yuv格式

要修改的内容都在uvc_bindings.pyx中。

首先修改_supported_formats,增加对uvc.UVC_FRAME_FORMAT_YUYV和uvc.UVC_FRAME_FORMAT_ANY的支持。修改前后的对比如下:
在这里插入图片描述
然后在class Frame中增加一个获取原始buffer的接口:

    @property
    def data_buffer(self):
        cdef np.uint8_t[::1] view = <np.uint8_t[:self._uvc_frame.data_bytes]>self._uvc_frame.data
        return view

最后修改class Capture的get_frame()成员函数,让其在读取到MJPEG、GRAY之外的格式时,使用Frame类来存放帧数据:

        if uvc_frame.frame_format == uvc.UVC_COLOR_FORMAT_MJPEG:
            ##check jpeg header
            header_ok = turbojpeg.tjDecompressHeader2(
                self.tj_context,
                <unsigned char *>uvc_frame.data,
                uvc_frame.data_bytes,
                &j_width,
                &j_height,
                &jpegSubsamp
            )
            if not (
                header_ok >= 0 and
                uvc_frame.width == j_width and
                uvc_frame.height == j_height
            ):
                raise StreamError("JPEG header corrupt.")
            out_frame_mjpeg = MJPEGFrame()
            out_frame_mjpeg.tj_context = self.tj_context
            out_frame_mjpeg.attach_uvcframe(uvc_frame=uvc_frame, copy=True)
            frame = out_frame_mjpeg

        elif uvc_frame.frame_format == uvc.UVC_COLOR_FORMAT_GRAY8:
            # if uvc_frame.width * uvc_frame.height > uvc_frame.data_bytes:
            #     raise StreamError(
            #         f"Received too few bytes to fill {uvc_frame.width}x"
            #         f"{uvc_frame.height} GRAY8 image"
            #     )
            out_frame_gray = Frame()
            out_frame_gray.attach_uvcframe(uvc_frame=uvc_frame, copy=True)
            frame = out_frame_gray

        else:
            # 这个分支是新增的
            out_frame_gray = Frame()
            out_frame_gray.attach_uvcframe(uvc_frame=uvc_frame, copy=True)
            frame = out_frame_gray

代码变化如下:

         else:
-            raise NotImplementedError(f"Unsupported frame format {uvc_frame.frame_format}")
+            out_frame_gray = Frame()
+            out_frame_gray.attach_uvcframe(uvc_frame=uvc_frame, copy=True)
+            frame = out_frame_gray

编译pyuvc

在windows下编译pyuvc需要提前安装vsstudio,我装的是vsstudio2015,具体命令参考源码中的README.rst文件的描述:

   pip install build delvewheel
   git clone https://github.com/pupil-labs/pyuvc --recursive
   cd pyuvc
   scripts/download-deps-win.ps1 -DEPS_TMP_PATH tmp
   $Env:DEPS_PATHS_LOC = "tmp/dep_paths.json"
   python -m build -w   # will create a wheel in dist/ folder; insert the wheel path below
   python scripts/repair-wheels-win.py $Env:DEPS_PATHS_LOC <wheel location> wheelhouse
   pip install wheelhouse/<wheel name>

在编译中我遇到的问题在delvewheel进行repair时报Unable to find library: msvcr100.dll【已解决】这篇文章中有介绍。

编译生成新的whl文件在源码的wheelhouse/目录下。在本地安装或者复制到其它环境下安装均可。

如何使用yuv数据

我的摄像头返回的是packaged格式的YUV420数据,我直接保存到磁盘文件中。

frame = cam.get_frame(timeout=0.001)
data_buffer = frame.data_buffer
with open(f"data_buffer{i}.yuy2",'wb') as f:
    f.write(data_buffer)

mat = np.asarray(data_buffer) #取原始数据
mat = mat.reshape((camera_spec.height, camera_spec.width, 2))  #将因为是yuv420,所以最后一个维度是2. 宽高是图片分辨率
#print(f"new mat.shape()={mat.shape}")
bgr = cv2.cvtColor(mat, cv2.COLOR_YUV2BGR_YUY2)  #将yuv转换为bgr
cv2.imshow("test", bgr)  

也可以用opencv来转码。

参考资料

使用python访问uvc摄像头

delvewheel进行repair时报Unable to find library: msvcr100.dll【已解决】

linux下使用v4l2-ctl查看摄像头数据

MATLAB是一款强大的数学计算软件,它可以用来进行图像处理YUV格式是一种常见的数字图像格式,通常用于视频编码和压缩。在MATLAB中,读取YUV格式图片可以通过以下两种方法实现: 1. 使用MATLAB自带的yuvRead函数。这个函数可以直接读取YUV格式的图片,并将其转换为RGB格式,方便进行后续的图像处理读取YUV格式图片的基本命令如下: > yuv = yuvRead('filename.yuv', width, height, frame_num); 其中,'filename.yuv'是 YUV 格式的文件名,width 和 height 为图像的宽度和高度,frame_num 是帧的数量。该函数返回值是一个三维矩阵,表示读取的图像数据。 2.手动读取YUV格式图片。如果没有yuvRead函数或者需要手动读取YUV格式图片,可以使用fread函数来读取二进制数据,并进行相应的转换。读取YUV格式图片的基本步骤如下: (1)打开文件,并读取二进制数据: > fid = fopen('filename.yuv', 'rb'); > data = fread(fid, width*height*3/2, 'uint8'); 其中,'rb' 表示以二进制模式打开文件,width 和 height 为图像的尺寸,3/2 表示每个像素由一个亮度值和两个色度值构成。 (2)解码数据,并将其转换为 RGB 格式的图像: > y = reshape(data(1:width*height), [width height]); > u = reshape(data(width*height+1:width*height*5/4), [width/2 height/2]); > v = reshape(data(width*height*5/4+1:width*height*3/2), [width/2 height/2]); > u = imresize(u, 2); > v = imresize(v, 2); > rgb = ycbcr2rgb(cat(3, y, u, v)); 其中,ycbcr2rgb函数可以将 YCbCr 格式的图像转换为 RGB 格式的图像,cat函数可以将三个数据矩阵连接起来,imresize函数可以调整尺寸。最后得到的rgb表示 RGB 格式的图像数据。 以上就是在MATLAB中读取YUV格式图片的两种方法。由于yuvRead函数已经封装好了读取、解码和转换的功能,所以使用它会更简单一些。而手动读取的方法则需要自己写代码来完成相应的功能,但也能够更加灵活地进行控制和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值