openCV实战-系列教程11:文档扫描OCR识别上(灰度/高斯滤波/边缘检测/轮廓检测/透视变换/tesseract OCR/pytesseract/OCR文字识别)项目实战、源码解读

🧡💛💚💙💜OpenCV实战系列总目录

有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传

中篇内容:
openCV实战-系列教程13:文档扫描OCR识别中(图像轮廓/模版匹配)项目实战、源码解读

下篇内容:
openCV实战-系列教程14:文档扫描OCR识别下(图像轮廓/模版匹配)项目实战、源码解读

1、运行效果演示

项目界面:
在这里插入图片描述

如果还没有安装openCV,请看这篇安装教程

1.1 输入参数

在运行参数配置界面输入以下指令即可运行

--image ./images/receipt.jpg

2023版pycharm配置运行参数教程
新版本openCV中的cv2.findContours返回值从3个变成了两个
通过修改参数receipt.jpg,可以处理其他的图像数据。

1.2 整体流程与效果

运行打印结果:

C:\Users\Alex\anaconda3\envs\CV\python.exe A:\2_gupao\ocr\scan.py --image ./images/receipt.jpg
STEP 1: 边缘检测
STEP 2: 获取轮廓
STEP 3: 变换
进程已结束,退出代码为 0

原始图像是一张购物小票,是从任意角度拍摄的,需要把这个小票调整到一个正确的角度,然后才能进行文字识别。第一步需要进行边缘检测,得到这个小票。

第二步框出这个小票,这个框起来的过程就是一个轮廓检测。

第三张就需要把这个小票放正了,整齐的排列出来,才能识别出里面的文字,做字符识别的操作。

第四步将这个小票的内容的文字识别出来,即OCR文字识别。

2、图像读取与处理

2.1 数据读取

读取输入

image = cv2.imread(args["image"])
ratio = image.shape[0] / 500.0
orig = image.copy()
image = resize(orig, height=500)
  1. 读取图像
  2. image.shape[0]是原始图像高,500是等下需要resize的高,保存这个比例,因为后续需要对原始图像进行处理,这个时候需要获取这个比例值
  3. 深度复制原始图像
  4. resize原始图像,设置高为500,宽会自动根据比例计算给出,这里的resize函数是我自己写的,主要是通过给定的h,安装原始的长宽比例计算出宽,再用openCV的resize函数(cv2.resize)

2.2 预处理

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 75, 200)
print("STEP 1: 边缘检测")
cv2.imshow("Image", image)
cv2.imshow("Edged", edged)
cv2.waitKey(0)
cv2.destroyAllWindows()
  1. 原始图像灰度处理
  2. 高斯滤波,过滤一些干扰噪声
  3. 边缘检测
  4. 打印文字
  5. 打印原始图像
  6. 打印边缘检测图像
  7. 等待按任意键
  8. 关闭所有窗口

打印结果:

STEP 1: 边缘检测

3、轮廓检测

3.1 获取轮廓

cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    if len(approx) == 4:
        screenCnt = approx
        break
  1. 获取轮廓,edged.copy()深度复制图像,RETR_LIST检索所有的轮廓,并将其保存到一条链表当中,CHAIN_APPROX_SIMPLE轮廓逼近方法,获取第一个返回值,全部轮廓
  2. 排序轮廓,这个函数是我自己写的(解析参考这个教程3.3),取出前5个轮廓,因为根据任务不同可能有多个复合的轮廓,比如有三张小票
  3. 遍历每一个轮廓
  4. 计算当前轮廓周长
  5. 计算近似轮廓,实际中的轮廓可能是一些点组成的,因为不规则的轮廓即拟合出大量的点,根据周长百分比0.02 * peri来近似轮廓,这个值设置的大近似出的轮廓可能就是多边形,小可能就是矩形或者三角形
  6. 如果点数是四就是矩形
  7. 如果是矩形,就是我们想要的轮廓,因为小票的轮廓最好是一个矩形,保存这个轮廓
  8. break

3.2 画出轮廓

print("STEP 2: 获取轮廓")
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
cv2.imshow("Outline", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

打印结果:

  1. 打印文字
  2. 画出轮廓,参数分别是原始图像、轮廓信息、全部轮廓、轮廓颜色、轮廓线条粗细
  3. 打印轮廓图像

STEP 2: 获取轮廓

在这里插入图片描述

4 顶点排序函数

我们有A、B、C、D四个点,组成一个不规整的四边形,现在通过下面这个函数,将这四个点的顺序调整到合适的顺序,调整后的结果方便我们把四个点映射成规整的矩形的四个点

def order_points(pts):
    rect = np.zeros((4, 2), dtype="float32")
    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
  1. pts是一个存放原始数据的二维list,一共有4个元素,分别对应ABCD四个点,然后每个元素对应两个值,分别是横坐标和纵坐标。
  2. 构造一个名为rect 结构和pts一样的二维list,里面全部存放0
  3. pts的每个点的横纵坐标加起来,保存一个名为s的有4个元素的list,每个元素分别为A、B、C、D四个点的坐标之和
  4. 求出s最小数对应的索引对应在pts的点的两个坐标值,作为rect 的第1个点的两个坐标
  5. 求出s最大数对应的索引对应在pts的点的两个坐标值,作为rect 的第3个点的两个坐标
  6. 把pts的每个点的纵坐标减去横坐标,保存一个名为diff 的有4个元素的list,每个元素分别为A、B、C、D四个点的坐标之差
  7. 求出diff最小数对应的索引对应在pts的点的两个坐标值,作为rect 的第2个点的两个坐标
  8. 求出diff最大数对应的索引对应在pts的点的两个坐标值,作为rect 的第4个点的两个坐标
  9. 返回rect

中篇内容:
openCV实战-系列教程13:文档扫描OCR识别中(图像轮廓/模版匹配)项目实战、源码解读

下篇内容:
openCV实战-系列教程14:文档扫描OCR识别下(图像轮廓/模版匹配)项目实战、源码解读

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,这个问题比较复杂,需要使用一些图像处理库和OCR库。以下是一个大致的流程: 1. 使用OpenCV库读取图像并将其转换为灰度图像。 2. 对灰度图像进行二值化处理,可以使用OpenCV的`cv2.threshold()`函数。 3. 对二值化后的图像进行高斯滤波,可以使用OpenCV的`cv2.GaussianBlur()`函数。 4. 对滤波后的图像进行腐蚀操作,可以使用OpenCV的`cv2.erode()`函数。 5. 对腐蚀后的图像进行轮廓检测,可以使用OpenCV的`cv2.findContours()`函数。 6. 对检测到的轮廓进行筛选,只保留符合字符特征的轮廓。可以根据轮廓的面积、宽高比等特征进行筛选。 7. 将选取的字符区域进行单独截取,可以使用OpenCV的`cv2.boundingRect()`函数。 8. 对截取出来的字符区域进行数字识别,可以使用OCR库,比如Tesseract OCR或者pytesseract。 下面是一个具体的代码实现,使用了OpenCV和pytesseract库: ```python import cv2 import pytesseract # 读取图像并转换为灰度图像 img = cv2.imread('image.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 _, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 高斯滤波 blur = cv2.GaussianBlur(thresh, (3, 3), 0) # 腐蚀操作 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) erode = cv2.erode(blur, kernel, iterations=1) # 轮廓检测 contours, hierarchy = cv2.findContours(erode, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 筛选符合条件的轮廓 roi_list = [] for cnt in contours: area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) aspect_ratio = float(w) / h if area > 50 and aspect_ratio > 0.2 and aspect_ratio < 1.2: roi = img[y:y+h, x:x+w] roi_list.append(roi) # 对截取出来的字符区域进行数字识别 for roi in roi_list: text = pytesseract.image_to_string(roi, config='--psm 10') print(text) ``` 需要注意的是,OCR库对字符的识别准确率并不是100%,有时会出现误识别的情况。可以尝试调整图像处理的参数,或者使用其他的OCR库进行识别

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器学习杨卓越

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值