Python 基于 OpenCV DNN 的图像风格迁移实战
1. 技术背景
图像风格迁移(Neural Style Transfer)是深度学习在计算机视觉领域的一个经典应用。它利用卷积神经网络(CNN)提取图像的'内容'和'风格',并通过优化算法将一种图像的风格应用到另一种图像的内容上。
早期的实现通常依赖 PyTorch 或 TensorFlow,需要配置 CUDA、cuDNN 等复杂环境。而 OpenCV 4.0+ 引入了 DNN(Deep Neural Network)模块,支持直接加载 Torch (.t7) 模型进行推理,无需安装庞大的深度学习框架,极大地降低了使用门槛,非常适合初学者快速体验。
2. 环境准备
2.1 基础环境
确保已安装 Python 3.6 及以上版本。推荐使用虚拟环境管理依赖:
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
2.2 安装依赖
本项目仅需 OpenCV 库即可运行,无需额外的深度学习框架:
pip install opencv-python numpy
若需处理视频流,可额外安装 opencv-contrib-python。
3. 模型资源
本教程基于 fast-neural-style 项目预训练的模型。该项目提供了多种艺术风格的模型文件(后缀为 .t7),例如梵高、蒙德里安、毕加索等风格。
由于原始下载链接可能失效,建议从以下官方仓库获取模型:
- GitHub: https://github.com/jcjohnson/fast-neural-style
- 或者搜索开源社区中的
fast-neural-style-models资源包。
常见的模型文件名包括:udnie.t7, mosaic.t7, starry_night.t7 等。
4. 代码实现
OpenCV 官方仓库中提供了基于 C++ 和 Python 的示例代码。以下是经过适配的 Python 3 版本,支持命令行参数控制输入路径、模型路径及图像尺寸。
import cv2 as cv
import numpy as np
import argparse
import sys
def main():
parser = argparse.ArgumentParser(
description='This script is used to run style transfer models from '
'https://github.com/jcjohnson/fast-neural-style using OpenCV')
parser.add_argument('--input', help='Path to image or video. Skip to capture frames from camera')
parser.add_argument(, =)
parser.add_argument(, default=-, =, =)
parser.add_argument(, default=-, =, =)
parser.add_argument(, default=, =, =)
args = parser.parse_args()
:
net = cv.dnn.readNetFromTorch(args.model)
Exception e:
()
sys.exit()
args.:
cap = cv.VideoCapture(args.)
:
cap = cv.VideoCapture()
cv.namedWindow(, cv.WINDOW_NORMAL)
:
hasFrame, frame = cap.read()
hasFrame:
inWidth = args.width args.width != - frame.shape[]
inHeight = args.height args.height != - frame.shape[]
inp = cv.dnn.blobFromImage(frame, , (inWidth, inHeight),
(, , ), swapRB=, crop=)
net.setInput(inp)
out = net.forward()
out = out.reshape(, out.shape[], out.shape[])
out[] +=
out[] +=
out[] +=
out /=
out = out.transpose(, , )
t, _ = net.getPerfProfile()
freq = cv.getTickFrequency() /
()
args.median_filter:
out = cv.medianBlur(out, args.median_filter)
cv.imshow(, out)
cv.waitKey() == ():
__name__ == :
main()


