百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

OCR图片预处理之去除印章(一)

ztj100 2024-12-12 16:13 9 浏览 0 评论

导读

在做OCR票据类识别的时候经常会遇到一些票据上会有印章,而对于的文字检测文字识别模型而言,印章的存在一定会影响模型识别的准确率,所以通常我们都是先将图片去除印章之后,再将图片送入到文字检测和文字识别模型中。

本篇文章就介绍一个比较简单的方法用来去除红色印章

移除红色印章

我们通过分离图片的通道提取图片的红色通道,然后再通过阈值来去除红色的印章

import cv2
import numpy as np


def remove_red_seal(input_img):
    # 分离图片的通道
    blue_c, green_c, red_c = cv2.split(input_img)
    #利用大津法自动选择阈值
    thresh, ret = cv2.threshold(red_c, 0, 255,cv2.THRESH_OTSU)
    #对阈值进行调整
    filter_condition = int(thresh * 0.90)
    #移除红色的印章
    _, red_thresh = cv2.threshold(red_c, filter_condition, 255, cv2.THRESH_BINARY)
    # 把图片转回3通道
    result_img = np.expand_dims(red_thresh, axis=2)
    result_img = np.concatenate((result_img, result_img, result_img), axis=-1)

    return result_img

input_img = cv2.imread("1.jpg")
remove_seal = remove_red_seal(input_img)
cv2.imwrite("remove_seal.jpg",remove_seal)

注意:对于不同的场景,你可能需要对阈值进行微调(百分比),以获取你认为的最佳阈值,百分比越小红色印章移除的越干净,同时也有可能会移除部分文字信息。

threshold函数

threshold(src, thresh, maxval, type[, dst])->ret,dst

  • src::灰度图或单通道图片
  • thresh:阈值
  • maxval:最大值
  • type:阈值类型

这里重点介绍一下type参数的取值,它的取值如下图所示

在对图片做二值化处理的时候需要设置一个阈值来对图片进行二值化处理,然而在部分复杂的场景下,如果采用固定的阈值可能在某些场景下效果不错,换到有些场景时效果就不行了。

这时候我们就会想要用自动的阈值,这时候就可以用到THRESH_OTSUTHRESH_TRIANGLE这两个参数,它们会根据图片的灰度直方图来计算出一个阈值将图片分为前景和背景,下面我们来介绍一下它们是如何实现的。

THRESH_OTSU

大津法(OTSU):也被称为是最大类间差法,被认为是图像分割阈值选择的最佳算法,计算简单,鲁棒性较好,不受图像亮度和和对比度的影响,因此在数字图像处理中被广泛的使用。

它根据图像的灰度直方图,将图像分为前景背景两个部分。因为方差是度量图像灰度分布是否均匀,如果图像的背景和前景之间的差别越大,那么它们之间的类间方差差距也会越大。所以,如果我们能够保证图像前景和背景的灰度直方图方差差距最大时,就能让前景和背景分离的效果达到最佳,实际效果还是取决于具体的场景,可能需要根据不同的需求对阈值进行微调。

  • 公式推导

其实只要抓住大津法的核心思想最大化前景和背景的方差要推导公式用代码来实现并不难,接下来我们来推导一下这个公式。

假设灰度T是图像分割前景和背景的最佳阈值,图像上任意一点属于前景的概率为ω1,属于背景的概率为ω2。图像前景的平均灰度值为μ1?,背景的平均灰度值为μ2?,所以图像的平均灰度值μ为

根据类间的方差计算公式,前景和背景的类间方差计算如下

因为

结合上面3个式子可得

为了方便我们后面编程来实现,还需要对上式做一些调整,这里引入几个参数pi表示灰度值等于i的概率,图像的灰度取值在[ 0 , 255 ] 范围内取整数。假设灰度值t可以使图像前景和背景的方差最大,m1?为灰度级t tt的累加均值,m为图像的灰度级L的均值累加

可得μ1和μ2

接下来我们对δ2 结合上面的式子做个变换

我们只需要使上式最大化即可

  • 代码实现OTSU

上面我们推导了大津法的公式,以及如何来求解阈值划分前景和背景,下面我们用python来实现这个算法

比较一下我们自己实现的大津法opencv内置的函数

最终两者输出的阈值都是160,不过python实现的代码是opencv时间的25倍左右,所以python在这方面对比c确实是硬伤。

THRESH_TRIANGLE

三角法(TRIANGLE):是基于直方图利用几何的方法来求分割的最佳阈值,假设的成立条件是直方图的最大波峰在靠近最亮的一侧,然后再通过三角形来求解最大的距离找到最佳阈值。

如图所示,在灰度直方图上,从最高峰bmax?到最暗对应直方图的bmin?构造一条直线,然后从bmin ?到bmax?开始计算到直线的垂直距离d,当d达到最大时,此时所对应的灰度值t就是分割图像的最佳阈值

接下来我们看看,使用三角法求解阈值值的整个流程,这里引入两个参数灰度级L和频率f:

  1. 将图片转换为灰度图,通过OpenCV可以很容易实现
  2. 计算灰度图的灰度直方图,也就是每个灰度级L对应的频率f
  3. 对灰度直方图进行排序,按灰度级进行排序,由小到大
  4. 确定直方图最大值(也就是f)所对应灰度级L的位置,如果在左侧(灰度值小)就需要对灰度直方图进行翻转
  5. 根据左侧边界的灰度级点( Lmin , fmin)和最亮部分频率最大对应的灰度级点( Lmax , fmax) ,由两点式我们可以确定这条直线
  6. 计算Lmin?到Lmax?的任意一点(L, f )到直线的距离d,当d最大时所对应的L就是我们要求的最佳阈值
  • 代码实现

大津法和三角法的对比

  • 共同点:两者都是算法自动计算出阈值,不需要指定阈值
  • 不同点:大津法适合双波峰的灰度直方图,三角法适合单波峰的灰度直方图

opencv显示灰度直方图

参考:

  1. https://blog.csdn.net/weixin_40647819/article/details/90179953
  2. https://www.cnblogs.com/ZFJ1094038955/p/12027836.html
  3. https://blog.csdn.net/qq_45769063/article/details/107102117

相关推荐

SpringBoot如何实现优雅的参数校验
SpringBoot如何实现优雅的参数校验

平常业务中肯定少不了校验,如果我们把大量的校验代码夹杂到业务中,肯定是不优雅的,对于一些简单的校验,我们可以使用java为我们提供的api进行处理,同时对于一些...

2025-05-11 19:46 ztj100

Java中的空指针怎么处理?

#暑期创作大赛#Java程序员工作中遇到最多的错误就是空指针异常,无论你多么细心,一不留神就从代码的某个地方冒出NullPointerException,令人头疼。...

一坨一坨 if/else 参数校验,被 SpringBoot 参数校验组件整干净了

来源:https://mp.weixin.qq.com/s/ZVOiT-_C3f-g7aj3760Q-g...

用了这两款插件,同事再也不说我代码写的烂了

同事:你的代码写的不行啊,不够规范啊。我:我写的代码怎么可能不规范,不要胡说。于是同事打开我的IDEA,安装了一个插件,然后执行了一下,规范不规范,看报告吧。这可怎么是好,这玩意竟然给我挑出来这么...

SpringBoot中6种拦截器使用场景

SpringBoot中6种拦截器使用场景,下面是思维导图详细总结一、拦截器基础...

用注解进行参数校验,spring validation介绍、使用、实现原理分析

springvalidation是什么在平时的需求开发中,经常会有参数校验的需求,比如一个接收用户注册请求的接口,要校验用户传入的用户名不能为空、用户名长度不超过20个字符、传入的手机号是合法的手机...

快速上手:SpringBoot自定义请求参数校验

作者:UncleChen来源:http://unclechen.github.io/最近在工作中遇到写一些API,这些API的请求参数非常多,嵌套也非常复杂,如果参数的校验代码全部都手动去实现,写起来...

分布式微服务架构组件

1、服务发现-Nacos服务发现、配置管理、服务治理及管理,同类产品还有ZooKeeper、Eureka、Consulhttps://nacos.io/zh-cn/docs/what-is-nacos...

优雅的参数校验,告别冗余if-else

一、参数校验简介...

Spring Boot断言深度指南:用断言机制为代码构筑健壮防线

在SpringBoot开发中,断言(Assert)如同代码的"体检医生",能在上线前精准捕捉业务逻辑漏洞。本文将结合企业级实践,解析如何通过断言机制实现代码自检、异常预警与性能优化三...

如何在项目中优雅的校验参数

本文看点前言验证数据是贯穿所有应用程序层(从表示层到持久层)的常见任务。通常在每一层实现相同的验证逻辑,这既费时又容易出错。为了避免重复这些验证,开发人员经常将验证逻辑直接捆绑到域模型中,将域类与验证...

SpingBoot项目使用@Validated和@Valid参数校验

一、什么是参数校验?我们在后端开发中,经常遇到的一个问题就是入参校验。简单来说就是对一个方法入参的参数进行校验,看是否符合我们的要求。比如入参要求是一个金额,你前端没做限制,用户随便过来一个负数,或者...

28个验证注解,通过业务案例让你精通Java数据校验(收藏篇)

在现代软件开发中,数据验证是确保应用程序健壮性和可靠性的关键环节。JavaBeanValidation(JSR380)作为一个功能强大的规范,为我们提供了一套全面的注解工具集,这些注解能够帮...

Springboot @NotBlank参数校验失效汇总

有时候明明一个微服务里的@Validated和@NotBlank用的好好的,但就是另一个里不能用,这时候问题是最不好排查的,下面列举了各种失效情况的汇总,供各位参考:1、版本问题springbo...

这可能是最全面的Spring面试八股文了

Spring是什么?Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。...

取消回复欢迎 发表评论: