目录
一、DNN风格迁移:原理与代码实现
1. 核心原理
2. 实战代码实现
3. 关键函数解析
二、CSRT物体追踪:原理与代码实现
1. 核心原理
2. 实战代码实现
3. 关键函数解析
三、两者整合:实时风格迁移+物体追踪
1. 整合核心逻辑
2. 整合后完整代码
3. 整合关键优化点
四、实战注意事项
在计算机视觉实战中,将风格迁移与物体追踪结合可实现更具视觉冲击力的效果。本文基于OpenCV,从原理到代码逐模块拆解,最终实现“实时风格迁移+目标追踪”的融合方案,全程聚焦实操,不堆砌冗余理论。
一、DNN风格迁移:原理与代码实现
1. 核心原理
DNN(Deep Neural Network,深度神经网络)是深度学习的核心载体,通过多层神经元模拟人脑结构,实现从数据中自动提取特征、完成复杂任务(如图像识别、风格迁移)。与传统浅层网络相比,DNN凭借深层结构可捕捉更抽象的特征,在计算机视觉领域中,预训练DNN模型能跳过繁琐的特征工程,直接用于推理部署,本文风格迁移正是基于预训练DNN模型快速实现。
基于预训练DNN模型的风格迁移,本质是通过神经网络提取输入图像的内容特征与风格图像的风格特征,再融合生成新图像。本文直接使用预训练的`.t7`模型(基于Torch框架训练),跳过训练环节,专注推理部署,兼顾速度与效果。
核心流程:读取图像→生成符合模型输入要求的Blob→模型前向传播→结果后处理(维度转换、归一化)→输出风格化图像。
2. 实战代码实现
依赖库:`opencv-python`、`numpy`,需提前准备4个预训练模型(放置于`model`文件夹):`composition_vii.t7`、`candy.t7`、`udnie.t7`、`feathers.t7`。
import cv2
import numpy as np
# 1. 加载预训练模型(仅加载一次,提升效率)
models = {
"left_top": cv2.dnn.readNet("model/composition_vii.t7"),
"right_top": cv2.dnn.readNet("model/candy.t7"),
"left_bottom": cv2.dnn.readNet("model/udnie.t7"),
"right_bottom": cv2.dnn.readNet("model/feathers.t7")
}
# 2. 风格迁移核心函数
def style_transfer(img, net):
h, w = img.shape[:2]
# 生成模型输入Blob:图像归一化、尺寸调整、均值减法
blob = cv2.dnn.blobFromImage(
img, 1.0, (w, h), (103.939, 116.779, 123.680),
swapRB=True, crop=False
)
# 设置模型输入
net.setInput(blob)
# 前向传播推理风格化结果
preds = net.forward()
# 结果后处理:维度转换(1,3,H,W)→(H,W,3)
preds = preds.reshape(3, h, w)
preds = np.transpose(preds, (1, 2, 0))
# 归一化到0-255并转为uint8(OpenCV兼容格式)
preds = (preds – preds.min()) / (preds.max() – preds.min() + 1e-8)
preds = (preds * 255).astype(np.uint8)
# 确保3通道(兼容灰度图输入)
if preds.shape[2] != 3:
preds = cv2.cvtColor(preds, cv2.COLOR_GRAY2BGR)
return preds
# 3. 摄像头实时风格迁移(四区域分风格)
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
h, w = frame.shape[:2]
h_half, w_half = h//2, w//2
# 分割图像为四区域,分别风格迁移
tl = style_transfer(frame[:h_half, :w_half], models["left_top"])
tr = style_transfer(frame[:h_half, w_half:], models["right_top"])
bl = style_transfer(frame[h_half:, :w_half], models["left_bottom"])
br = style_transfer(frame[h_half:, w_half:], models["right_bottom"])
# 拼接结果并显示
top_row = np.hstack((tl, tr))
bottom_row = np.hstack((bl, br))
merged = np.vstack((top_row, bottom_row))
cv2.imshow("Style Transfer", merged)
if cv2.waitKey(1) == 27:
break
cap.release()
cv2.destroyAllWindows()
3. 关键函数解析
-
cv2.dnn.readNet():加载预训练DNN模型,支持`.t7`、`.pb`等多种格式,此处用于读取风格迁移模型。
-
cv2.dnn.blobFromImage():将图像转换为模型可接受的Blob格式,核心参数需匹配模型训练时的配置(均值、通道交换等),否则会导致风格异常。
-
net.setInput():为DNN模型设置输入数据(Blob格式),是推理前的必要步骤。
-
net.forward():执行模型前向传播,返回风格化后的特征图,需后续维度转换才能作为图像显示。
-
np.transpose():调整数组维度,将模型输出的(通道数,高度,宽度)转为OpenCV支持的(高度,宽度,通道数)。
二、CSRT物体追踪:原理与代码实现
1. 核心原理
CSRT(Channel and Spatial Reliability Tracking)是OpenCV内置的高精度追踪算法,结合了通道可靠性和空间可靠性评估,能适应光照变化、目标缩放等场景,精度优于KCF、BOOSTING等算法,适合实时场景。
核心流程:初始化追踪器→手动选择ROI(感兴趣区域)→逐帧更新追踪器→获取目标坐标并绘制。
2. 实战代码实现
import cv2
# 1. 初始化CSRT追踪器
tracker = cv2.TrackerCSRT_create()
tracking = False # 追踪状态标志
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 2. 按键控制:按's'选择ROI开始追踪
key = cv2.waitKey(1) & 0xFF
if key == ord('s'):
tracking = True
# 选择ROI(感兴趣区域),返回(x,y,w,h)
roi = cv2.selectROI("CSRT Tracking", frame, showCrosshair=False)
# 初始化追踪器(绑定当前帧和ROI)
tracker.init(frame, roi)
elif key == 27:
break
# 3. 追踪更新
if tracking:
# 逐帧更新追踪器,返回追踪状态和目标框坐标
success, box = tracker.update(frame)
if success:
x, y, w, h = [int(v) for v in box]
# 绘制追踪框(绿色,线宽2)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0,255,0), 2)
# 显示结果
cv2.imshow("CSRT Tracking", frame)
cap.release()
cv2.destroyAllWindows()
3. 关键函数解析
-
cv2.TrackerCSRT_create():创建CSRT追踪器实例,无需额外配置,直接调用即可。
-
cv2.selectROI():弹出窗口让用户手动框选目标区域,返回矩形框坐标(x,y,w,h),`showCrosshair`参数控制是否显示十字准星。
-
tracker.init():初始化追踪器,绑定初始帧和ROI,是追踪的起点,需在选择ROI后调用。
-
tracker.update():逐帧更新追踪状态,返回两个值:`success`(布尔值,追踪是否成功)和`box`(目标框坐标),失败时`box`无效。
-
cv2.rectangle():在图像上绘制矩形追踪框,参数依次为:图像、左上角坐标、右下角坐标、颜色、线宽。
三、两者整合:实时风格迁移+物体追踪
1. 整合核心逻辑
整合的关键是解决两个核心问题:① 追踪精度:风格迁移会改变图像像素,直接在风格化图像上追踪会导致精度下降,因此采用“原始帧追踪→风格化处理→追踪框绘制到风格化图像”的流程;② 格式兼容:风格化结果需转为OpenCV兼容格式(3通道、uint8、连续内存布局),避免绘图报错。
2. 整合后完整代码
import cv2
import numpy as np
# ====================== 初始化配置 ======================
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("无法打开摄像头!")
exit()
# 初始化CSRT追踪器
tracker = cv2.TrackerCSRT_create()
tracking = False
track_box = None
# 加载风格迁移模型
try:
models = {
"left_top": cv2.dnn.readNet("model/composition_vii.t7"),
"right_top": cv2.dnn.readNet("model/candy.t7"),
"left_bottom": cv2.dnn.readNet("model/udnie.t7"),
"right_bottom": cv2.dnn.readNet("model/feathers.t7")
}
print("模型加载成功!")
except Exception as e:
print(f"模型加载失败:{e}")
cap.release()
exit()
# ====================== 核心函数 ======================
def style_transfer(img, net):
h, w = img.shape[:2]
blob = cv2.dnn.blobFromImage(
img, 1.0, (w, h), (103.939, 116.779, 123.680),
swapRB=True, crop=False
)
net.setInput(blob)
preds = net.forward()
preds = preds.reshape(3, h, w)
preds = np.transpose(preds, (1, 2, 0))
preds = (preds – preds.min()) / (preds.max() – preds.min() + 1e-8)
preds = (preds * 255).astype(np.uint8)
if preds.shape[2] != 3:
preds = cv2.cvtColor(preds, cv2.COLOR_GRAY2BGR)
return preds
# ====================== 主循环 ======================
while True:
ret, frame = cap.read()
if not ret:
break
frame_h, frame_w = frame.shape[:2]
if len(frame.shape) == 2:
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
# 按键控制
key = cv2.waitKey(1) & 0xFF
if key == ord('s'):
tracking = True
roi = cv2.selectROI("Tracking + Style Transfer", frame, showCrosshair=False)
tracker.init(frame, roi)
elif key == 27:
break
# 原始帧上更新追踪
if tracking:
success, box = tracker.update(frame)
track_box = [int(v) for v in box] if success else None
# 四区域风格迁移
h_half, w_half = frame_h//2, frame_w//2
tl = style_transfer(frame[:h_half, :w_half], models["left_top"])
tr = style_transfer(frame[:h_half, w_half:], models["right_top"])
bl = style_transfer(frame[h_half:, :w_half], models["left_bottom"])
br = style_transfer(frame[h_half:, w_half:], models["right_bottom"])
# 拼接风格化图像(统一尺寸+连续内存布局)
tl = cv2.resize(tl, (w_half, h_half))
tr = cv2.resize(tr, (w_half, h_half))
bl = cv2.resize(bl, (w_half, h_half))
br = cv2.resize(br, (w_half, h_half))
top_row = np.hstack((tl, tr))
bottom_row = np.hstack((bl, br))
styled_frame = np.vstack((top_row, bottom_row))
# 关键:转为连续内存布局,解决OpenCV绘图兼容问题
styled_frame = np.ascontiguousarray(styled_frame, dtype=np.uint8)
# 绘制追踪框
if tracking and track_box is not None:
x, y, w, h = track_box
if 0 <= x < frame_w and 0 <= y < frame_h:
cv2.rectangle(styled_frame, (x, y), (x+w, y+h), (0,255,0), 2)
cv2.imshow("Tracking + Style Transfer", styled_frame)
cap.release()
cv2.destroyAllWindows()
3. 整合关键优化点
-
追踪与风格化顺序:优先在原始帧上执行tracker.update(),确保追踪精度,再对原始帧做风格迁移,最后将追踪框绘制到风格化图像上,避免风格化干扰追踪。
-
格式兼容性修复:通过np.ascontiguousarray()强制风格化图像为连续内存布局,解决OpenCV cv2.rectangle() 函数报“Layout incompatible”错误的问题。
-
尺寸统一:用cv2.resize() 统一四区域风格化结果的尺寸,避免拼接后图像变形,确保追踪框坐标映射准确。
-
鲁棒性增强:增加摄像头打开校验、模型加载异常处理、坐标越界判断,避免程序直接崩溃。
四、实战注意事项
模型路径:确保`model`文件夹与代码文件同级,模型文件名与代码中一致,否则会报模型加载失败错误。
性能优化:若运行卡顿,可缩小摄像头分辨率(如`cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)`),减少风格迁移的计算量。
追踪稳定性:CSRT精度高但速度略慢,若需实时性优先,可替换为cv2.TrackerKCF_create() 追踪器。
风格调整:更换`.t7`模型即可切换风格,可从OpenCV官方仓库或第三方资源获取更多预训练模型。
本文通过模块化拆解与整合,实现了两种核心视觉任务的融合,代码可直接落地运行。实际项目中可基于此扩展,如增加多目标追踪、风格切换按键、视频文件输入输出等功能。
网硕互联帮助中心




评论前必须登录!
注册