news 2026/6/15 8:54:03

OpenCV 学习:文档扫描与视频运动检测与跟踪

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenCV 学习:文档扫描与视频运动检测与跟踪

文章目录

    • 一、文档扫描与实时矫正
      • 1.1 核心思路
      • 1.2 关键代码分析
    • 二、视频运动检测与跟踪
      • 2.1 核心思路
      • 2.2 关键代码分析
    • 三、特定物体提取与分割
      • 3.1 核心思路
      • 3.2 关键代码分析

一、文档扫描与实时矫正

1.1 核心思路

通过摄像头实时捕捉图像,自动检测文档轮廓,并进行透视变换将其矫正为正面视角。整个过程包含以下步骤:

  1. 图像采集与预处理
  2. 边缘检测
  3. 轮廓查找与筛选
  4. 透视变换矫正
  5. 二值化处理

1.2 关键代码分析

# 图像显示函数defcv_show(name,img):"""显示图像"""cv2.imshow(name,img)cv2.waitKey(1)# 使用1ms等待,适合视频流

参数说明:

  • name:显示窗口的名称
  • img:要显示的图像矩阵
  • waitKey(1):等待1毫秒,适合视频流的连续显示
# 坐标点排序函数deforder_points(pts):# 一共4个坐标点rect=np.zeros((4,2),dtype="float32")# 用来存储排序之后的坐标位置# 按顺序找到对应坐标0123分别是:左上、右上、右下、左下s=pts.sum(axis=1)# 对pts矩阵的每一行进行求和操作。(x+y)rect[0]=pts[np.argmin(s)]rect[2]=pts[np.argmax(s)]diff=np.diff(pts,axis=1)# 对pts矩阵的每一行进行求差操作。(y-x)rect[1]=pts[np.argmin(diff)]rect[3]=pts[np.argmax(diff)]returnrect

功能说明:
这个函数将检测到的四个角点按照"左上、右上、右下、左下"的顺序排列,为后续的透视变换提供正确的坐标顺序。

# 透视变换函数deffour_point_transform(image,pts):# 获取输入坐标点rect=order_points(pts)(tl,tr,br,bl)=rect# 计算输入的w和h值widthA=np.sqrt(((br[0]-bl[0])**2)+((br[1]-bl[1])**2))widthB=np.sqrt(((tr[0]-tl[0])**2)+((tr[1]-tl[1])**2))maxWidth=max(int(widthA),int(widthB))heightA=np.sqrt(((tr[0]-br[0])**2)+((tr[1]-br[1])**2))heightB=np.sqrt(((tl[0]-bl[0])**2)+((tl[1]-bl[1])**2))maxHeight=max(int(heightA),int(heightB))# 变换后对应坐标位置dst=np.array([[0,0],[maxWidth-1,0],[maxWidth-1,maxHeight-1],[0,maxHeight-1]],dtype="float32")# 透视变换矩阵M=cv2.getPerspectiveTransform(rect,dst)warped=cv2.warpPerspective(image,M,(maxWidth,maxHeight))returnwarped

关键函数分析:

  • cv2.getPerspectiveTransform(rect, dst):计算透视变换矩阵
    • rect:原始图像的四个点坐标
    • dst:目标图像的四个点坐标
  • cv2.warpPerspective():应用透视变换
    • image:输入图像
    • M:变换矩阵
    • (maxWidth, maxHeight):输出图像尺寸
# 图像预处理与轮廓检测gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)# 转换为灰度图gray=cv2.GaussianBlur(gray,ksize=(5,5),sigmaX=0)# 高斯滤波edged=cv2.Canny(gray,15,45)# Canny边缘检测# 轮廓检测cnts=cv2.findContours(edged,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]cnts=sorted(cnts,key=cv2.contourArea,reverse=True)[:3]

参数说明:

  • GaussianBlur():高斯模糊,减少噪声
    • ksize=(5,5):高斯核大小
    • sigmaX=0:X方向标准差
  • Canny():边缘检测
    • 15:低阈值
    • 45:高阈值
  • findContours():查找轮廓
    • RETR_EXTERNAL:只检测外轮廓
    • CHAIN_APPROX_SIMPLE:压缩轮廓点
# 轮廓近似与筛选forcincnts:peri=cv2.arcLength(c,True)# 计算轮廓周长approx=cv2.approxPolyDP(c,0.05*peri,True)# 轮廓近似area=cv2.contourArea(approx)ifarea>40000andlen(approx)==4:screenCnt=approx flag=1break

函数分析:

  • arcLength():计算轮廓周长
    • c:轮廓点集
    • True:轮廓是否闭合
  • approxPolyDP():多边形近似
    • 0.05*peri:近似精度(周长百分比)
    • True:轮廓是否闭合

二、视频运动检测与跟踪

2.1 核心思路

通过分析视频帧间的差异来检测运动物体,主要包含:

  1. 背景建模与前景提取
  2. 形态学处理去除噪声
  3. 轮廓检测与目标框选

2.2 关键代码分析

# 创建结构元素kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,ksize=(3,3))

参数说明:

  • MORPH_CROSS:十字形结构元素
  • ksize=(3,3):核大小为3×3
# 创建背景减除模型fgbg=cv2.createBackgroundSubtractorMOG2()

功能说明:
创建混合高斯背景模型,用于分离前景(运动物体)和背景。

# 应用背景减除fgmask=fgbg.apply(frame)# 获取前景掩码

工作流程:

  1. 模型学习视频的背景
  2. 将当前帧与背景模型比较
  3. 提取出运动的前景物体
# 形态学开运算fgmask_new=cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)

功能说明:

  • MORPH_OPEN:开运算(先腐蚀后膨胀)
  • 作用:去除小的噪声点,平滑前景区域
# 轮廓查找与框选contours=cv2.findContours(fgmask_new,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]forcincontours:perimeter=cv2.arcLength(c,True)ifperimeter>188:x,y,w,h=cv2.boundingRect(c)frame_rect=cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)

函数分析:

  • boundingRect():计算轮廓的外接矩形
  • rectangle():绘制矩形框
    • (0,255,0):绿色(BGR格式)
    • 2:线宽

三、特定物体提取与分割

3.1 核心思路

从图像中提取特定物体(扇子),主要步骤:

  1. 图像预处理(缩放、旋转)
  2. 边缘检测
  3. 轮廓查找与掩码生成
  4. 物体提取

3.2 关键代码分析

# 图像尺寸调整与旋转img_resized=cv2.resize(img,(640,480))img_rotated=cv2.rotate(img_resized,cv2.ROTATE_90_COUNTERCLOCKWISE)

参数说明:

  • resize():调整图像尺寸
  • ROTATE_90_COUNTERCLOCKWISE:逆时针旋转90度
# 边缘检测gray=cv2.cvtColor(img_rotated,cv2.COLOR_BGR2GRAY)edges=cv2.Canny(gray,threshold1=50,threshold2=150)

Canny参数:

  • threshold1=50:低阈值,低于此值的边缘被丢弃
  • threshold2=150:高阈值,高于此值的边缘被保留
# 轮廓查找与掩码生成contours=cv2.findContours(edges,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]mask=np.zeros_like(gray)ifcontours:contour_areas=[cv2.contourArea(cnt)forcntincontours]max_area_idx=np.argmax(contour_areas)max_contour=contours[max_area_idx]cv2.drawContours(mask,[max_contour],-1,(255),thickness=cv2.FILLED)# 形态学闭运算kernel=np.ones((5,5),np.uint8)mask=cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel)

功能说明:

  1. 查找所有轮廓
  2. 选择面积最大的轮廓(假设为扇子)
  3. 绘制填充轮廓作为掩码
  4. 闭运算填充空洞
# 物体提取mask_3ch=cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR)extracted=cv2.bitwise_and(img_rotated,mask_3ch)

位运算:

  • bitwise_and():按位与操作
  • 作用:使用掩码提取原图中的对应区域
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/30 1:09:07

2026年8款降AI率工具实测,毕业党闭眼入这款

2026年8款降AI率工具实测,毕业党闭眼入这款 试了8款降AI工具,踩坑无数,最后锁定2个:嘎嘎降AI和比话降AI。 先说结论:日常用嘎嘎降AI(www.aigcleaner.com),4.8元/千字,达…

作者头像 李华
网站建设 2026/6/15 0:47:41

RAG不是魔法,是工程:从知识库到企业部署的硬核实践

前言 大模型热潮席卷技术圈,但真正将其用于企业生产环境的人很快会发现:开箱即用的聊天机器人远不能满足业务需求。模型会胡说八道,回答不了昨天刚发布的新政策,更不敢把客户合同上传到公有云API。这时候,RAG&#xf…

作者头像 李华
网站建设 2026/6/14 22:01:51

为什么几乎所有大厂,都在选 Go ?

沉默是金,总会发光大家好,我是沉默这几年,你会发现一个非常明显的趋势:腾讯、美团、滴滴、百度字节跳动(早期 Python,如今全面 Go 化)Google、bilibili……国内外头部互联网公司,几乎…

作者头像 李华
网站建设 2026/6/9 18:51:27

10.BTC-分叉-北大肖臻老师客堂笔记

北京大学肖臻老师《区块链技术与应用》公开课第 10 讲的主题是**“比特币的分叉:硬分叉与软分叉”**。这节课非常重要,因为它解释了在去中心化系统中,当协议(规则)发生升级时,网络是如何达成共识&#xff0…

作者头像 李华
网站建设 2026/6/13 13:10:28

智能包装行业发展趋势下,如何提高竞争力?

在当前快速发展的智能包装行业中,中科天工包装技术正在利用其技术优势积极布局市场。通过研发更高效的智能包装设备,中科天工致力于满足不断变化的市场需求。公司在技术创新上持续投入,推出具备自动化和智能管理功能的设备。这些设备不仅提升…

作者头像 李华