【opencv】opencv透视变换和ocr识别实验

news2024/12/24 22:12:40

实验环境:anaconda、jupyter notebook

实验用到的包opencv、numpy、matplotlib、tesseract

一、opencv透视变换

原图

图片是我拍的耳机说明书,哈哈哈哈,你也可以使用自己拍的照片,最好是英文内容,tesseract默认识别英文,识别中文需要额外训练

原图

包导入

import cv2
import matplotlib.pyplot as plt
import numpy as np

图像预处理(比例放缩)

page = cv2.imread('page.jpg')
ratio  = 500.0 / page.shape[0]
# 放缩比例
page_original = page.copy()
page_resize = cv2.resize(page_original,(int(page.shape[1] * ratio),500))

plt.imshow(cv2.cvtColor(page_resize, cv2.COLOR_BGR2RGB))
plt.show()

图像比例收缩

图像转为二值图像

# 转灰度图
page_gray = cv2.cvtColor(page_resize, cv2.COLOR_BGR2GRAY)
# 高斯滤波,去除噪点
page_guassion = cv2.GaussianBlur(page_gray,(5,5),0)
# canny边缘检测
page_canny = cv2.Canny(page_guassion, 30, 100)

plt.figure(figsize=(20,25))
plt.subplot(131)
plt.imshow(page_gray, 'gray')

plt.subplot(132)
plt.imshow(page_guassion, 'gray')

plt.subplot(133)
plt.imshow(page_canny, 'gray')

plt.show()

转二值图流程

获得目标图像外轮廓

轮廓检测会得到很多的轮廓,这里通过周长比较,拿到周长最长的(在实验图像中,显然周长最长的轮廓是外轮廓)

# 轮廓检测
binary, page_contours, hierarchy = cv2.findContours(page_canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

page_cnt = None
page_cnt_arc = 0

# 最大面积的轮廓
for page_contour in page_contours:
    # 算近似轮廓
    page_cnt_arc_temp = cv2.arcLength(page_contour,True)
    page_cnt_arc_approx = cv2.approxPolyDP(page_contour, 0.05 * page_cnt_arc_temp, True)

    # 取最大周长的轮廓
    page_cnt_arc_temp = cv2.arcLength(page_cnt_arc_approx,True)
    if page_cnt_arc_temp > page_cnt_arc:
        page_cnt = page_cnt_arc_approx
        page_cnt_arc = page_cnt_arc_temp


page_temp = page_resize.copy()
cv2.drawContours(page_temp, [page_cnt], -1, (0,255,0),2)

plt.figure(figsize=(5,10))
plt.imshow(cv2.cvtColor(page_temp, cv2.COLOR_BGR2RGB))
plt.show()

外轮廓

构建透视变换的原矩阵和目标矩阵

print('原始',page_cnt)
page_cnt_deal = np.float32(page_cnt[:,0,:]) / ratio
print('处理',page_cnt_deal)
A,B,C,D = page_cnt_deal 
print('顶点',A,B,C,D)

# 在原始图像上画轮廓
page_temp = page.copy()
page_cnt_deal_temp = np.array([[np.int32(A)],[np.int32(B)],[np.int32(C)],[np.int32(D)]])
print(page_cnt_deal_temp)
cv2.drawContours(page_temp, [page_cnt_deal_temp], -1, (0,255,0),10)
plt.imshow(cv2.cvtColor(page_temp, cv2.COLOR_BGR2RGB))
plt.show()

W1 = np.sqrt((A[0] - B[0]) ** 2 + (A[1] -B[1]) ** 2)
W2 = np.sqrt((C[0] -D[0]) ** 2 + (C[1] -D[1]) ** 2)
W = max(int(W1), int(W2))

H1 = np.sqrt((A[0] - C[0]) ** 2 + (A[1] -C[1]) ** 2)
H2 = np.sqrt((B[0] -D[0]) ** 2 + (B[1] -D[1]) ** 2)
H = max(int(H1), int(H2))

# 目标坐标
dest = np.array([
    [0,W],
    [H,W],
    [H,0],
    [0,0]
], dtype=np.float32)

print('目标',dest)

# 在原始图像上画轮廓
page_temp = page.copy()
page_cnt_deal_temp = np.array([[np.int32(dest[0])],[np.int32(dest[1])],[np.int32(dest[2])],[np.int32(dest[3])]])
print(page_cnt_deal_temp)
cv2.drawContours(page_temp, [page_cnt_deal_temp], -1, (0,255,0),10)
plt.imshow(cv2.cvtColor(page_temp, cv2.COLOR_BGR2RGB))
plt.show()

矩阵构建1

矩阵构建2

透视变换

这里创建出的矩阵M就是原坐标矩阵pagecntdeal到目标坐标矩阵dest的变换矩阵。

# 透视变换
M = cv2.getPerspectiveTransform(page_cnt_deal, dest)
page_warped = cv2.warpPerspective(page, M, (int(H),int(W)))

plt.imshow(cv2.cvtColor(page_warped, cv2.COLOR_BGR2RGB))
plt.show()

透视变换

二值化处理

这里二值化处理是为了ocr识别更清晰

# 二值化
page_warped_gray = cv2.cvtColor(page_warped, cv2.COLOR_BGR2GRAY)
res,page_warped_bin = cv2.threshold(page_warped_gray, 100,255, cv2.THRESH_BINARY)

plt.imshow(page_warped_bin,'gray')
plt.show()

二值化处理

二、tesseract-orc识别

安装tesseract

ubuntu上安装非常容易

sudo apt install tesseract-ocr

查看版本号

tesseract -v

tesseract安装成功

命令行使用

在当前目录下放一张图片,你可以自己画一张

ocr命令行识别原图

tesseract 图片名称 输出文件名称

不得不说,这个算法还是有些许偏颇,像我这样写得一手好字,居然也被认错了

tesseract识别

安装pytesseract

pip install pytesseract

使用tesseract识别刚刚透视转换的结果

import pytesseract

text = pytesseract.image_to_string(page_warped_bin)
print(text)

牛逼!

orc识别结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1677169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++|多态性与虚函数(2)|虚析构函数|重载函数|纯虚函数|抽象类

前言 看这篇之前,可以先看多态性与虚函数(1)⬇️ C|多态性与虚函数(1)功能绑定|向上转换类型|虚函数-CSDN博客https://blog.csdn.net/weixin_74197067/article/details/138861418?spm1001.2014.3001.5501这篇文章会…

Kasawaki川崎机器人故障维修

在当今的自动化工业领域,川崎工业机器人以其卓越的性能和可靠的工作效率赢得了广泛的赞誉。作为机器人的核心组成部分,伺服电机的作用至关重要。然而,就像所有机械设备一样,也可能会遭遇电机磨损或故障,需要适时的川崎…

二叉树——初解

二叉树 树树的概念树的性质 二叉树二叉树的概念二叉树的性质二叉树的实现方式数组构建左孩子右兄弟法构建指针构建 树 树的概念 在计算机科学中,树(Tree)是一种重要的非线性数据结构,它由若干节点(Node)组…

iPhone15销量不佳,新产品没希望,苹果开始寻找库克接班人

美国媒体开始谈论谁将成为苹果的新CEO,这意味着苹果董事会开始为库克寻找接班人了,导致如此结果,可能在于iPhone15的表现实在太差了,而库克力推的vision Pro等新产品又没有为苹果打开局面所致。 如今的苹果倒是与1980年代乔布斯离…

壹资源知识付费系统源码-小程序端+pc端

最新整理优化,含微信小程序和pc网页。内置几款主题,并且可以自己更改主题样式,各区块颜色,文字按钮等。 适用于知识付费类资源类行业。如:项目类,小吃技术类,图书类,考研资料类&…

Nodejs 第七十一章(libuv)

libuv 在Node.js中,libuv是作为其事件循环和异步I/O的核心组件而存在的。Node.js是构建在libuv之上的,它利用libuv来处理底层的异步操作,如文件I/O、网络通信和定时器等。 libuv在Node.js中扮演了以下几个重要角色: 事件循环&a…

同为科技详解智能PDU所应用的通信协议与接口

现如今,信息服务、AI人工智能的飞速发展与增长,全球正经历信息数据的爆炸。不仅数据量以惊人的速度增长,而且全球社会各行业对数据的依赖的程度也在日益增加。这些趋势使数据中心在全球都享有关键基础架构的地位。假设某个数据中心发生严重的…

写一个类ChatGPT应用,前后端数据交互有哪几种

❝ 对世界的态度,本质都是对自己的态度 ❞ 大家好,我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder 前言 最近,公司有一个AI项目,要做一个文档问答的AI产品。前端部分呢,还是「友好借鉴」Cha…

经典神经网络(8)GAN、CGAN、DCGAN、LSGAN及其在MNIST数据集上的应用

经典神经网络(8)GAN、CGAN、DCGAN、LSGAN及其在MNIST数据集上的应用 1 GAN的简述及其在MNIST数据集上的应用 GAN模型主导了生成式建模的前一个时代,但由于训练过程中的不稳定性,对GAN进行扩展需要仔细调整网络结构和训练考虑,因此GANs虽然在…

【js逆向】易车网JS逆向案例实战手把手教学(附完整代码)

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

一表捋清网络安全等级保护测评要求

三级网络安全等级保护测评指标: 对于中小企事业单位来说,网络安全建设是一个复杂且投入较高的过程,因此他们更倾向于寻找一种“省心省力”的等保建设方案,以及一种能够持续有效且具有较高性价比的网络安全建设投入方式。 此时&…

合合信息:TextIn文档解析技术与高精度文本向量化模型再加速

文章目录 前言现有大模型文档解析问题表格无法解析无法按照阅读顺序解析文档编码错误 诉求文档解析技术技术难点技术架构关键技术回根溯源 文本向量化模型结语 前言 随着人工智能技术的持续演进,大语言模型在我们日常生活中正逐渐占据举足轻重的地位。大模型语言通…

通过java将数据导出为PDF,包扣合并单元格操作

最近项目中需要将查询出来的表格数据以PDF形式导出&#xff0c;并且表格的形式包含横向行与纵向列的单元格合并操作&#xff0c;导出的最终效果如图所示&#xff1a; 首先引入操作依赖 <!--导出pdf所需包--><dependency><groupId>com.itextpdf</groupId&…

Linux 生态与工具

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 目录 Linux生态简介:Linux工具lrzsz&#xff…

适用于 Windows 8/10/11 的 10 大 PC 迁移工具:电脑克隆迁移软件

当您发现自己拥有一台新的 PC 或笔记本电脑时&#xff0c;PC 迁移变得至关重要。将数据从旧计算机传输到新计算机的过程似乎令人生畏&#xff0c;尤其是如果您是第一次这样做。迁移过程中数据丢失的潜在风险加剧了焦虑。为确保文件和系统设置的无缝无忧传输&#xff0c;使用专为…

探索设计模式的魅力:机器学习赋能,引领“去中心化”模式新纪元

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 探索设计模式的魅力&#xff1a;机器学习赋能&#xff0c;引领“去中心化”模式新纪元 ✨欢迎加入…

3月份太阳镜行业线上市场销售数据分析

在消费者行为方面&#xff0c;太阳镜不仅仅是视力保护工具&#xff0c;更逐渐成为一种时尚单品。随着人们对健康和美容重视程度的提高&#xff0c;太阳镜作为体现个人风格的单品&#xff0c;其市场需求得到了进一步的推动。此外&#xff0c;全球旅行和旅游业的恢复&#xff0c;…

被暗示离职?教你优雅反击

在职场中&#xff0c;面对公司暗示离职的情况&#xff0c;应届毕业生可能会感到困惑与无助。但是&#xff0c;保持冷静和据理力争是保护自己权益的重要途径。以下是如何应对此类情况的一些建议。 当你感觉到被暗示离职时&#xff0c;首要的策略就是与上司进行有效沟通。安排一个…

halo博客--解决恶意刷评论的问题

原文网址&#xff1a;halo博客--解决恶意刷评论的问题_IT利刃出鞘的博客-CSDN博客 简介 本文介绍halo博客如何通过设置评论次数来解决恶意刷评论的问题。 评论功能要设置频率的限制&#xff0c;否则可能被人一直刷评论&#xff0c;然后数据库存的垃圾评论越来越多&#xff0…

数据结构——队列(链表实现)

一、队列的特点 先进先出 二、队列的代码 typedef int QDataType;// 链式结构&#xff1a;表示队列 typedef struct QListNode {struct QListNode* next;QDataType data; }QNode;// 队列的结构 typedef struct Queue {QNode* front; //指向队列的第一个结点QNode* rear;//指…