news 2026/4/23 15:19:45

OpenCV 学习:从光流跟踪到艺术风格迁移

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenCV 学习:从光流跟踪到艺术风格迁移

文章目录

    • 一、光流法运动轨迹跟踪
      • 关键技术分析
    • 二、基于深度学习的艺术风格迁移
      • blobFromImage函数详解
    • 三、实时目标跟踪
      • 跟踪器工作流程
    • 四、多风格实时艺术滤镜
      • 多线程优化策略
      • 性能优化技巧

一、光流法运动轨迹跟踪

光流法是一种通过分析连续帧之间的像素变化来追踪物体运动轨迹的技术。下面的代码展示了如何使用Shi-Tomasi角点检测和Lucas-Kanade光流法实现运动跟踪:

importcv2importnumpyasnp# 读取视频文件cap=cv2.VideoCapture('test.avi')# Shi-Tomasi角点检测参数配置feature_params=dict(maxCorners=100,# 设置检测的最大角点数量qualityLevel=0.3,# 角点质量阈值,值越小检测到的角点越多minDistance=7# 角点间的最小像素距离,避免角点过于密集)# Lucas-Kanade光流法参数配置lk_params=dict(winSize=(15,15),# 搜索窗口大小,较大的窗口能处理更大的运动maxLevel=2# 金字塔层数,用于处理不同尺度下的运动)# 生成随机颜色用于绘制不同轨迹color=np.random.randint(0,255,(100,3))# 读取视频第一帧并转换为灰度图ret,old_frame=cap.read()old_gray=cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY)# 检测初始角点作为跟踪起点p0=cv2.goodFeaturesToTrack(old_gray,mask=None,**feature_params)# 创建与视频帧大小相同的黑色画布,用于绘制轨迹mask=np.zeros_like(old_frame)# 主循环:逐帧处理视频whileTrue:ret,frame=cap.read()ifnotret:break# 当前帧转换为灰度图frame_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)# 计算光流:追踪p0点在当前帧中的新位置p1,st,err=cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)# 筛选跟踪成功的点(状态为1表示跟踪成功)good_new=p1[st==1]good_old=p0[st==1]# 绘制运动轨迹fori,(new,old)inenumerate(zip(good_new,good_old)):a,b=new.ravel()# 当前帧中的点坐标c,d=old.ravel()# 上一帧中的点坐标a,b,c,d=int(a),int(b),int(c),int(d)# 在掩模上绘制连接线,显示运动路径mask=cv2.line(mask,(a,b),(c,d),color[i].tolist(),2)# 在当前帧上标记角点位置cv2.circle(frame,(a,b),5,color[i].tolist(),-1)# 将轨迹叠加到当前帧上img=cv2.add(frame,mask)# 显示结果cv2.imshow('frame',img)# 更新前一帧数据和特征点old_gray=frame_gray.copy()p0=good_new.reshape(-1,1,2)# 检测ESC键退出k=cv2.waitKey(150)ifk==27:break# 释放资源cap.release()cv2.destroyAllWindows()

关键技术分析

Shi-Tomasi角点检测

  • maxCorners:控制检测角点的最大数量,平衡精度和性能
  • qualityLevel:决定角点质量的阈值,值越小检测越敏感
  • minDistance:确保角点分布均匀,避免聚集

Lucas-Kanade光流法

  • winSize:搜索窗口大小,影响运动检测的敏感度
  • maxLevel:图像金字塔层数,用于处理多尺度运动

二、基于深度学习的艺术风格迁移

OpenCV的dnn模块支持加载预训练的深度学习模型,实现艺术风格转换:

importcv2# 读取并调整输入图像大小image=cv2.imread(r"picture_1.jpg")image=cv2.resize(image,None,fx=0.5,fy=0.5)# 显示原始图像cv2.imshow('yuan tu',image)cv2.waitKey(0)# 获取图像尺寸(h,w)=image.shape[:2]# 图像预处理:创建神经网络输入格式blob=cv2.dnn.blobFromImage(image,# 输入图像scalefactor=1,# 像素值缩放因子size=(w,h),# 输出blob的尺寸mean=(0,0,0),# 各通道的均值(不进行均值减法)swapRB=False,# 不交换R和B通道(OpenCV使用BGR格式)crop=False# 不进行裁剪)# 加载预训练的艺术风格模型# 支持多种框架格式:Caffe、TensorFlow、PyTorch、Darknet等net=cv2.dnn.readNet(r'model\starry_night.t7')# PyTorch格式的星空风格模型# 设置网络输入net.setInput(blob)# 前向传播:获得风格化输出out=net.forward()# 输出数据处理:四维转三维out_new=out.reshape(out.shape[1],out.shape[2],out.shape[3])# 数据归一化到[0,1]范围cv2.normalize(out_new,out_new,norm_type=cv2.NORM_MINMAX)# 调整维度顺序:CHW → HWCresult=out_new.transpose(1,2,0)# 显示风格化结果cv2.imshow('Stylized Image',result)cv2.waitKey(0)cv2.destroyAllWindows()

blobFromImage函数详解

cv2.dnn.blobFromImage()是将图像转换为神经网络输入格式的关键函数:

  • scalefactor:每个像素值的缩放倍数,常用于数据归一化
  • size:指定输出blob的宽度和高度,通常与网络输入层匹配
  • mean:各通道的均值,用于均值减法(数据标准化)
  • swapRB:OpenCV使用BGR格式,而大多数模型使用RGB,此参数控制是否交换通道
  • crop:是否在调整大小后进行中心裁剪

三、实时目标跟踪

OpenCV提供多种跟踪算法,CSRT跟踪器在准确性和速度之间取得良好平衡:

importcv2# 创建CSRT跟踪器实例tracker=cv2.TrackerCSRT_create()# 跟踪状态标志tracking=False# 打开摄像头cap=cv2.VideoCapture(0)whileTrue:# 读取摄像头帧ret,frame=cap.read()ifnotret:break# 按下's'键开始跟踪,选择ROI区域ifcv2.waitKey(1)==ord('s'):tracking=True# 交互式选择跟踪区域roi=cv2.selectROI('Tracking',frame,showCrosshair=False)# 初始化跟踪器tracker.init(frame,roi)# 如果正在跟踪,更新跟踪器位置iftracking:success,box=tracker.update(frame)ifsuccess:# 提取边界框坐标x,y,w,h=[int(v)forvinbox]# 绘制跟踪框cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)# 显示跟踪结果cv2.imshow('Tracking',frame)# 按下ESC键退出ifcv2.waitKey(1)==27:break# 释放资源cap.release()cv2.destroyAllWindows()

跟踪器工作流程

  1. 初始化阶段:用户通过鼠标选择感兴趣区域(ROI)
  2. 跟踪阶段:跟踪器根据目标的纹理、颜色等特征在后续帧中定位目标
  3. 更新阶段tracker.update()返回跟踪状态和边界框坐标

四、多风格实时艺术滤镜

将摄像头画面分割为四个区域,分别应用不同的艺术风格:

importcv2importnumpyasnpimportthreadingfromqueueimportQueue# 加载四种不同的艺术风格模型defload_models():models=[cv2.dnn.readNet(r'model\starry_night.t7'),# 梵高星空风格cv2.dnn.readNet(r'model\candy.t7'),# 糖果风格cv2.dnn.readNet(r'model\composition_vii.t7'),# 康定斯基风格cv2.dnn.readNet(r'model\la_muse.t7')# 缪斯风格]returnmodels# 对单个图像块应用风格迁移defapply_style(image_block,model):(h,w)=image_block.shape[:2]# 图像预处理blob=cv2.dnn.blobFromImage(image_block,scalefactor=1.0,size=(w,h),mean=(0,0,0),swapRB=False,crop=False)# 模型推理model.setInput(blob)out=model.forward()# 后处理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)result=np.uint8(result*255)# 转换为8位图像returnresult# 并行处理器类:使用多线程加速处理classStyleProcessor:def__init__(self,models):self.models=models self.results=[None]*4defprocess_block(self,block_idx,block,model):result=apply_style(block,model)self.results[block_idx]=resultdefprocess_all_blocks(self,blocks):threads=[]foriinrange(4):# 为每个区域创建独立线程thread=threading.Thread(target=self.process_block,args=(i,blocks[i],self.models[i]))threads.append(thread)thread.start()# 等待所有线程完成forthreadinthreads:thread.join()returnself.results# 主函数(优化版本)defmain_optimized():# 初始化模型和处理器models=load_models()processor=StyleProcessor(models)# 设置摄像头cap=cv2.VideoCapture(0)cap.set(cv2.CAP_PROP_FRAME_WIDTH,640)cap.set(cv2.CAP_PROP_FRAME_HEIGHT,480)print("按ESC键退出程序...")whileTrue:ret,frame=cap.read()ifnotret:break# 统一图像尺寸frame=cv2.resize(frame,(640,480))height,width=frame.shape[:2]# 计算分割点mid_h,mid_w=height//2,width//2# 将画面分割为四个区域blocks=[frame[0:mid_h,0:mid_w],# 左上区域frame[0:mid_h,mid_w:width],# 右上区域frame[mid_h:height,0:mid_w],# 左下区域frame[mid_h:height,mid_w:width]# 右下区域]# 并行处理四个区域styled_blocks=processor.process_all_blocks(blocks)# 创建输出画布output_frame=np.zeros_like(frame)# 拼接处理后的区域output_frame[0:mid_h,0:mid_w]=styled_blocks[0]output_frame[0:mid_h,mid_w:width]=styled_blocks[1]output_frame[mid_h:height,0:mid_w]=styled_blocks[2]output_frame[mid_h:height,mid_w:width]=styled_blocks[3]# 绘制区域分割线cv2.line(output_frame,(mid_w,0),(mid_w,height),(255,255,255),2)cv2.line(output_frame,(0,mid_h),(width,mid_h),(255,255,255),2)# 显示多风格画面cv2.imshow('Multi-Style Camera View',output_frame)ifcv2.waitKey(1)&0xFF==27:break# 清理资源cap.release()cv2.destroyAllWindows()if__name__=="__main__":main_optimized()

多线程优化策略

  1. 区域分割:将摄像头画面均匀分为四个独立区域
  2. 并行处理:每个区域使用独立线程应用不同的风格模型
  3. 结果拼接:将处理后的区域重新组合为完整画面

性能优化技巧

  • 降低分辨率:减小处理数据量,提高实时性
  • 多线程处理:充分利用多核CPU并行计算
  • 模型选择:选择轻量级模型或优化模型大小
  • 帧率控制:可适当降低处理帧率,平衡质量和速度

这些代码示例展示了OpenCV在计算机视觉领域的多样化应用,从传统的运动跟踪到基于深度学习的艺术创作,体现了计算机视觉技术的强大功能和广泛应用前景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 7:54:11

实测对比5款模型,VibeThinker-1.5B-WEBUI性价比最高

实测对比5款模型,VibeThinker-1.5B-WEBUI性价比最高 你有没有试过:为解一道AIME代数题卡住两小时,翻遍资料仍找不到清晰推导路径;或者在LeetCode上反复调试动态规划状态转移方程,却始终差一个边界条件?更现…

作者头像 李华
网站建设 2026/4/23 7:56:29

Chandra OCR入门指南:Streamlit交互界面使用技巧与常见问题解决

Chandra OCR入门指南:Streamlit交互界面使用技巧与常见问题解决 1. 为什么你需要Chandra OCR 你有没有遇到过这样的场景:手头有一堆扫描版的合同、数学试卷、带表格的财务报表,或者一页页PDF格式的学术论文,想把它们变成可编辑、…

作者头像 李华
网站建设 2026/4/23 9:19:41

Hunyuan-MT-7B部署教程:vLLM显存优化技巧让7B模型在24G GPU运行

Hunyuan-MT-7B部署教程:vLLM显存优化技巧让7B模型在24G GPU运行 1. Hunyuan-MT-7B模型快速认识 Hunyuan-MT-7B是腾讯混元团队推出的开源翻译大模型,专为高质量多语言互译设计。它不是简单套用通用大模型做翻译,而是从训练范式、架构设计到推…

作者头像 李华
网站建设 2026/4/23 2:29:29

PyTorch-2.x-Universal-Dev-v1.0功能全解析,小白也能看懂

PyTorch-2.x-Universal-Dev-v1.0功能全解析,小白也能看懂 你是不是也经历过这样的困扰:每次想开始一个深度学习项目,光是环境配置就要折腾半天?装PyTorch版本不对、CUDA驱动不匹配、依赖包冲突、源速度慢得像蜗牛……好不容易配好…

作者头像 李华