摄像头文档识别与透视变化技术和背景建模技术(追踪)
目录
一.摄像头文档识别与透视变化技术
1. 文档识别与透视变换技术方案
2. 与传统OCR的区别
3.代码步骤
①读取输入,确保摄像头是可以打开的状态
②循环读取每一帧,再对每一帧图片操作
做一些图片的预处理
轮廓检测
遍历轮廓,当四个点的时候就吧flag设置成1,方便后续是否透视变换的判断
透视变换
③释放资源
二背景建模技术
1.背景建模技术介绍
2.基于混合高斯模型的实现原理
3.后处理与优化技术
4.代码步骤
①读取视频文件
②创建一个卷积核
③创建混合高斯模型,用于背景建模
④循环对对视频每一帧操作
读取每一帧
利用前面的高斯混合模型对象对输入帧进行背景与前景分离,输出前景掩码,返回一个单通道的灰度图像(掩码),直观展示前景区域
寻找视频中的轮廓通过周长判断是不是人行轮廓再画出外接矩形
设置帧的刷新的速度60ms,如果按下esc键则推出
⑤释放资源
一.摄像头文档识别与透视变化技术
1. 文档识别与透视变换技术方案
- 功能定位: 该技术并非传统意义上的OCR,其核心在于通过对摄像头实时捕捉的画面进行处理,自动识别特定的文档(如A4纸、车票等),并将其进行透视变换,修正其上歪斜的状态,最终以便于后续的字符识别。
- 实现原理: 技术流程主要包括以下步骤:
- 在主循环中,通过摄像头读取视频帧。
- 将图像转为灰度图,并使用Canny边缘检测和KNN算法找出文档轮廓。
- 通过面积大小筛选出疑似文档区域的前三个最大轮廓。
- 利用轮廓近似(reshape)尝试将筛选出的轮廓转换为四个角点坐标。
- 当成功近似并确认其为有效文档且面积足够大时,触发透视变换。
- 应用形态学处理(如二值化)提升图像清晰度,为后续OCR提取做准备。
2. 与传统OCR的区别
- 只是一个文档识别和图像预处理的基础工具。真正的OCR功能(即从图片中提取可复制的文字)需要在此基础上进一步集成。
3.代码步骤
①读取输入,确保摄像头是可以打开的状态
#读取输入
cap=cv2.VideoCapture(0)#确保摄像头是可以启动的状态
if not cap.isOpened():print('Cannot open camera')exit()
②循环读取每一帧,再对每一帧图片操作
- 在主循环中,通过摄像头读取视频帧。
while True:flag=0#用于标识是否检测到文档ret,image=cap.read()#如果正确读取帧,ret为Trueorig=image.copy()if not ret:print('不能读取摄像头')breakcv_show('image',image)
做一些图片的预处理
- 将图像转为灰度图,并使用Canny边缘检测和KNN算法找出文档轮廓。
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#预处理gray=cv2.GaussianBlur(gray,(5,5),0)#高斯滤波eddged=cv2.Canny(gray,15,45)cv_show('1',eddged)
轮廓检测
- 通过面积大小筛选出疑似文档区域的前三个最大轮廓。
#轮廓检测cnts=cv2.findContours(eddged,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]cnts=sorted(cnts,key=cv2.contourArea,reverse=True)[:3]image_contours=cv2.drawContours(image,cnts,-1,(0,255,0),2)cv_show('image_contours',image_contours)
遍历轮廓,当四个点的时候就吧flag设置成1,方便后续是否透视变换的判断
利用轮廓近似(reshape)尝试将筛选出的轮廓转换为四个角点坐标。
当成功近似并确认其为有效文档且面积足够大时,触发透视变换。
#遍历轮廓for c in cnts:#计算轮廓近似:peri=cv2.arcLength(c,True)approx=cv2.approxPolyDP(c,0.05*peri,True)area=cv2.contourArea(approx)#四个点的时候就拿出来if area>20000 and len(approx)==4:screenCnt=approxflag=1print(peri,area)print('检测到文件')break
透视变换
if flag==1:#展示成果image_contours=cv2.drawContours(image,[screenCnt],0,(0,255,0),2)cv_show('image',image_contours)#透视变换warped=four_point_transform(orig,screenCnt.reshape(4,2))cv_show('warped',warped)warped=cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)ref=cv2.threshold(warped,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]cv_show('ref',ref)
③释放资源
cap.release()#释放捕捉器
cv2.destroyAllWindows()
用到的自定义方法:
def cv_show(name,img):cv2.imshow(name,img)cv2.waitKey(100)
def order_points(pts):rect=np.zeros((4,2),dtype='float32')#按顺序找到对应坐标0123即左上右上右下左下s=pts.sum(axis=1)#每行求和rect[0]=pts[np.argmin(s)]rect[2]=pts[np.argmax(s)]diff=np.diff(pts,axis=1)#每行求差rect[1]=pts[np.argmin(diff)]rect[3]=pts[np.argmax(diff)]return rect
def four_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)#M是获取到的转换之间的关系warped=cv2.warpPerspective(image,M,(maxWidth,maxHeight))#返回变换后结果return warped
二背景建模技术
1.背景建模技术介绍
- 背景建模旨在从视频流中将静态背景与动态前景(如行人)进行分离。
- 该技术有多种实现方法,本次主要探讨了基于混合高斯模型的方法。
- 应用场景包括目标检测、物体跟踪等。
2.基于混合高斯模型的实现原理
- 通过创建一个混合高斯模型来学习场景的背景分布。
- 对每一帧画面输入模型,模型会输出一个前景/背景掩码图(fg_mask),其中运动物体被标记为白色,背景为黑色。
3.后处理与优化技术
- 去噪: 使用开运算(腐蚀后膨胀)处理掩码图,以消除因环境因素(如风吹动树叶)导致的噪点。
- 轮廓筛选: 使用
findContours()
函数获取所有轮廓,并通过设定轮廓周长阈值(如大于188)来过滤掉小的噪点或无效轮廓(如彩带),只保留大面积的人体
4.代码步骤
①读取视频文件
import cv2
video=cv2.VideoCapture('test.avi')
②创建一个卷积核
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
③创建混合高斯模型,用于背景建模
#创建混合高斯模型,用于背景建模
fgbg=cv2.createBackgroundSubtractorMOG2()
④循环对对视频每一帧操作
读取每一帧
while True:ret,frame=video.read()if not ret:breakcv2.imshow('frame',frame)
利用前面的高斯混合模型对象对输入帧进行背景与前景分离,输出前景掩码,返回一个单通道的灰度图像(掩码),直观展示前景区域
开运算去除噪声点
fgmask=fgbg.apply(frame)#视频处理, 对输入帧进行背景与前景分离,输出前景掩码,返回一个单通道的灰度图像(掩码),直观展示前景区域fgmask_new=cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)#开运算去噪点cv2.imshow('fgmask_new',fgmask_new)
寻找视频中的轮廓通过周长判断是不是人行轮廓再画出外接矩形
#寻找是视频中的轮廓_,contours,h=cv2.findContours(fgmask_new,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE,)for c in contours:perimeter=cv2.arcLength(c,True)if perimeter>188:#找到一个直矩形x,y,w,h=cv2.boundingRect(c)#画出这个矩形fgmask_new_rect=cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)cv2.imshow('fgmask_new_rect',fgmask_new_rect)
设置帧的刷新的速度60ms,如果按下esc键则推出
k=cv2.waitKey(60)if k==27:break
⑤释放资源
video.release()
cv2.destroyAllWindows()