Java實現(xiàn)去除文檔陰影的示例代碼
一、前言
文稿掃描大家用的都比較頻繁、想是各種證件、文件都可以通過掃描文稿功能保存到手機。相比直接拍照,在掃描文稿時,程序會對圖像進行一些矯正。比如去除陰影、修正傾斜、旋轉(zhuǎn)矯正等。進行這些處理后的圖片要更加容易識別。今天就來討論以下去除陰影的操作。
二、實現(xiàn)原理
1. 圖像
在開始實現(xiàn)前,我們來了解一些圖像相關的知識。這里討論RGB圖像,也就是我們俗稱的彩色的圖像。圖像可以被看作是一個height×width的數(shù)組,每一個數(shù)表示一個像素。如果是彩色的圖像,每個像素會包含RBG三個值,最低字節(jié)表示G、次低字節(jié)表示B、第三字節(jié)表示R。

比如像素值為:
0x00ff00
其RBG值分別為:
R: 0x00
G: 0xff
B: 0x00
如果想要從原像素中取RGB的值,可以使用按位與操作,示例如下:
// pixel是從圖像中取出來的數(shù) int[] rgb = new int[3]; rgb[0] = (pixel & 0xff0000) >> 16; rgb[1] = (pixel & 0xff00) >> 8; rgb[2] = (pixel & 0xff);
因為獲取R和G的時候,保留的是高位,我們希望得到的是一個低位的數(shù)據(jù),因此向右移一定位。
2. 灰度轉(zhuǎn)換
有時候,為了方便處理會把圖像轉(zhuǎn)換成灰度圖像。轉(zhuǎn)換成灰度圖像的方法有很多,一種非常簡單的辦法就是讓rgb三個通道都為同樣的值,這個值就是rgb三個值的均值。
3.閾值處理
閾值處理是今天關鍵部分,閾值處理的思想非常簡單,就是當圖像像素值大于閾值時將其處理為最大值,當像素小于等于閾值時將其處理為0。這樣可以得到一張完全的黑白圖像。
在文稿中,文字部分可以看作是黑色,背景部分可以看作是白色,而陰影則是介于黑白之間的值。如果想要去除陰影,則需要對圖像進行閾值處理,把閾值設定為小于陰影的值。比如下圖:

左圖是原圖,其中灰色部分為陰影,需要去除。這時我們對圖像進行閾值處理,把閾值設定為50,那么陰影部分就會被設置成255,文字部分和背景部分變換都不大,這樣就實現(xiàn)了文稿的陰影去除工作。
三、代碼實現(xiàn)
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轉(zhuǎn)成一個rgb數(shù)組。代碼輸出結(jié)果如下:
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;
}
}
下圖是原圖和處理后的結(jié)果:

左圖中有兩處陰影,右側(cè)則去除了陰影。最終效果圖與設定的閾值有關系,當閾值設置不恰當時,會導致結(jié)果圖比原圖更糟糕,或者導致最終文字目標也被去除了。這里可以用循環(huán)來解決,代碼如下:
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);
}
}大家可以自行測試。有時候之間閾值處理不能很好的去除陰影,這個時候會結(jié)合一些其它辦法。包括濾波操作、形態(tài)學處理等。
到此這篇關于Java實現(xiàn)去除文檔陰影的示例代碼的文章就介紹到這了,更多相關Java去除文檔陰影內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
在IDEA中配置tomcat并創(chuàng)建tomcat項目的圖文教程
這篇文章主要介紹了在IDEA中配置tomcat并創(chuàng)建tomcat項目的圖文教程,需要的朋友可以參考下2020-07-07
詳解Java8與Runtime.getRuntime().availableProcessors()
這篇文章主要介紹了詳解Java8與Runtime.getRuntime().availableProcessors(),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06
SpringBoot項目多層級多環(huán)境yml設計詳解
這篇文章主要為大家介紹了SpringBoot項目多層級多環(huán)境yml設計詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
Java創(chuàng)建對象之顯示創(chuàng)建與隱式創(chuàng)建
在本篇文章中,小編會帶大家學習面向?qū)ο笾嘘P于對象的創(chuàng)建之顯示創(chuàng)建和隱式創(chuàng)建,其實類和對象作為面向?qū)ο笾凶罨镜?,也是最重要?需要的朋友可以參考下2023-05-05

