OpenCv高阶(八)——摄像头调用、摄像头OCR

文章目录


前言

摄像头 OCR 是指利用摄像头采集图像信息,然后通过光学字符识别(OCR)技术对图像中的文字进行识别和处理的一种技术手段。

一、摄像头调用通用方法

1、导入必要的库

python 复制代码
import cv2
import numpy as np

2、创建摄像头接口

读取本地的视频文件或者摄像头,接收的参数为视频文件的地址,或者摄像头的名称(一般0指的是电脑自身的摄像头,1则是外接的摄像头)

python 复制代码
video_capture=cv2.VideoCapture('../data/test.avi')

#判断视频文件或者摄像头是否正常读取,如果读取失败则返回提示信息
if not  video_capture.isOpened():
    print("视频打开失败")
    exit()
   

视频以及摄像头文件我们都可以把它理解成老式的电影,一段视频以及摄像头读取的画面都可以看成是一张图片一张图片的播放,只是视频和摄像头的播放速度很快,导致我们视觉上认为动作是连贯的,帧率也就是一秒播放多少张图片。

因此,在使用opencv读取摄像头和视频文件时我们采用循环的方法来不断获取摄像头读取的画面。

当我们要使用opencv来做视觉方向的问题时,我们就可以调用摄像头,对对读取到的每一帧画面做视觉方面的处理,来达到与摄像头结合的动态效果。

python 复制代码
while True:
    ret,frame=video_capture.read()
	#ret是一个标志,检测摄像头是否读取成功,frame则是接收到的画面,是一张一张的图片
	
    if not ret:
        break
	
	#设置这个if判断,是为了手动控制跳出循环,当我们按下ESC键时跳出循环停止读取画面。
    if cv2.waitKey(100)==27:
        break

#释放摄像头资源
video_capture.release()
cv2.destroyAllWindows()

二、摄像头OCR

简单处理文字,将不正的文档扶正并使文档的字迹更清晰。

1.引入库

python 复制代码
import numpy as np
import cv2

2、定义函数

(1)定义显示opencv显示函数

python 复制代码
def cv_show(name,value):
    cv2.imshow(name,value)
    cv2.waitKey(50)

(2)保持宽高比的缩放函数

python 复制代码
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
	dim=None
    (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:
        r = width / float(w)    # 计算宽度缩放比例
        dim = (width, int(h * r))
    
    # 执行缩放操作
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

(3)坐标点排序函数

python 复制代码
def order_points(pts):
    rect = np.zeros((4, 2), dtype="float32")  # 初始化4x2矩阵
    #按顺序找到对应的坐标0123,分别是左上右上右下、左下
    # 计算坐标点x+y的和
    s = pts.sum(axis=1)  # 形状:(4,) ,对矩阵的每一行进行求和操作
    rect[0] = pts[np.argmin(s)]  # 左上角:x+y最小
    rect[2] = pts[np.argmax(s)]  # 右下角:x+y最大
    
    # 计算坐标点x-y的差
    diff = np.diff(pts, axis=1)  # 形状:(4,1)
    rect[1] = pts[np.argmin(diff)]  # 右上角:x-y最小(即y相对较大)
    rect[3] = pts[np.argmax(diff)]  # 左下角:x-y最大(即y相对较小)
    
    return rect  # 返回有序坐标:[左上, 右上, 右下, 左下]

(4) 四点透视变换实现

python 复制代码
def four_point_transform(image, pts):
    # 坐标排序(关键步骤!)
    rect = order_points(pts)
    (tl, tr, br, bl) = rect  # 解构赋值四个顶点
    
    # 计算输出图像的宽度(取两组对边最大值)
    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],          # 宽度方向预留1像素边界
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")
    
    # 计算透视变换矩阵(核心数学操作)
    M = cv2.getPerspectiveTransform(rect, dst)
    
    # 执行透视变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    return warped

3、读取摄像头显示摄像头画面并做灰度处理

python 复制代码
#读取输入
cap=cv2.VideoCapture(0)
if not cap.isOpened():
    print("摄像头打开失败")
    exit()

while True:
    flag=0  #是否检测到文档的标志
    ret,frame=cap.read()
    orig=frame.copy()
    if not ret: #读取失败则退出循环
        print("不能读取摄像头")
        break
    cv_show('iamge',frame)

    gray=cv2.cvtColor(frame,cv2.COLOR_BGRA2GRAY)

4、做中值滤波并使用canny边缘检测

python 复制代码
gray=cv2.medianBlur(gray,3)
edged=cv2.Canny(gray,75,200)
cv_show('i',edged)

中值滤波核大小 3 适用于720p分辨率

Canny阈值可改为自适应算法(如基于图像亮度百分比)

5、轮廓检测

python 复制代码
#轮廓检测
    cnts=cv2.findContours(edged,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]

    cnts=sorted(cnts,key=cv2.contourArea,reverse=True)[:3]# 取面积前三的轮廓
    image_contours=cv2.drawContours(orig,cnts,-1,(0,255,0),2) # 多边形近似
    cv_show('image_contours',image_contours)

RETR_EXTERNAL 只检测最外层轮廓(假设文档无嵌套)

面积阈值 20000 需根据摄像头分辨率调整(例如:1280x720下约为2%画面占比)

6、遍历轮廓

python 复制代码
 #遍历轮廓做透视变换
    for c in cnts:
        peri=cv2.arcLength(c,True)

        #做轮廓近似
        approx=cv2.approxPolyDP(c,0.01*peri,True)
        area=cv2.contourArea(approx)

        #做透视变换要求轮廓近似满足是4个点,挑选出符合要求的结果

        if area>20000 and len(approx)==4:
            screenCnt=approx
            flag=1  #标识找到了文档
            print(peri,area)
            print('检测到文档')
            break

7、透视变换

python 复制代码
if flag==1:

        image_contours=cv2.drawContours(frame,[screenCnt],0,(0,255,0),2)
        cv_show('image',image_contours)

        #左四点转换,扶正后的坐标

        warped=four_point_transform(orig,screenCnt.reshape(4,2))
        cv_show('warped',warped)
        
cap.release()
cv2.destroyAllWindows()

完整代码展示

python 复制代码
import numpy as np
import cv2

def cv_show(name,value):
    cv2.imshow(name,value)
    cv2.waitKey(50)


def resize(image,width=None,height=None,inter=cv2.INTER_AREA):

    dim=None
    (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:
        r=width/float(w)
        dim=(width,int(h*r))
    resized=cv2.resize(image,dim,interpolation=inter)
    return resized


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,0],[maxwidth,maxheight],[0,maxheight]],dtype='float32')

    M=cv2.getPerspectiveTransform(rect,dst)
    warped=cv2.warpPerspective(image,M,(maxwidth,maxheight))
    return warped

#读取输入
cap=cv2.VideoCapture(0)
if not cap.isOpened():
    print("摄像头打开失败")
    exit()

while True:
    flag=0  #是否检测到文档的标志
    ret,frame=cap.read()
    orig=frame.copy()
    if not ret: #读取失败则退出循环
        print("不能读取摄像头")
        break
    cv_show('iamge',frame)

    gray=cv2.cvtColor(frame,cv2.COLOR_BGRA2GRAY)

    gray=cv2.medianBlur(gray,3)
    edged=cv2.Canny(gray,75,200)

    cv_show('i',edged)

    #轮廓检测
    cnts=cv2.findContours(edged,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]

    cnts=sorted(cnts,key=cv2.contourArea,reverse=True)[:3]
    image_contours=cv2.drawContours(orig,cnts,-1,(0,255,0),2)
    cv_show('image_contours',image_contours)

    #遍历轮廓做透视变换
    for c in cnts:
        peri=cv2.arcLength(c,True)

        #做轮廓近似
        approx=cv2.approxPolyDP(c,0.01*peri,True)
        area=cv2.contourArea(approx)

        #做透视变换要求轮廓近似满足是4个点,挑选出符合要求的结果

        if area>20000 and len(approx)==4:
            screenCnt=approx
            flag=1  #标识找到了文档
            print(peri,area)
            print('检测到文档')
            break

    if flag==1:

        image_contours=cv2.drawContours(frame,[screenCnt],0,(0,255,0),2)
        cv_show('image',image_contours)

        #左四点转换,扶正后的坐标

        warped=four_point_transform(orig,screenCnt.reshape(4,2))
        cv_show('warped',warped)
        
cap.release()
cv2.destroyAllWindows()

总结

应用

文档处理

快速将纸质文档中的文字转换为电子文本,方便编辑、存储和检索,提高文字处理效率。

车牌识别

在智能交通系统中,通过摄像头拍摄车牌图像,利用 OCR 技术自动识别车牌号码,实现车辆的自动管理和收费等功能。

身份证识别

在一些需要身份验证的场合,如银行开户、酒店入住等,通过摄像头 OCR 快速识别身份证上的文字信息,提高信息录入效率和准确性。

场景文字识别

在图像和视频内容分析中,识别场景中的文字,如街道标志、广告招牌等,为图像理解和信息检索提供支持。

相关推荐
张彦峰ZYF1 分钟前
多模态大模型、混合专家模型与云端协同架构
人工智能·计算机视觉·多模态大模型·混合专家架构·大小模型协同架构
丝斯20114 分钟前
AI学习笔记整理(43)——NLP之大规模预训练模型BERT
人工智能·学习·自然语言处理
yong99906 分钟前
信号分形维数计算方法与MATLAB实现
开发语言·人工智能·matlab
爱吃大芒果8 分钟前
openJiuwen(Windows端)大模型添加及AI Agent创建教程
人工智能·ubuntu·openjiuwen
工藤学编程8 分钟前
零基础学AI大模型之个人助理智能体之tool_calling_agent实战
人工智能·langchain
WZgold14110 分钟前
黄金再创新高!2026 年金价走势预测
大数据·人工智能·经验分享·区块链
雷焰财经10 分钟前
生成式AI走进金融核心系统——效率革命还是风险放大器?
人工智能
TOPGUS10 分钟前
谷歌第三季度财报发布:AI搜索并未蚕食传统搜索,反而正在创造增量
大数据·人工智能·搜索引擎·谷歌·seo·数字营销
百度智能云技术站11 分钟前
基于 vLLM 的大模型推理服务秒级扩缩容的工程优化实践
人工智能