opencv DNN模块及利用实现风格迁移
目录
一.DNN模块
1.DNN模块介绍
2.DNN核心调用流程
二.DNN模型实现风格迁移
1.DN模型风格迁移介绍
2.代码实现
图片风格迁移:
①读取原图
②获取图片的宽和高,并用cv2.dnn.blobFromImage()方法预处理图片
③加载模型
④图片输入,和前向传播
⑤调整out形状
⑥归一化
⑦转置结果维度
视频风格迁移:
①读取视频
②直接加载模型
③循环对每一帧图片进行风格迁移操作
④释放资源
一.DNN模块
1.DNN模块介绍
- 定义: 开源项目OpenCV的深度神经网络模块,主要用于加载和调用已训练好的模型完成预测。
- 特点:
- 模块本身仅实现模型推理功能,代码精简。
- 外部依赖性极低,无需复杂的环境部署。
- 提供统一接口(readNet),支持TensorFlow、Caffe、PyTorch等多种框架训练的模型。
- 模型支持多种设备和操作系统。
2.DNN核心调用流程
- 模型加载: 使用readNet方法导入模型。为保证兼容性,推荐使用统一接口readNet而非框架特定的入口。
- 图像预处理: 使用dnn_blobFromImage方法,对输入图片进行尺寸缩放、减去均值、通道顺序交换(从BGR改为RGB)等操作,将其转换为符合模型输入要求的四维tensor格式。
- 模型输入与前向传播: 使用setInput方法将预处理后的tensor送入模型,再使用forward方法执行前向传播,获得模型输出。
- 结果后处理: 将模型输出的tensor进行规范化、维度转换,并转换回OpenCV可显示的标准格式,以便进行后续处理或展示。
二.DNN模型实现风格迁移
1.DN模型风格迁移介绍
- DN模块可用于实现图片的风格迁移,即将图像转化为特定画风。
- 实现流程:加载预训练模型(如星空模型),循环处理视频帧,通过前向传播获得结果,随后经过归一化和维度转换,最终在图像开发者上显示。
2.代码实现
图片风格迁移:
①读取原图
import cv2
image=cv2.imread('coca.png')
cv2.imshow('image',image)
cv2.waitKey(0)
②获取图片的宽和高,并用cv2.dnn.blobFromImage()方法预处理图片
对输入图片进行尺寸缩放、减去均值、通道顺序交换(从BGR改为RGB)等操作,将其转换为符合模型输入要求的四维tensor格式
#图片预处理
(h,w)=image.shape[:2]
blob=cv2.dnn.blobFromImage(image,1,(w,h),(0,0,0),swapRB=False,crop=False)
③加载模型
推荐使用统一接口readNet()方法读取
#加载模型
net=cv2.dnn.readNet(r'model\starry_night.t7')
模型有很多种,这里我们以一种为例
④图片输入,和前向传播
net.setInput(blob)
#对输入图像前向传播,得到输出结果
out=net.forward()#四维状
注意:这里我们得到的输出结果out是四维的,第0维是batch_size大小
⑤调整out形状
将输出结果out转换为opencv可以展现的形状,舍弃第0维的batch_size
out_new=out.reshape(out.shape[1],out.shape[2],out.shape[3])
⑥归一化
cv2.normalize(out_new,out_new,norm_type=cv2.NORM_MINMAX)
由于数据中存在负数等情况,所谓i我们将所有数据归一化到0~1之间,opencv会自动将这些0~1的值转化到0~255之间
⑦转置结果维度
将结果转换为opencv的bgr通道顺序
result=out_new.transpose(1,2,0)
cv2.imshow('Stylized Image',result)
cv2.waitKey(0)
视频风格迁移:
①读取视频
import cv2
video=cv2.VideoCapture('test.avi')
②直接加载模型
# 加载模型
net=cv2.dnn.readNet(r'..\model\starry_night.t7')
③循环对每一帧图片进行风格迁移操作
操作与上述案例操作一致
while True:ret,frame=video.read()if not ret:breakcv2.imshow('frame', frame)cv2.waitKey(60)# 图片预处理(h, w) = frame.shape[:2]blob = cv2.dnn.blobFromImage(frame, 1, (w, h), (0, 0, 0), swapRB=False, crop=False)net.setInput(blob)# 对输入图像前向传播,得到输出结果out = net.forward() # 四维状# 调整out形状out_new = out.reshape(out.shape[1], out.shape[2], out.shape[3])# 归一化cv2.normalize(out_new, out_new, norm_type=cv2.NORM_MINMAX)# 转置输出结果的维度result = out_new.transpose(1, 2, 0)cv2.imshow('Stylized Image', result)if cv2.waitKey(60)==27:break
④释放资源
video.release()
cv2.destroyAllWindows()