前言
这两天在做毕设,尝试使用 Python 的 cv2 库读取一个视频文件并对图像进行处理,但我读取完视频文件后发现内存占用达到了 4.9GB,可实际上视频文件之后 10.8MB 多一点:
原因
由于我的电脑只有可怜的 8GB 内存,所以这个问题需要进行及时处理,否则视频文件一大内存肯定会溢出。
首先我尝试读取一段视频,并读取单帧图片,然后 sys.getsizeof() 查询图片的实际存储大小,发现单帧图片的大小大概在 2.63MB 左右,这个大小还行,但实际再算上视频的 1389 帧的数量,内存占用就达到了 3662MB。
然后查看了一下图片的存储格式,numpy.ndarray,每个像素点也是,但每个通道的数据是uint8。
恍然大悟,720 * 1280 * 3 = 2764800 Byte,算上数组的指针等开销,确实差不多。
但视频的压缩率是真的高,也不知道怎么实现的。
import sysimport cv2
# Test1: 查看整个视频文件读取后的大小 3662MBvideo = cv2.VideoCapture("data/TrafficVideo.mp4")print(sys.getsizeof(video)) # 32 Byteval, img = video.read()print(sys.getsizeof(val)) # 28 Byteprint(sys.getsizeof(img)) # 2764928 Byteprint(video.get(cv2.CAP_PROP_FRAME_COUNT)) # 1389video.release()
# Test2: 查看存储格式 uint8 1Bytevideo = cv2.VideoCapture("data/TrafficVideo.mp4")val, img = video.read()print(type(img)) # <class 'numpy.ndarray'>print(img.shape) # (720, 1280, 3) = 2764800 单个像素 1Byteprint(type(img[0][0][0])) # <class 'numpy.uint8'>video.release()
解决方案
方法1: 缩放图像
这里我尝试将图像缩放到原有的 1/4 大小(高和宽对半),内存占用直接砍 3/4 ,立竿见影:
import sysimport cv2import time
# Test3: 尝试将图片压缩到原始的1/4 915MBvideo = cv2.VideoCapture("data/TrafficVideo.mp4")val, img = video.read()height, width, channel = img.shapeimg = cv2.resize(img, (int(height/2), int(width/2)))print(sys.getsizeof(img)) # 691328 Bytevideo.release()
# Test4: 看看压缩后再放大的图片效果video = cv2.VideoCapture("data/TrafficVideo.mp4")val, img = video.read()cv2.imshow("Origin", img)height, width, channel = img.shapeimg = cv2.resize(img, (int(width/2), int(height/2)))img = cv2.resize(img, (int(width), int(height)))cv2.imshow("Resize", img)cv2.waitKey(0)video.release()
比比时间看看,如果不算提前读取的时间,从硬盘取比从内存区慢了近10倍,原来抑制播放速度的最大原因是读取速度啊…
# Test5:time1 = time.time()video = cv2.VideoCapture("data/TrafficVideo.mp4")val, img = video.read()cv2.imshow("Origin", img)time2 = time.time()print(time2 - time1)
height, width, channel = img.shapeimg = cv2.resize(img, (int(width/2), int(height/2)))
time1 = time.time()img = cv2.resize(img, (int(width), int(height)))cv2.imshow("Resize", img)time2 = time.time()print(time2 - time1)video.release()
碰到个bug,尝试 安装对应包之后,安装opencv-contrib-python不是opencv-python 我之前试过cv2和pyqt的包冲突,opencv-contrib-python-headless
sudo apt install libgtk2.0-devsudo apt install pkg-configpip install opencv-contrib-python
方法1:删除 cv2 中的 libqxcb
找到 ~/.local/lib/python3.8/site-packages/cv2/qt/plugins
调用的相同库 libqxcb.so
,并删除该文件,但在其他只调用 cv2 的项目中无法再使用窗口
方法2:安装 opencv-contrib-python-headless
pip uninstall opencv-pythonpip install opencv-contrib-python-headless
cv2.error: OpenCV(4.5.5) /io/opencv/modules/highgui/src/window.cpp:1268: error: (-2:Unspecified error) The function is not implemented.Rebuild the library with Windows, GTK+ 2.x or Cocoa support.If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage'