OpenCV项目1-OCR识别

这篇具有很好参考价值的文章主要介绍了OpenCV项目1-OCR识别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


文章处理的图片:
OpenCV项目1-OCR识别

项目思路:

思路:我们拿到一张图片不是直接就识别的,而是做一些处理,去除我们不需要的信息,保留我们所需要的信息,再做识别。

通常要做的是对图片进行灰度化处理,再进行滤波,形态学等等去除掉不要的信息。

因为在处理的过程中,我们要对每一步处理后的图片进行查看分析,我们要显示很多次图片,因此我们可以把显示图片的功能封装成一个函数形式来使用:

# 显示图片
def cv_show(winname, image):
    cv2.imshow(winname, image)
    # 销毁窗口
    cv2.waitKey(0)
    cv2.destroyAllWindows()

我们在拿到一张图片的时候,有时候图片的大小不好处理,比如我们这次处理的图片的大小为3264×2448。我们先对尺寸大小进行处理。

OpenCV项目1-OCR识别

可以将修改尺寸的功能封装成一个函数:

# 封装resize功能.
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
    # 指定了resize的height
    if width is None:
        r = height / float(h) # 缩放比例
        dim = (int(w * r), height)
    # 指定了resize的width
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

我们修改成高度为500的大小处理图片:

image = resize(image_copy, height = 500)

1、灰度化处理:

# 灰度化处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show('gray',gray)

OpenCV项目1-OCR识别

2、采用高斯滤波去噪

参考文章:
OpenCV学习笔记8-滤波器原理及代码实现

为后续Canny检测服务:

# 高斯平滑
Gaussian = cv2.GaussianBlur(gray, (5, 5), 0)
cv_show('Gaussian',Gaussian)

OpenCV项目1-OCR识别

3、边缘检测

参考文章:
OpenCV学习笔记8-滤波器原理及代码实现

我们采用Canny找出信息的边缘,为后续查找轮廓做准备:

# 边缘检测,寻找边界
edged = cv2.Canny(Gaussian, 70, 200)
cv_show('edged',edged)

OpenCV项目1-OCR识别

4、查找轮廓并排序:

参考文章:
OpenCV学习笔记10-图像轮廓的相关知识及代码实现

# 查找轮廓
cnts = cv2.findContours(edged, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]

找到轮廓后,我们排序一下,为后面的透视变换和绘制轮廓做准备:

# 将轮廓按照面积降序排序
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

5、绘制全部轮廓

参考文章:
OpenCV学习笔记10-图像轮廓的相关知识及代码实现

注意绘制轮廓会对原图片进行绘制,我们copy一份:

# 绘制所有轮廓
image_contours = cv2.drawContours(image.copy(), cnts, -1, (0, 0, 255), 1)

OpenCV项目1-OCR识别

6、多边形逼近

参考文章:
OpenCV学习笔记10-图像轮廓的相关知识及代码实现

绘制轮廓的方法有可能使得轮廓线粗糙且不平滑,我们用多边形逼近的方法去得到平滑的轮廓,只保留最有用的信息,注意也要对copy的图片进行处理。近似完后,只剩下四个顶点的角的坐标,因此下面的len(approx)=4

# 遍历轮廓找出最大的轮廓.
for c in cnts:
    # 计算轮廓周长
    perimeter = cv2.arcLength(c, True)
    # 多边形逼近,得到近似的轮廓
    approx = cv2.approxPolyDP(c, 0.02 * perimeter, True)
    # 最大的轮廓
    if len(approx) == 4:
        # 接收approx
        screen_cnt = approx
        break
# 画出多边形逼近
image_screen_cnt = cv2.drawContours(image.copy(), [screen_cnt], -1, (0, 0, 255), 1)
cv_show('image_screen_cnt', image_screen_cnt)

7、仿射变换

参考文章:
OpenCV学习笔记7-图像的基本变换(附代码实现)

我们对图片进行完预处理后,得到的近似轮廓,因为我们只想处理最有用的信息,其他周围没有用的背景给它去掉,因此我们用仿射变换使得图像变正。

透视变换要找到变换矩阵,因为多边形逼近后只留下四个顶点的坐标,因此我们需要找到原图的四个坐标和仿射变换后的四个坐标。

现在已经找到了原图的4个点的坐标。需要知道变换后的4个坐标,因此我们可以对原图的四个坐标按照角点顺时针或者逆时针排序,封装成一个函数:

# 排序功能是一个独立功能,可以封装成一个函数
def order_points(pts):
    # 创建全是0的矩阵, 来接收等下找出来的4个角的坐标.
    rect = np.zeros((4, 2), dtype='float32')
    # 列相加
    s = pts.sum(axis=1)
    # 左上的坐标一定是x,y加起来最小的坐标. 右下的坐标一定是x,y加起来最大的坐标.
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    # 右上角的x,y相减的差值一定是最小的.
    # 左下角的x,y相减的差值, 一定是最大.
    # diff的作用是后一列减前一列得到的差值
    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):
    # 对输入的4个坐标排序
    rect = order_points(pts)
    # top_left简称tl,左上角
    # top_right简称tr,右上角
    # bottom_right简称br,右下角
    # bottom_left简称bl,左下角
    (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)
    max_width = 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)
    max_height = max(int(heightA), int(heightB))
    # 构造变换之后的对应坐标位置.
    dst = np.array([
        [0, 0],
        [max_width, 0],
        [max_width, max_height],
        [0, max_height]], dtype='float32')
    # 计算变换矩阵
    M = cv2.getPerspectiveTransform(rect, dst)
    # 透视变换
    warped = cv2.warpPerspective(image, M, (max_width, max_height))
    return warped

调用仿射变换的函数:

进项仿射变换的时候,我们需要将之前的大小还原回来:

# 计算比例. 限定高度500
# 此时像素点都缩小了一定的比例,进行放射变换时要还原
ratio = image.shape[0] / 500.0
# 拷贝一份
image_copy = image.copy()
# 进行仿射变换,使图片变正
warped = four_point_transform(image_copy, cv_show('warped', warped)

OpenCV项目1-OCR识别

拉正之后,我们通过二值化处理进行过滤信息,得到有用的信息,方便ocr的扫描和提取:

# 二值处理,先转成灰度图
warped_gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
# 再二值化处理
ref = cv2.threshold(warped_gray, 150, 255, cv2.THRESH_BINARY)[1]
cv_show('ref', ref)

OpenCV项目1-OCR识别

8、写入图片文件

将处理好的文件保存下来

# 把处理好的图片写入图片文件.
_ = cv2.imwrite('./scan.jpg', ref)

9、扫描读取

我们需要导入pytesseract的工具包,进行扫描文字:

我们先打开cmd下载一下:

pip install pytesseract

OpenCV项目1-OCR识别

出现这个情况不要紧,我们修改一下下载路径:

pip install --target=d:\python3.9\lib\site-packages pytesseract

OpenCV项目1-OCR识别

具体可以查看我的这个文章:
已解决:Requirement already satisfied:xxx

pytesseract要求的image不是opencv读进来的image, 而是pillow这个包, 即PIL

所以我们要传入pillow包的图片!

页面分隔模式+OCR引擎模式可以看看我这篇文章:
OpenCV学习笔记11-Tesseract-OCR的安装和使用

  • pytesseract.image_to_string(Image.open(‘图片路径’), lang='使用的语言包‘, config=‘页面分隔模式+OCR引擎模式’)
    • tesseract5.0配套的traineddata文件某些语言版本不支持老版本的引擎(即oem=0)。

# pytesseract要求的image不是opencv读进来的image, 而是pillow这个包, 即PIL
text = pytesseract.image_to_string(Image.open('./scan.jpg'), lang='chi_sim+eng', config='--oem 1')

10、写入本地

# 保存到本地
with open('output.txt', 'w') as f:
    print(text)
    f.write(str(text))

我们可以在保存的目录下看到已保存的scan和output

OpenCV项目1-OCR识别

查看识别结果:

eee ek RK KOK KOR KOK

WHOLE FOODS MARKET - WESTPORT,CT 06880
399 POST RD WEST - (203) 227-6858

365
365
365
365

uexH TAX

BACON LS
BACON LS
BACON LS
BACON LS

BROTH CHIC
FLOUR ALMOND

CHKN BRST BNLSS SK
HEAVY CREAM
BALSMC REDUCT

BEEF GRND 85/15
JUICE COF CASHEW C

.00

DOCS PINT ORGANIC
HNY ALMOND BUTTER

BAL

NP
NP
NP
NP
NP
NP
NP
NP
NP
NP
NP
NP
NP

4.99
4.99
4.99
4.99
2.19
11.99
18.80
3.39
6.49
5.04
8.99
194.49
9.99
101.33

ae Mees es ieee i en

呃呃呃呃呃,好像识别结果准确率不高,但是大部分还是识别出来了。

完整代码:

import cv2
import numpy as np
import pytesseract
from PIL import Image

# 显示图片
def cv_show(winname, image):
    cv2.imshow(winname, image)
    # 销毁窗口
    cv2.waitKey(0)
    cv2.destroyAllWindows()
# 有些原图片的size不好处理,我们可以封装成一个函数来统一图片的size
# 封装resize功能.
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
    # 指定了resize的height
    if width is None:
        r = height / float(h) # 缩放比例
        dim = (int(w * r), height)
    # 指定了resize的width
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized
    
# 进行透视变换.
# 透视变换要找到变换矩阵
# 变换矩阵要求原图的4个点坐标和变换之后的4个点的坐标
# 现在已经找到了原图的4个点的坐标。需要知道变换后的4个坐标
# 先对获取到的4个角点按照一定顺序(顺/逆时针)排序
# 排序功能是一个独立功能,可以封装成一个函数
def order_points(pts):
    # 创建全是0的矩阵, 来接收等下找出来的4个角的坐标.
    rect = np.zeros((4, 2), dtype='float32')
    # 列相加
    s = pts.sum(axis=1)
    # 左上的坐标一定是x,y加起来最小的坐标. 右下的坐标一定是x,y加起来最大的坐标.
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    # 右上角的x,y相减的差值一定是最小的.
    # 左下角的x,y相减的差值, 一定是最大.
    # diff的作用是后一列减前一列得到的差值
    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):
    # 对输入的4个坐标排序
    rect = order_points(pts)
    # top_left简称tl,左上角
    # top_right简称tr,右上角
    # bottom_right简称br,右下角
    # bottom_left简称bl,左下角
    (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)
    max_width = 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)
    max_height = max(int(heightA), int(heightB))
    # 构造变换之后的对应坐标位置.
    dst = np.array([
        [0, 0],
        [max_width, 0],
        [max_width, max_height],
        [0, max_height]], dtype='float32')
    # 计算变换矩阵
    M = cv2.getPerspectiveTransform(rect, dst)
    # 透视变换
    warped = cv2.warpPerspective(image, M, (max_width, max_height))
    return warped
    
# 把图像预处理的功能封装成一个函数
def Image_Pretreatment(image):
    # 图片预处理
    # 灰度化处理
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # cv_show('gray',gray)
    # 高斯平滑
    Gaussian = cv2.GaussianBlur(gray, (5, 5), 0)
    # cv_show('Gaussian',Gaussian)
    # 边缘检测,寻找边界(为后续查找轮廓做准备)
    edged = cv2.Canny(Gaussian, 70, 200)
    # cv_show('edged',edged)
    # 查找轮廓
    cnts = cv2.findContours(edged, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]
    # 将轮廓按照面积降序排序
    cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
    # 绘制所有轮廓
    image_contours = cv2.drawContours(image.copy(), cnts, -1, (0, 0, 255), 1)
#     cv_show('image_contours', image_contours)
    # 遍历轮廓找出最大的轮廓.
    for c in cnts:
        # 计算轮廓周长
        perimeter = cv2.arcLength(c, True)
        # 多边形逼近,得到近似的轮廓
        # 近似完后,只剩下四个顶点的角的坐标
        approx = cv2.approxPolyDP(c, 0.02 * perimeter, True)
        # 最大的轮廓
        if len(approx) == 4:
            # 接收approx
            screen_cnt = approx
            break
    # 画出多边形逼近
    image_screen_cnt = cv2.drawContours(image.copy(), [screen_cnt], -1, (0, 0, 255), 1)
    # cv_show('image_screen_cnt', image_screen_cnt)
    # 进行仿射变换,使图片变正
    warped = four_point_transform(image_copy, screen_cnt.reshape(4, 2) * ratio)
    # cv_show('warped', warped)
    # 二值处理,先转成灰度图
    warped_gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
    # 再二值化处理
    ref = cv2.threshold(warped_gray, 150, 255, cv2.THRESH_BINARY)[1]
    cv_show('ref', ref)
    # 旋转变正
    # dst = cv2.rotate(ref, cv2.ROTATE_90_COUNTERCLOCKWISE)
    # cv_show('dst', dst)
    return ref
    
if __name__ == "__main__":
    # 读取图片
    image = cv2.imread('D:/Desktop/daxue/shiyanshi/Project/OCR/images/receipt.jpg')
    # 计算比例. 限定高度500
    # 此时像素点都缩小了一定的比例,进行放射变换时要还原
    ratio = image.shape[0] / 500.0
    # 拷贝一份
    image_copy = image.copy()
    # 修改尺寸
    image = resize(image_copy, height=500)
    # cv_show('image', image)
    # 返回透视变换的结果
    ref = Image_Pretreatment(image)
    # 把处理好的图片写入图片文件.
    _ = cv2.imwrite('./scan.jpg', ref)
    # pytesseract要求的image不是opencv读进来的image, 而是pillow这个包, 即PIL
    text = pytesseract.image_to_string(Image.open('./scan.jpg'), lang='chi_sim+eng', config='--oem 1')
    # 保存到本地
    with open('output.txt', 'w') as f:
        print(text)
        f.write(str(text))

附OpenCV目录:OpenCV总目录学习笔记

智科专业小白,写博文不容易,如果喜欢的话可以点个赞哦!OpenCV项目1-OCR识别

文章来源地址https://www.toymoban.com/news/detail-470799.html

到了这里,关于OpenCV项目1-OCR识别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python OCR 使用easyocr库将图片中的文章提取出来

    EasyOCR是一个开源的Python库,专注于提供易用而准确的文字识别功能。它基于深度学习技术,使用了一种端到端的方法,能够在多种语言和字体下进行稳定的识别。 希望能写一些简单的教程和案例分享给需要的人 Python 3.10.12 系统: ubuntu 22.04 接下来我分享如何使用Python的easy

    2024年02月11日
    浏览(45)
  • 【java】opencv + Tesseract(tess4j) 实现图片处理验证码识别

    2022/12/27 有的小伙伴说maven导入不了依赖,加了一种方法,百分百解决。 2022/12/28 写了半天,想去论坛放松休息下,结果看到别人已经有成品了,难受啊马飞,晚点看情况要不要写个搭建使用方法(我猜没人看,估计也不用写了,就当自己做个记录) 2023/3/24 更新了一键部署验

    2024年02月08日
    浏览(66)
  • 【Python】【OpenCV】OCR识别(三)——字符识别

    通过上一篇博客,我们成功将有角度的图片进行“摆正”,接下来我们来提取图片中的文字。 我们使用Tesseract来处理图片并提取文字,相关下载安装请参考:Python下Tesseract Ocr引擎及安装介绍 - 黯然销魂掌2015 - 博客园 (cnblogs.com) 同时我们需要下载第三方Lib——pytesseract,使用

    2024年02月02日
    浏览(47)
  • 【Python】【OpenCV】OCR识别(一)

    接着练手图像处理例子   抛开网上截图进行OCR识别,更多的图源来自于我们的手机,相机等等设备,而得到的图片都并非是板正的,大多随手一拍的图源都是带有角度的,所以我们需要先将图像进行摆正。 首先先对图像进行预处理,上代码:         1、使用Canny来进行边缘

    2024年02月03日
    浏览(45)
  • OpenCV(九)--文字扫描OCR识别

    步骤:边缘检测+计算轮廓+变换+OCR OCR识别 识别结果: 完整代码

    2024年01月18日
    浏览(42)
  • 分享一个免费的OCR图片文字识别接口

    此接口为每天100次免费,应对平时自己调试使用也够了~ 亲测准确度还不错。 请求地址 https://api.itapi.cn/api/ocr/v2 请求参数 参数名 参数说明 key 用户请求密钥,可在 密钥管理页面 申请 data 图片base64编码数据 或 网络图片URL 请求结果参数说明 参数名 参数说明 code 状态码 msg 状态

    2024年02月15日
    浏览(45)
  • 【uniapp】调用阿里云OCR图片识别文字:

    一、效果: 二、实现: 【阿里官方】高精版OCR文字识别【最新版】-云市场-阿里云

    2024年01月23日
    浏览(37)
  • 完全离线的OCR图片转文字识别工具Umi-OCR

    OCR图片转文字识别软件,完全离线。截屏/批量导入图片,支持多国语言、合并段落、竖排文字。可排除水印区域,提取干净的文本。基于 PaddleOCR 。 免费:本项目所有代码开源,完全免费。 方便:解压即用,离线运行,无需网络。 批量:可批量导入处理图片,结果保存到本

    2024年02月03日
    浏览(80)
  • Mac 上使用 Tesseract OCR 识别图片文本

    Tesseract OCR 引擎:Tesseract是一个开源的OCR引擎,你需要先安装它。可以从Tesseract官方网站(https://github.com/tesseract-ocr/tesseract)下载适用于你的操作系统的安装程序或源代码,并按照官方文档进行安装。 Tesseract OCR 对于低分辨率或模糊的图片可能无法准确识别。尝试使用更高分

    2024年02月15日
    浏览(41)
  • Umi-OCR:开源、免费、离线、多功能的 OCR 图片文字识别软件

    官方版本说明 不同版本仅OCR引擎插件不同,其它功能完全一致。 均支持 win7 x64 及以上的系统,附带多国语言识别库。 .7z.exe 为自解压包,可以用压缩软件打开,也可以在没有安装压缩软件的电脑上直接双击解压。 Paddle 引擎插件版 (性能好,速度快,占用率高,适合高配机

    2024年01月19日
    浏览(92)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包