目录
一、摄像头OCR
1、含义
2、一般操作步骤
1)安装OpenCV库
2)设置摄像头
3)图像采集
4)图像预处理
5)文本识别
6)文本处理
7)结果显示
二、案例实现
1、定义展示图像函数
2、定义自动缩放图片大小函数
3、定义轮廓点的排序函数
4、定义透视变换函数
5、打开相应摄像头
6、建立整体循环结构
7、执行上述代码
一、摄像头OCR
1、含义
OpenCV摄像头OCR是一个使用OpenCV库和OCR技术实现的工具,它可以通过摄像头实时读取图像,然后利用OCR(光学字符识别)技术将图像中的文本内容提取出来。这个工具可以应用于各种场景,例如扫描身份证、识别车牌号、读取条形码等。使用OpenCV摄像头OCR,可以方便地在实时图像中进行文本识别和处理。
2、一般操作步骤
1)安装OpenCV库
首先需要安装OpenCV库,这是一个开源的计算机视觉库,提供了许多图像处理和分析的功能。
2)设置摄像头
将摄像头与计算机连接,并通过OpenCV库进行初始化和设置,以确保能够实时获取摄像头图像。
3)图像采集
通过调用OpenCV库提供的函数,从摄像头中获取图像帧,并将其存储为图像对象。
4)图像预处理
对采集到的图像进行预处理,以提高后续的OCR识别效果。可能的预处理包括图像灰度化、二值化、降噪等。
5)文本识别
使用OCR技术对预处理后的图像进行文本识别。这可以使用OCR引擎,如Tesseract进行,也可以使用第三方OCR服务。
6)文本处理
对识别出的文本进行必要的后处理,例如去除空格、提取特定格式的信息等。
7)结果显示
将识别和处理后的文本结果显示在图像或图形用户界面上,以便用户查看和使用。
二、案例实现
1、定义展示图像函数
import numpy as np
import cv2def cv_show(name,img):cv2.imshow(name,img)# cv2.waitKey(60)
2、定义自动缩放图片大小函数
# 调整图像高宽,保持图像宽高比不变
def resize(image,width=None,height=None ,inter=cv2.INTER_AREA): # 输入参数为图像、可选宽度、可选高度、插值方式默认为cv2.INTER_AREA,即面积插值dim = None # 存储计算后的目标尺寸w、h(h,w) = image.shape[:2] # 返回输入图像高宽if width is None and height is None: # 判断是否指定了宽和高大小,如果没有指定则返回原图return imageif width is None: # 判断如果没有指定宽度大小,则表示指定了高度大小,那么运行内部代码r = height/float(h) # 指定高度与原图高度的比值dim = (int(w*r),height) # 宽度乘以比值得到新的宽度,此处得到新的宽高else: # 此处表示为width不是None,即指定了宽度,与上述方法一致,计算比值r = width/float(w)dim = (width,int(h*r))resized = cv2.resize(image,dim,interpolation=inter) # 指定图像大小为上述的dim,inter默认为cV2.INTER_AREA,即面积插值,适用于缩放图像。return resized
3、定义轮廓点的排序函数
def order_points(pts): # 对输入的四个点按照左上、右上、右下、左下进行排序rect = np.zeros((4,2),dtype='float32') # 创建一个4*2的数组,用来存储排序之后的坐标位置# 按顺序找到对应坐标0123分别是左上、右上、右下、左下s = pts.sum(axis=1) # 对pts矩阵的每个点的x y相加rect[0] = pts[np.argmin(s)] # np.argmin(s)表示数组s中最小值的索引,表示左上的点的坐标rect[2] = pts[np.argmax(s)] # 返回最大值索引,即右下角的点坐标diff = np.diff(pts,axis=1) # 对pts矩阵的每一行的点求差值rect[1] = pts[np.argmin(diff)] # 差值最小的点为右上角点rect[3] = pts[np.argmax(diff)] # 差值最大表示左下角点return rect # 返回排序好的四个点的坐标
4、定义透视变换函数
# 将透视扭曲的矩形变换成一个规则的矩阵
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) # 根据原始点和变换后的点计算透视变换矩阵Mwarped = cv2.warpPerspective(image,M,(maxWidth,maxHeight)) # 对原始图像,针推变换矩阵和输出图像大小进行透视变换,返回变换后的图片# 返回变换后的结果return warped
5、打开相应摄像头
import cv2
cap = cv2.VideoCapture(0) # 确保摄像头是可以启动的状态
if not cap.isOpened(): # 打开失败print("Cannot open camera")exit()
6、建立整体循环结构
while True:flag = 0 # 用于标识 当前是否检测到文档ret,image = cap.read() # 从摄像头读取每一帧图像,如果正确读取帧,ret为True,image为读取到的帧图像orig = image.copy() # 对每一帧做副本if not ret: # 读取失败,则退出循环print("不能读取摄像头")breakcv_show("image",image) # 展示读取到的帧画面gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # 图像处理,转换为灰度图gray = cv2.GaussianBlur(gray,(5,5), 0) # 高斯滤波减少图像中的噪点edged = cv2.Canny(gray,75,200) # 使用canny边缘检测算法检测图像边缘cv_show('1',edged)# 对进行处理过的图像做副本,然后进行轮廓检测,cv2.RETR_EXTERNAL表示只检测最外层轮廓,cv2.CHAIN_APPROX_SIMPLE表示只保存轮廓端点坐标,返回轮廓点的集合列表cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]# 对轮廓点进行排序,排序方式为轮廓面积的大小,以降序排列cnts = sorted(cnts,key=cv2.contourArea,reverse=True)[:3]image_contours = cv2.drawContours(image, cnts, -1, (0, 255, 0),2) # 在原图上绘制轮廓,-1表示绘制所有轮廓cv_show( "image_contours", image_contours)k = cv2.waitKey(60)if k == 27: # esc键的asc码为27,点击esc终止循环breakfor c in cnts: # 遍历每一幅轮廓的描述信息# 计算轮廓近似peri = cv2.arcLength(c,True) # 其计算轮蹦的周长,True表示封闭图像# c表示输入的点集# epsilon表示从原始轮到近似轮的最大距离,它是一个准确度参数approx = cv2.approxPolyDP(c,0.05 * peri, True) # 轮廓近似,对待逼近的轮廓c进行多边形逼近,逼近的精度为0.05*peri,即周长的5%area = cv2.contourArea(approx) # 计算逼近的多边形轮廓面积# 4个点的时候就拿出来if area > 20000 and len(approx) == 4: # 筛选轮廓面积大于20000,近似多边形四个顶点,认为检测到了文档screenCnt = approx # 将筛选出来的近似多边形赋值给screenCntflag = 1 # 将上述设置的旗帜设置为1print(peri, area) # 打印识别出来的轮廓周长和轮廓面积print('检测到文档')breakif flag == 1: # 如果检测到文档# 展示结果# print("STEP 2:获取轮骤")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,220,255,cv2.THRESH_BINARY)[1]# ref = cv2.threshold(warped,0, 255, CV2.THRESH BINARY | CV2.THRESH OTSU)[1]cv_show("ref",ref)cap.release() # 释放捕获器,释放摄像头资源
cv2.destroyAllWindows() # 关闭所有OpenCV创建的窗口