目录
一、摄像头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、定义展示图像函数
python
import numpy as np
import cv2
def cv_show(name,img):
cv2.imshow(name,img)
# cv2.waitKey(60)
2、定义自动缩放图片大小函数
python
# 调整图像高宽,保持图像宽高比不变
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 image
if 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、定义轮廓点的排序函数
python
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、定义透视变换函数
python
# 将透视扭曲的矩形变换成一个规则的矩阵
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
5、打开相应摄像头
python
import cv2
cap = cv2.VideoCapture(0) # 确保摄像头是可以启动的状态
if not cap.isOpened(): # 打开失败
print("Cannot open camera")
exit()
6、建立整体循环结构
python
while True:
flag = 0 # 用于标识 当前是否检测到文档
ret,image = cap.read() # 从摄像头读取每一帧图像,如果正确读取帧,ret为True,image为读取到的帧图像
orig = image.copy() # 对每一帧做副本
if not ret: # 读取失败,则退出循环
print("不能读取摄像头")
break
cv_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终止循环
break
for 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 # 将筛选出来的近似多边形赋值给screenCnt
flag = 1 # 将上述设置的旗帜设置为1
print(peri, area) # 打印识别出来的轮廓周长和轮廓面积
print('检测到文档')
break
if 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创建的窗口