【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存

时间:2022-12-18 12:56:24


前言

本文参考视频:唐宇迪老师的视频
我的代码也就是差不多跟着视频里的代码敲了一遍,并对自己不懂的地方进行加强学习和补充。

一、cv2读取图片并展示

1.1、cv2.imread读取图片

import cv2
X1=cv2.imread('dog.jpg')

值得注意的是cv2.imread读取的图片为BGR模式,而非RGB模式。
我们检查一下X1的属性:

print(X1)
print(X1.shape)
print(type(X1))

【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存

【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
因为图片读进来的维度顺序为h,w,c,和从深度学习里张量的c,h,w有点区别,所以看起来比较怪。
我们再看看读取的图片的数据类型

print(X1.dtype)

【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
uint8是8位无符号整型(1个字节),一般图像的显示就用8位的uint8,可以表示的范围是0-255

1.2、cv2.imshow展示图片

进行图片展示的函数为:

cv2.imshow('dog',X1)

dog为展示的窗口名称,X1为要展示的“图像”
当然如果此时直接运行的话,会显示不出来任何结果:
【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
为了能正常运行,需要加上几句话:

cv2.imshow('dog',X1)
cv2.waitKey(0) #0为任意键位终止
cv2.destroyAllWindows()

此时的图片就能正常显示出来了:
【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
如果想对窗口展示的时间作限制的话,可以在cv2.waitKey(0) 的括号里做一定的修改:

cv2.imshow('dog',X1)
cv2.waitKey(1000) 
cv2.destroyAllWindows()

比如这里改成1000,就是窗口保持1S,然后消失。2000就是2S,以此类推。

1.3、完整代码

cv2.imshow('dog',X1)
import cv2

X1=cv2.imread('dog.jpg')
cv2.imshow('dog',X1)
cv2.waitKey(0) #0为任意键位终止
cv2.destroyAllWindows()

1.4、封装函数调用

如果嫌后面几行每次写都太麻烦,可以封装一个函数

import cv2

def cvshow(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)  # 0为任意键位终止
    cv2.destroyAllWindows()

X1=cv2.imread('dog.jpg')
cvshow('dog',X1)

1.5、cv2读取为灰度图像

相比于前面读取为彩色图片,只有一个地方需要修改:

X1=cv2.imread('dog.jpg',cv2.IMREAD_GRAYSCALE)

或者改为:

X1=cv2.imread('dog.jpg',0)

最后的效果都是一样的:
【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
完整代码:

import cv2
X1=cv2.imread('dog.jpg',0)
cv2.imshow('dog',X1)
cv2.waitKey(0) #0为任意键位终止
cv2.destroyAllWindows()

我们此时再打印一下图像的几个属性看看:

print(X1)
print(X1.shape)
print(type(X1))

【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
可以很明显看到,数组变成了2维,少了通道这个维度了。
当然,读入的灰度图也是uint8数据类型

1.6、cv2.imwrite保存图像

一句话就够了 :

cv2.imwrite('baocun.jpg', X1)

结果:
【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存

二、cv2读取视频并且展示

2.1 展示彩色视频

我们直接放代码看看

import cv2

cap=cv2.VideoCapture('1.mp4')#设为0的话为调用摄像头
if cap.isOpened():  #判断是否正常打开
    ret,frame=cap.read()#返回两个参数,第一个是bool是否正常打开,第二个是照片数组
else:
    ret =False

while ret:
    ret,frame=cap.read()
    if frame is None:
        break
    if ret==True:
        cv2.imshow('video',frame)
        if cv2.waitKey(100)&0xFF== ord('q'):   #cv2.waitKey,每帧数据延时 Xms,是视频播放速度的快慢,值设的越大越慢
            break
cap.release() # 释放摄像头
cv2.destroyAllWindows()

1)首先生成一个VideoCapture对象,用以捕捉视频流。如果想捕捉摄像头的视频流,可以设置:

cap=cv2.VideoCapture(0)#设为0的话为调用摄像头

2)然后使用 cap.isOpened()判断是否正常打开
3)如果正常打开,用cap.read()开始一帧帧读取视频,返回两个参数ret,frame,第一个是bool是否正常打开,第二个是图像数组
4)一切顺利的情况下,cv2.imshow()就会开始展示视频了
5)cv2.waitKey(100)是对每帧图像进行延迟的函数,这里是延迟100ms,数字设的越大,播放的越慢
6)ord(‘q’)为检测按键q,如果键盘有触碰到了按键q,就会关闭视频。

最后结果:
【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
这里可以看到出现了一个问题:
由于我导入的视频是4K视频,分辨率很大,超过了屏幕的显示范围。为了更好展示,我们需要对视频帧进行缩放,缩放到1080P(1920X1080):

frame=cv2.resize(frame,(1920,1080))  #4K视频缩小为1080p

值得一提的是,4K视频要转换为1080p视频时,差不多 4个像素就要合成为一个像素。
完整代码:

import cv2

cap=cv2.VideoCapture('1.mp4')#设为0的话为调用摄像头
if cap.isOpened():  #判断是否正常打开
    ret,frame=cap.read()#返回两个参数,第一个是bool是否正常打开,第二个是照片数组
else:
    ret =False

while ret:
    ret,frame=cap.read()
    if frame is None:
        break
    if ret==True:
        frame=cv2.resize(frame,(1920,1080))  #4K视频缩小为1080p
        cv2.imshow('video',frame)
        if cv2.waitKey(100)&0xFF== ord('q'):   #cv2.waitKey,每帧数据延时 Xms,是视频播放速度的快慢,值设的越大越慢
            break
cap.release() # 释放摄像头
cv2.destroyAllWindows()

当然还可以对代码进行更进一步的简化:

import cv2
cap=cv2.VideoCapture('1.mp4')#设为0的话为调用摄像头

while (cap.isOpened()):
    ret,frame=cap.read()
    if frame is None:
        break
    if ret==True:
        frame=cv2.resize(frame,(1920,1080))  #4K视频缩小为1080p
        cv2.imshow('video',frame)
        if cv2.waitKey(100)&0xFF== ord('q'):   #cv2.waitKey,每帧数据延时 Xms,是视频播放速度的快慢,值设的越大越慢
            break
cap.release() # 释放摄像头
cv2.destroyAllWindows()

2.2 展示灰度视频

只用加一句代码就行:

gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存
完整代码:

import cv2
cap=cv2.VideoCapture('1.mp4')#设为0的话为调用摄像头

while (cap.isOpened()):
    ret,frame=cap.read()
    if frame is None:
        break
    if ret==True:
        gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        frame=cv2.resize(gray,(1920,1080))  #4K视频缩小为1080p
        cv2.imshow('video',frame)
        if cv2.waitKey(100)&0xFF== ord('q'):   #cv2.waitKey,每帧数据延时 Xms,是视频播放速度的快慢,值设的越大越慢
            break
cap.release() # 释放摄像头
cv2.destroyAllWindows()

2.3 保存视频

需要在原来的代码中添加几句话:

fourcc = cv2.VideoWriter_fourcc(*'mp4v') #保存格式为mp4格式
out = cv2.VideoWriter('2.mp4',fourcc, 30, (1920,1080),True) 
out.write(frame)

cv2.VideoWriter第一个参数是保存路径,第二个参数是指定的编码器,第三个参数是 保存的帧率,第四个参数是保存的尺寸,第五个参数为是否保存为彩色图像。

完整代码如下:

import cv2

cap=cv2.VideoCapture('1.mp4')#设为0的话为调用摄像头
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('2.mp4',fourcc, 30, (1920,1080),True)
while (cap.isOpened()):
    ret,frame=cap.read()
    if frame is None:
        break
    if ret==True:
        #gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        frame=cv2.resize(frame,(1920,1080))  #4K视频缩小为1080p
        cv2.imshow('video',frame)
        out.write(frame)
        if cv2.waitKey(10)&0xFF== ord('q'):   #cv2.waitKey,每帧数据延时 Xms,是视频播放速度的快慢,值设的越大越慢
            break
cap.release() # 释放摄像头
cv2.destroyAllWindows()