Java簡單驗證碼識別(附原始碼)
阿新 • • 發佈:2019-01-01
學習目的:熟悉java類集與IO流操作,熟悉影象基本知識
可識別的圖形:
思路:這個驗證碼比較規則,數字都是顯示在固定的區域,數字也無粘連,實現步驟如下
1.對影象進行分割,分割成一個影象顯示一個數字
2.對每個影象進行灰化處理,就是設定一個閾值將他們變成黑白圖片
3.建立一個標準的數字影象庫
4.將每個被分割的小圖片與標準庫比較,畫素點重合最多的就是該數字
下面是簡單介面
識別介面:
擷取關鍵原始碼如下(文末有詳細的專案下載地址和可開啟exe檔案):
注意事項:1.標準影象庫是對分割的小圖片一個一個畫素點操作建立的
2.路徑不懂的地方可參考我的上一篇文章
package stringText;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer ;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util .Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageInputStream;
import javax.print.attribute.standard.RequestingUserName;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class temp extends JPanel {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
System.out.println("請選擇你要識別的圖片:");//
temp st = new temp(); // 例項化本類的一個物件
File file = st.getFile(); // 呼叫函式來獲取要識別檔案的路徑
String path = file.getAbsolutePath(); // 獲取要識別檔案的絕對路徑
BufferedImage image; // 儲存要識別的圖片
int result[] = new int[4];// 儲存識別的結果
copyStandardImg();// 將參考的標準圖片複製到D:\image\VerificationCode\temp
result = discernImg(path); // 識別圖片,返回數字給陣列
System.out.print("識別的結果為:");
for (int i = 0; i < 4; i++) { // 輸出結果
System.out.print(result[i]);
}
}
/**
* 從外部讀取檔案地址
*
* @return
*/
public File getFile() {
JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
int returnVal = fc.showOpenDialog(this);
File fileChoosed = fc.getSelectedFile();
return fileChoosed;
}
/**
* 將驗證碼參考的標準圖片複製到D:\image\VerificationCode\temp目錄下
*
* @throws IOException
*/
public static void copyStandardImg() throws IOException {
File sf = new File("d:\\image\\VerificationCode\\temp\\");// 建立儲存標準圖片的資料夾
if (!sf.exists()) { // 如果不存在則建立
sf.mkdirs();
}
temp st = new temp(); // 例項化本類的一個物件
for (int i = 0; i < 10; i++) {
String s = i + ".gif"; // 設定檔名
InputStream is = st.getClass().getResourceAsStream("/image/" + s); // 讀取包裡面的檔案流
// 1K的資料緩衝
byte[] bs = new byte[1024];
// 讀取到的資料長度
int len;
OutputStream os = new FileOutputStream(sf.getPath() + "\\" + s); // 新建輸出檔案
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len); // 將輸出流寫到檔案
}
}
}
/**
* 傳入要識別的圖片,返回識別的數字
*/
public static int[] discernImg(String imgPath) {
int result[] = new int[4]; // 儲存結果的陣列
try {
BufferedImage image; // 用來儲存圖片
image = ImageIO.read(new File(imgPath)); // 讀取圖片
List<BufferedImage> bufImgList = new ArrayList<BufferedImage>(); // 儲存分割的圖片
bufImgList = splitImage(image); // 分割圖片
for (int i = 0; i < 4; i++) {
bufImgList.set(i, removeBackgroudMin(bufImgList.get(i))); // 對每張圖片灰度化
result[i] = decideImgNumber(bufImgList.get(i)); // 識別每張小圖的數字
}
} catch (Exception e) {
// TODO: handle exception
}
return result;
}
/**
* 分割圖片,並返回圖片列表
*
* @param img
* @return
* @throws Exception
*/
public static List<BufferedImage> splitImage(BufferedImage img) throws Exception {
List<BufferedImage> subImgs = new ArrayList<BufferedImage>();
subImgs.add(img.getSubimage(7, 5, 9, 12));// 擷取的起始座標,圖片大小為9x12,起始座標為(7,5)
subImgs.add(img.getSubimage(16, 5, 9, 12));
subImgs.add(img.getSubimage(25, 5, 9, 12));
subImgs.add(img.getSubimage(34, 5, 9, 12));
return subImgs;
}
/**
* 預處理驗證碼圖片,小圖片變為黑白
*
* @param picFile
* @return
* @throws Exception
*/
public static BufferedImage removeBackgroudMin(BufferedImage img) throws Exception {
int width = img.getWidth(); // 獲取圖片的高度與寬度
int height = img.getHeight();
for (int x = 0; x < height; ++x) {
for (int y = 0; y < width; ++y) {
if (isWhite(img.getRGB(y, x)) == 1) { // 判斷該設為白色則設為白色
img.setRGB(y, x, Color.WHITE.getRGB()); // 設為白色
} else {
img.setRGB(y, x, Color.BLACK.getRGB()); // 設為黑色
}
}
}
return img;
}
/**
* 儲存圖片(可指定儲存檔案路徑和檔名)
*
* @param bufImg
* @param savePath
* @param saveName
*/
public static void saveImage(BufferedImage bufImg, String savePath, String saveName) {
try {
int width = bufImg.getWidth(); // 獲取傳入圖片的寬度
int height = bufImg.getHeight();// 獲取傳入圖片的高度
Graphics g = bufImg.getGraphics();// 再建立一個Graphics變數,用來畫出來要保持的圖片,及上面傳遞過來的Image變數
g.drawImage(bufImg, 0, 0, null); // 繪製圖片到新建的圖片
ImageIO.write(bufImg, "gif", new File(savePath + saveName));// 將BufferedImage變數寫入檔案中。
} catch (Exception e) {
// TODO: handle exception
}
}
/**
* 預處理驗證碼圖片,小圖片變為黑白
*
* @param picFile
* @return
* @throws Exception
*/
public static BufferedImage removeBackgroudMin(String picFile) throws Exception {
BufferedImage img = ImageIO.read(new File(picFile));
int width = img.getWidth();
int height = img.getHeight();
for (int x = 0; x < height; ++x) {
for (int y = 0; y < width; ++y) {
if (isWhite(img.getRGB(y, x)) == 1) {
img.setRGB(y, x, Color.WHITE.getRGB());
} else {
img.setRGB(y, x, Color.BLACK.getRGB());
}
}
}
return img;
}
public static int isBlack(int colorInt) {
Color color = new Color(colorInt); // 例項化顏色類
if (color.getRed() + color.getGreen() + color.getBlue() <= 100) {// 設定閾值,來判斷該畫素是否是黑色
return 1; // 是白色則返回1
}
return 0;// 不是白色,則返回0
}
/**
* 判斷當前畫素點的顏色是否是白色
*
* @param colorInt
* @return
*/
public static int isWhite(int colorInt) {
Color color = new Color(colorInt); // 例項化顏色類
if (color.getRed() + color.getGreen() + color.getBlue() > 450) {// 設定閾值,來判斷該畫素是否是黑色
return 1; // 是白色則返回1
}
return 0; // 不是白色則返回0
}
/**
* 根據畫素點RGB的值來返回畫素點各值之和
*/
public static int getRgbalue(int colorInt) {
Color color = new Color(colorInt); // 例項化顏色類
if ((color.getRed() + color.getGreen() + color.getBlue() > 0))
return 0;// 設定閾值,來判斷該畫素是否是黑色
return 1;
}
/**
* 繪製數字畫素標準模版,通過對被分割和灰話的圖片進行更改(臨時函式)
*
* @throws IOException
*/
public static void drawStandardTemplate(int n) throws IOException {
int width = 9; // 獲取傳入圖片的寬度
int height = 12;// 獲取傳入圖片的高度
BufferedImage standardPicture;
// BufferedImage standardPicture1 = new BufferedImage(width, height,
// BufferedImage.TYPE_3BYTE_BGR); // 新建處理後的圖片
// Graphics g = standardPicture1.getGraphics();//
// 再建立一個Graphics變數,用來畫出來要保持的圖片,及上面傳遞過來的Image變數
// g.drawImage(standardPicture1, 0, 0, null); // 繪製圖片到新建的圖片
switch (n) {
case 0: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第4張.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\0.gif");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(5, 0, Color.WHITE.getRGB());
standardPicture.setRGB(6, 0, Color.WHITE.getRGB());
standardPicture.setRGB(6, 1, Color.WHITE.getRGB());
standardPicture.setRGB(0, 2, Color.BLACK.getRGB());
standardPicture.setRGB(3, 2, Color.WHITE.getRGB());
standardPicture.setRGB(2, 6, Color.WHITE.getRGB());
standardPicture.setRGB(3, 8, Color.WHITE.getRGB());
standardPicture.setRGB(6, 10, Color.WHITE.getRGB());
standardPicture.setRGB(5, 11, Color.WHITE.getRGB());
standardPicture.setRGB(8, 11, Color.WHITE.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\0.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 1: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張驗證碼分割12.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\1.gif");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(5, 0, Color.BLACK.getRGB());
standardPicture.setRGB(2, 1, Color.BLACK.getRGB());
standardPicture.setRGB(8, 1, Color.WHITE.getRGB());
standardPicture.setRGB(5, 2, Color.BLACK.getRGB());
standardPicture.setRGB(8, 2, Color.WHITE.getRGB());
standardPicture.setRGB(5, 3, Color.BLACK.getRGB());
standardPicture.setRGB(5, 4, Color.BLACK.getRGB());
standardPicture.setRGB(3, 5, Color.BLACK.getRGB());
standardPicture.setRGB(5, 5, Color.BLACK.getRGB());
standardPicture.setRGB(5, 6, Color.BLACK.getRGB());
standardPicture.setRGB(3, 7, Color.BLACK.getRGB());
standardPicture.setRGB(7, 8, Color.WHITE.getRGB());
standardPicture.setRGB(0, 9, Color.WHITE.getRGB());
standardPicture.setRGB(3, 9, Color.BLACK.getRGB());
standardPicture.setRGB(5, 10, Color.BLACK.getRGB());
standardPicture.setRGB(3, 11, Color.BLACK.getRGB());
standardPicture.setRGB(5, 11, Color.BLACK.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\1.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 2: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張驗證碼分割10.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(1, 0, Color.WHITE.getRGB());
standardPicture.setRGB(5, 0, Color.WHITE.getRGB());
standardPicture.setRGB(6, 0, Color.WHITE.getRGB());
standardPicture.setRGB(7, 0, Color.WHITE.getRGB());
standardPicture.setRGB(7, 4, Color.WHITE.getRGB());
standardPicture.setRGB(2, 5, Color.WHITE.getRGB());
standardPicture.setRGB(2, 6, Color.WHITE.getRGB());
standardPicture.setRGB(7, 7, Color.WHITE.getRGB());
standardPicture.setRGB(7, 8, Color.WHITE.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\2.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 3: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張驗證碼分割14.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(5, 0, Color.WHITE.getRGB());
standardPicture.setRGB(7, 0, Color.WHITE.getRGB());
standardPicture.setRGB(6, 0, Color.WHITE.getRGB());
standardPicture.setRGB(7, 0, Color.WHITE.getRGB());
standardPicture.setRGB(6, 3, Color.BLACK.getRGB());
standardPicture.setRGB(1, 5, Color.WHITE.getRGB());
standardPicture.setRGB(2, 5, Color.WHITE.getRGB());
standardPicture.setRGB(6, 5, Color.BLACK.getRGB());
standardPicture.setRGB(1, 6, Color.WHITE.getRGB());
standardPicture.setRGB(2, 6, Color.WHITE.getRGB());
standardPicture.setRGB(3, 6, Color.WHITE.getRGB());
standardPicture.setRGB(7, 7, Color.WHITE.getRGB());
standardPicture.setRGB(1, 8, Color.WHITE.getRGB());
standardPicture.setRGB(7, 8, Color.WHITE.getRGB());
standardPicture.setRGB(2, 9, Color.WHITE.getRGB());
standardPicture.setRGB(0, 10, Color.WHITE.getRGB());
standardPicture.setRGB(1, 11, Color.WHITE.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\3.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 4: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張驗證碼分割15.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(3, 0, Color.WHITE.getRGB());
standardPicture.setRGB(1, 1, Color.WHITE.getRGB());
standardPicture.setRGB(2, 1, Color.WHITE.getRGB());
standardPicture.setRGB(3, 1, Color.BLACK.getRGB());
standardPicture.setRGB(8, 1, Color.WHITE.getRGB());
standardPicture.setRGB(1, 2, Color.WHITE.getRGB());
standardPicture.setRGB(2, 2, Color.WHITE.getRGB());
standardPicture.setRGB(0, 3, Color.WHITE.getRGB());
standardPicture.setRGB(2, 3, Color.BLACK.getRGB());
standardPicture.setRGB(7, 3, Color.WHITE.getRGB());
standardPicture.setRGB(8, 3, Color.WHITE.getRGB());
standardPicture.setRGB(0, 4, Color.WHITE.getRGB());
standardPicture.setRGB(4, 4, Color.WHITE.getRGB());
standardPicture.setRGB(0, 5, Color.BLACK.getRGB());
standardPicture.setRGB(3, 5, Color.WHITE.getRGB());
standardPicture.setRGB(0, 9, Color.WHITE.getRGB());
standardPicture.setRGB(1, 11, Color.WHITE.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\4.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 5: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張驗證碼分割13.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(0, 2, Color.BLACK.getRGB());
standardPicture.setRGB(0, 3, Color.BLACK.getRGB());
standardPicture.setRGB(0, 4, Color.BLACK.getRGB());
standardPicture.setRGB(5, 4, Color.WHITE.getRGB());
standardPicture.setRGB(6, 5, Color.WHITE.getRGB());
standardPicture.setRGB(0, 6, Color.WHITE.getRGB());
standardPicture.setRGB(1, 6, Color.WHITE.getRGB());
standardPicture.setRGB(0, 5, Color.WHITE.getRGB());
standardPicture.setRGB(5, 5, Color.BLACK.getRGB());
standardPicture.setRGB(5, 7, Color.BLACK.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\5.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 6: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(8, 1, Color.WHITE.getRGB());
standardPicture.setRGB(8, 6, Color.WHITE.getRGB());
standardPicture.setRGB(2, 8, Color.WHITE.getRGB());
standardPicture.setRGB(7, 9, Color.WHITE.getRGB());
standardPicture.setRGB(6, 10, Color.WHITE.getRGB());
standardPicture.setRGB(7, 10, Color.WHITE.getRGB());
standardPicture.setRGB(8, 10, Color.WHITE.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\6.gif"));// 將BufferedImage變數寫入檔案中。
}
break;
case 7: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17時20分第3張驗證碼分割16.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(7, 0, Color.WHITE.getRGB());
standardPicture.setRGB(3, 1, Color.BLACK.getRGB());
standardPicture.setRGB(8, 4, Color.WHITE.getRGB());
standardPicture.setRGB(5, 5, Color.WHITE.getRGB());
standardPicture.setRGB(5, 8, Color.WHITE.getRGB());
standardPicture.setRGB(6, 8, Color.WHITE.getRGB());
standardPicture.setRGB(0, 9, Color.WHITE.getRGB());
standardPicture.setRGB(1, 9, Color.WHITE.getRGB());
standardPicture.setRGB(5, 9, Color.WHITE.getRGB());
standardPicture.setRGB(6, 9, Color.WHITE.getRGB());
// for (int x = 0; x < width; ++x) {
// for (int y = 0; y < height; ++y) {
//
// standardPicture.setRGB(x, y, Color.WHITE.getRGB());
// }
// }
ImageIO.write(standardPicture, "gif", new File("d:\\image\\VerificationCode\\standard\\7.gif"));// 將BufferedImage變數寫入檔案中。
}