当前位置: 首页 > news >正文

# 如何使用OpenCV进行发票的透视变换和二值化处理

如何使用OpenCV进行发票的透视变换和二值化处理

引言

在自动化处理发票和其他文档时,图像预处理是一个关键步骤,它可以帮助提高OCR(光学字符识别)的准确性。透视变换用于校正图像中的透视失真,而二值化处理则可以简化图像,使其更适合OCR处理。本文将介绍如何使用OpenCV库进行这些操作。

环境准备

确保您的环境中安装了OpenCV库。如果尚未安装,可以通过以下命令安装:

pip install opencv-python

代码实现

以下是完整的代码实现,包括图像读取、透视变换、二值化处理和显示结果。

import numpy as np
import cv2def cv_show(name, img):"""简单的图像显示函数,用于显示图像窗口,参数name为窗口名称,img为要显示的图像"""cv2.imshow(name, img)cv2.waitKey(0)def order_points(pts):"""对四个点进行排序,以便于进行透视变换参数pts为四个检测到的点的坐标返回值rect为排序后的点的坐标"""rect = np.zeros((4, 2), dtype="float32")s = pts.sum(axis=1)  # 对pts矩阵的每一行进行求和操作(x+y)rect[0] = pts[np.argmin(s)]  # 选择坐标和最小的点为左上角rect[2] = pts[np.argmax(s)]  # 选择坐标和最大的点为右下角diff = np.diff(pts, axis=1)  # 对pts矩阵的每一行进行求差操作(y-x)rect[1] = pts[np.argmin(diff)]  # 选择差异最小的点为右上角rect[3] = pts[np.argmax(diff)]  # 选择差异最大的点为左下角return rectdef four_point_transform(image, pts):"""根据四个点进行透视变换参数image为原始图像,pts为四个检测到的点的坐标返回值warped为变换后的图像"""rect = order_points(pts)(tl, tr, br, bl) = rectwidthA = 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)warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))return warpeddef resize(image, width=None, height=None, inter=cv2.INTER_AREA):"""调整图像大小参数image为原始图像,width和height为调整后的宽度和高度,inter为插值方法返回值resized为调整大小后的图像"""dim = None(h, w) = image.shape[:2]if width is None and height is None:return imageif 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# 读取输入图像
image = cv2.imread('fapiao.jpg')
cv_show('image', image)# 图片过大,进行缩小处理
ratio = image.shape[0] / 500.0  # 计算缩小比率
orig = image.copy()
image = resize(orig, height=500)  # 缩小图像
cv_show('1', image)print('STEP 1: 轮廓检测')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 转换为灰度图
edged = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]  # 二值化
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
image_contours = cv2.drawContours(image.copy(), cnts, -1, (0, 0, 255), 1)
cv_show("image_contours", image_contours)print("STEP 2:获取最大轮廓")
screenCnt = sorted(cnts, key=cv2.contourArea, reverse=True)[0]  # 获取面积最大的轮廓
peri = cv2.arcLength(screenCnt, True)  # 计算轮廓周长
screenCnt = cv2.approxPolyDP(screenCnt, 0.05 * peri, True)  # 轮廓近似
print(screenCnt.shape)
image_contours = cv2.drawContours(image.copy(), [screenCnt], -1, (0, 255, 0), 2)
cv_show("image_contours", image_contours)
cv2.waitKey(0)# 透视变换
warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)
cv2.imwrite('invoice_new.jpg', warped)
cv2.namedWindow('xx', cv2.WINDOW_NORMAL)
cv2.imshow("xx", warped)
cv2.waitKey(0)# 二值处理
warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
ref = cv2.threshold(warped, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('ref', ref)kernel = np.ones((2, 2), np.uint8)  # 设置kernel大小
ref_new = cv2.morphologyEx(ref, cv2.MORPH_CLOSE, kernel)  # 闭运算
ref_new = resize(ref_new.copy(), width=500)
cv_show('ref_new', ref_new)
rotated_image = cv2.rotate(ref_new, cv2.ROTATE_90_COUNTERCLOCKWISE)
cv2.imshow("result", rotated_image)
cv2.waitKey(0)

运行结果

在这里插入图片描述
在这里插入图片描述

步骤解析

  1. 图像读取和缩小处理:首先读取图像,并根据需要进行缩小处理。
  2. 轮廓检测:将图像转换为灰度图,然后进行二值化处理,最后检测轮廓。
  3. 获取最大轮廓:从检测到的轮廓中找到面积最大的轮廓,并进行多边形近似。
  4. 透视变换:对原始图像进行透视变换,以消除透视失真。
  5. 二值化处理:对变换后的图像进行二值化处理,并进行形态学操作以去除噪声。
  6. 旋转处理:根据需要对图像进行旋转处理。

结论

通过这篇文章,您学会了如何使用OpenCV进行发票的透视变换和二值化处理。这些步骤对于自动化处理发票和其他文档非常重要,可以显著提高OCR的准确性。希望这篇文章对您有所帮助!如果您有任何问题或建议,请在评论区留言。

相关文章:

  • 如何观察epoll_threadpool_echo_server 线程的变化
  • 【HarmonyOS 5】App Linking 应用间跳转详解
  • CDN 回源:原理、作用与工作流程
  • 排序算法——基数排序
  • YY/T 1732-2020口腔曲面体层X射线模体
  • Nginx1.26.2安装包编译安装并配置stream模块
  • 101alpha_第6个
  • MYSQL 快速解析
  • k8s术语之DaemonSet
  • SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理标准)-(一)
  • Spark缓存--persist方法
  • 【C语言】文件操作(续)
  • AI原生手机:三大技术阵营的终极对决与未来展望
  • MyBatis(进阶)(xml标签)
  • 【Ubuntu】安裝向日葵远程控制
  • React Native基础环境配置
  • 【办公类-99-05】20250508 D刊物JPG合并PDF便于打印
  • CTF之常见的文件头和文件尾
  • LeetCode 3341到达最后一个房间的最少时间 I 题解
  • 前端三大件---CSS
  • 上海楼市“银四”兑现:新房市场高端改善领跑,二手房量价企稳回升
  • 股价两天涨超30%,中航成飞:不存在应披露而未披露的重大事项
  • 教育部、国家发改委联合启动实施教师教育能力提升工程
  • 李公明︱一周书记:浪漫主义为什么……仍然重要?
  • 陈丹燕:赤龙含珠
  • 前瞻|美联储明晨“按兵不动”几无悬念:关税战阴霾下,会否释放降息信号