Java实现去除文档阴影的示例代码

 更新时间:2022年12月08日 09:14:29   作者:ZackSock  
文稿扫描大家用的都比较频繁、想是各种证件、文件都可以通过扫描文稿功能保存到手机。相比直接拍照,在扫描文稿时,程序会对图像进行一些矫正。比如去除阴影、修正倾斜、旋转矫正等。进行这些处理后的图片要更加容易识别。今天就来讨论一下去除阴影的操作

一、前言

文稿扫描大家用的都比较频繁、想是各种证件、文件都可以通过扫描文稿功能保存到手机。相比直接拍照,在扫描文稿时,程序会对图像进行一些矫正。比如去除阴影、修正倾斜、旋转矫正等。进行这些处理后的图片要更加容易识别。今天就来讨论以下去除阴影的操作。

二、实现原理

1. 图像

在开始实现前,我们来了解一些图像相关的知识。这里讨论RGB图像,也就是我们俗称的彩色的图像。图像可以被看作是一个height×width的数组,每一个数表示一个像素。如果是彩色的图像,每个像素会包含RBG三个值,最低字节表示G、次低字节表示B、第三字节表示R。

比如像素值为:

0x00ff00

其RBG值分别为:

R: 0x00
G: 0xff
B: 0x00

如果想要从原像素中取RGB的值,可以使用按位与操作,示例如下:

// pixel是从图像中取出来的数
int[] rgb = new int[3];
rgb[0] = (pixel & 0xff0000) >> 16;
rgb[1] = (pixel & 0xff00) >> 8;
rgb[2] = (pixel & 0xff); 

因为获取R和G的时候,保留的是高位,我们希望得到的是一个低位的数据,因此向右移一定位。

2. 灰度转换

有时候,为了方便处理会把图像转换成灰度图像。转换成灰度图像的方法有很多,一种非常简单的办法就是让rgb三个通道都为同样的值,这个值就是rgb三个值的均值。

3.阈值处理

阈值处理是今天关键部分,阈值处理的思想非常简单,就是当图像像素值大于阈值时将其处理为最大值,当像素小于等于阈值时将其处理为0。这样可以得到一张完全的黑白图像。

在文稿中,文字部分可以看作是黑色,背景部分可以看作是白色,而阴影则是介于黑白之间的值。如果想要去除阴影,则需要对图像进行阈值处理,把阈值设定为小于阴影的值。比如下图:

左图是原图,其中灰色部分为阴影,需要去除。这时我们对图像进行阈值处理,把阈值设定为50,那么阴影部分就会被设置成255,文字部分和背景部分变换都不大,这样就实现了文稿的阴影去除工作。

三、代码实现

1.读取图像

首先来看看如何读取图像以及如何访问图像的像素,这里使用ImageIO类。代码如下:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class DocumentDealing {

    public static void main(String[] args) throws Exception {
        String imagePath = "D:/images/imgs/10000.jpeg";
        BufferedImage bi = ImageIO.read(new File(imagePath));
        //获取图片宽高
        int width = bi.getWidth();
        int height = bi.getHeight();
        System.out.println("width:" + width + ",height:" + height);
        //获取坐标为(0, 0)位置的像素
        int pixel = bi.getRGB(0, 0);
        System.out.println("pixel" + pixel);
        //获取rgb值
        int[] rgb = new int[3];
        rgb[0] = (pixel & 0xff0000) >> 16;
        rgb[1] = (pixel & 0xff00) >> 8;
        rgb[2] = pixel & 0xff;
        System.out.println(
                "r:" + rgb[0] +
                        "\tg:" + rgb[1] +
                        "\tb:" + rgb[2]
        );
    }

    public static int[] getRgb(BufferedImage bi, int x, int y) {
        int[] rgb = new int[3];
        int pixel = bi.getRGB(x, y);
        rgb[0] = (pixel & 0xff0000) >> 16;
        rgb[1] = (pixel & 0xff00) >> 8;
        rgb[2] = (pixel & 0xff);
        return rgb;
    }

}

我们可以通过下面代码读取图片,其中imagePath是图片路径:

BufferedImage bi = ImageIO.read(new File(imagePath));

BufferedImage可以获取图片的宽、高、某个点的像素等。为了方便,编写一个getRgb来把pixel转成一个rgb数组。代码输出结果如下:

width:400,height:400
pixel-2853206
r:212    g:118    b:170

2.阈值处理

知道了上面的基本操作后,就可以开始进行阈值处理了。阈值处理就是求rgb均值mean,如果mean大于阈值,则把像素设置为0xffffff,否则设置为0。具体代码如下:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class DocumentDealing {

    public static void main(String[] args) throws Exception {
        String imagePath = "C:/Users/Administrator/Desktop/document.jpg";
        threshold(imagePath, "result.jpg", 50);
    }

    public static void threshold(String imagePath, String savePath, int threshold) throws Exception{
      	//读取图片
        BufferedImage bi = ImageIO.read(new File(imagePath));
        //读取宽高
      	int width = bi.getWidth();
        int height = bi.getHeight();
      	//遍历图片像素
        for(int y = 0; y < height; y ++){
            for(int x = 0; x < width; x ++){
                int[] rgb = getRgb(bi, x, y);
              	//计算rgb均值
                int grayScale = (rgb[0] + rgb[1] + rgb[2]) / 3;
              	//如果均值大于阈值,则赋值将该像素设置为0xffffff(全白),否则赋值为0(全黑)
                if(grayScale > threshold){
                  	bi.setRgb(x, y, 0xffffff);
                }else{
                  	bi.setRgb(x, y, 0);
                }
            }
        }
      	//保存图片
        ImageIO.write(bi, "jpg", new File(savePath));
    }

    public static int[] getRgb(BufferedImage bi, int x, int y){
        int[] rgb = new int[3];
        int pixel = bi.getRGB(x, y);
        rgb[0] = (pixel & 0xff0000) >> 16;
        rgb[1] = (pixel & 0xff00) >> 8;
        rgb[2] = (pixel & 0xff);
        return rgb;
    }

}

下图是原图和处理后的结果:

左图中有两处阴影,右侧则去除了阴影。最终效果图与设定的阈值有关系,当阈值设置不恰当时,会导致结果图比原图更糟糕,或者导致最终文字目标也被去除了。这里可以用循环来解决,代码如下:

public static void main(String[] args) throws Exception {
    String imagePath = "C:/Users/Administrator/Desktop/document.jpg";
      for (int i = 50; i < 127; i++) {
        threshold(imagePath, "imgs/result" + i + ".jpg", i);
      }
}

大家可以自行测试。有时候之间阈值处理不能很好的去除阴影,这个时候会结合一些其它办法。包括滤波操作、形态学处理等。

到此这篇关于Java实现去除文档阴影的示例代码的文章就介绍到这了,更多相关Java去除文档阴影内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解在java中进行日期时间比较的4种方法

    详解在java中进行日期时间比较的4种方法

    这篇文章主要介绍了详解在java中进行日期时间比较的4种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • SpringBoot+easypoi实现数据的Excel导出

    SpringBoot+easypoi实现数据的Excel导出

    这篇文章主要为大家详细介绍了SpringBoot+easypoi实现数据的Excel导出,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • spring mvc利用ajax向controller传递对象的方法示例

    spring mvc利用ajax向controller传递对象的方法示例

    这篇文章主要给大家介绍了关于spring mvc利用ajax向controller传递对象的相关资料,文中通过示例代码将步骤介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来跟着小编一起学习学习吧。
    2017-07-07
  • 浅析idea生成war包放入tomcat的路径访问问题

    浅析idea生成war包放入tomcat的路径访问问题

    这篇文章主要介绍了关于idea 生成war 包放入tomcat的路径访问问题,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • SpringBoot整合RocketMQ的详细过程

    SpringBoot整合RocketMQ的详细过程

    这篇文章主要介绍了SpringBoot整合RocketMQ的详细过程,本文分为三部分,第一部分实现SpringBoot与RocketMQ的整合,第二部分解决在使用RocketMQ过程中可能遇到的一些问题并解决他们,第三部分介绍如何封装RocketMQ以便更好地使用,需要的朋友可以参考下
    2023-04-04
  • Knife4j 3.0.3 整合SpringBoot 2.6.4的详细过程

    Knife4j 3.0.3 整合SpringBoot 2.6.4的详细过程

    本文要讲的是 Knife4j 3.0.3 整合SpringBoot 2.6.4,在SpringBoot 2.4以上的版本和之前的版本还是不一样的,这个也容易导致一些问题,本文就这两个版本的整合做一个实战介绍
    2022-09-09
  • 基于java流实现压缩图片过程解析

    基于java流实现压缩图片过程解析

    这篇文章主要介绍了基于java流实现压缩图片过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • SpringBoot中@RestControllerAdvice注解实现全局异常处理类

    SpringBoot中@RestControllerAdvice注解实现全局异常处理类

    这篇文章主要介绍了SpringBoot中@RestControllerAdvice注解全局异常处理类,springboot中使用@RestControllerAdvice注解,完成优雅的全局异常处理类,可以针对所有异常类型先进行通用处理后再对特定异常类型进行不同的处理操作,需要的朋友可以参考下
    2024-01-01
  • MyBatis通过BATCH批量提交的方法

    MyBatis通过BATCH批量提交的方法

    今天小编就为大家分享一篇关于MyBatis通过BATCH批量提交的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Mybatis环境搭建和使用实例代码

    Mybatis环境搭建和使用实例代码

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。本文重点给大家介绍Mybatis的环境搭建和使用实例代码,需要的朋友参考下吧
    2017-12-12

最新评论