实时27实战机器学习:图片验证码识别(Java实现)

 

实战机器学习:图片验证码识别(Java实现)

 
 https://ai.baidu.com/sdk#ocr
https://www.pianshen.com/article/4263265085/
https://github.com/tesseract-ocr/tessdata
https://blog.csdn.net/zhulier1124/article/details/80606647
https://www.cnblogs.com/qjmnong/p/10067314.html
 
 
 
 
 

学习目的:熟悉java类集与IO流操作,熟悉图像基本知识
可识别的图形:

该验证码下载网址为:http://www.quanjing.com/createImg.aspx
(这个验证码可以采集,在我上一篇http://blog.csdn.net/q651742112/article/details/76177275有源代码)

思路:这个验证码比较规则,数字都是显示在固定的区域,数字也无粘连,实现步骤如下
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变量写入文件中。
}

break;
case 8: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17时20分第1张.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\8.gif");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(0, 1, Color.WHITE.getRGB());
standardPicture.setRGB(1, 2, Color.BLACK.getRGB());
standardPicture.setRGB(2, 2, Color.BLACK.getRGB());
standardPicture.setRGB(4, 2, Color.BLACK.getRGB());
standardPicture.setRGB(7, 2, Color.WHITE.getRGB());
standardPicture.setRGB(0, 3, Color.BLACK.getRGB());
standardPicture.setRGB(4, 3, Color.WHITE.getRGB());
standardPicture.setRGB(0, 4, Color.BLACK.getRGB());
standardPicture.setRGB(6, 4, Color.BLACK.getRGB());
standardPicture.setRGB(0, 5, Color.WHITE.getRGB());
standardPicture.setRGB(6, 5, Color.WHITE.getRGB());
standardPicture.setRGB(3, 6, Color.BLACK.getRGB());
standardPicture.setRGB(3, 7, Color.BLACK.getRGB());
standardPicture.setRGB(4, 7, Color.BLACK.getRGB());
standardPicture.setRGB(6, 10, Color.WHITE.getRGB());
standardPicture.setRGB(6, 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\\8.gif"));// 将BufferedImage变量写入文件中。
}

break;
case 9: {
standardPicture = ImageIO.read(new File("d:\\image\\VerificationCode\\2017年6月27日17时20分第3张验证码分割17.gif"));
File sf = new File("d:\\image\\VerificationCode\\standard\\");
if (!sf.exists()) {
sf.mkdirs();
}
standardPicture.setRGB(6, 1, Color.WHITE.getRGB());
standardPicture.setRGB(7, 1, Color.WHITE.getRGB());
standardPicture.setRGB(7, 2, Color.WHITE.getRGB());
standardPicture.setRGB(7, 7, Color.WHITE.getRGB());
standardPicture.setRGB(8, 7, Color.WHITE.getRGB());
standardPicture.setRGB(0, 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\\9.gif"));// 将BufferedImage变量写入文件中。
}

break;
default:
break;
}
}

/**
* 图片与图片之间的黑色像素比较
*/
public static int imgToImgCompare(BufferedImage bufImg, BufferedImage standardImg) {
int width = bufImg.getWidth(); // 读取识别图片的高度与宽度
int height = bufImg.getHeight();
int count = 0;
for (int x = 0; x < width; ++x) { // 循环每一个像素
for (int y = 0; y < height; ++y) {
if (bufImg.getRGB(x, y) == standardImg.getRGB(x, y) && bufImg.getRGB(x, y) == Color.BLACK.getRGB()) {// 相等就加一
count++;
}
}
}

return count;
}

/**
* 确认被分割的小图片的数字
*/
public static int decideImgNumber(BufferedImage bufImg) throws Exception {
// try {
// 自己输入的绝对路径
// 读取标准图片
BufferedImage standardImg0 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\0.gif"));
BufferedImage standardImg1 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\1.gif"));
BufferedImage standardImg2 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\2.gif"));
BufferedImage standardImg3 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\3.gif"));
BufferedImage standardImg4 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\4.gif"));
BufferedImage standardImg5 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\5.gif"));
BufferedImage standardImg6 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\6.gif"));
BufferedImage standardImg7 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\7.gif"));
BufferedImage standardImg8 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\8.gif"));
BufferedImage standardImg9 = ImageIO.read(new File("D:\\image\\VerificationCode\\temp\\9.gif"));

int result[] = new int[10]; // 存储与每一个标准图片比较的结果
// 下面为取出比较结果的最大值
int max = 0; // 保存最大值
int site = 0; // 保存识别的数字
for (int i = 0; i < 10; i++) { // 一一识别
switch (i) {
case 0: {
result[i] = imgToImgCompare(bufImg, standardImg0);
}

break;
case 1: {
result[i] = imgToImgCompare(bufImg, standardImg1);
}
break;
case 2: {
result[i] = imgToImgCompare(bufImg, standardImg2);
}
break;
case 3: {
result[i] = imgToImgCompare(bufImg, standardImg3);
}
break;
case 4: {
result[i] = imgToImgCompare(bufImg, standardImg4);
}
break;
case 5: {
result[i] = imgToImgCompare(bufImg, standardImg5);
}
break;
case 6: {
result[i] = imgToImgCompare(bufImg, standardImg6);
}
break;
case 7: {
result[i] = imgToImgCompare(bufImg, standardImg7);
}
break;
case 8: {
result[i] = imgToImgCompare(bufImg, standardImg8);
}
break;
case 9: {
result[i] = imgToImgCompare(bufImg, standardImg9);
}
break;
default:
break;
}

}

for (int i = 0; i < 10; i++) { // 比较大小
if (result[i] > max) {
max = result[i];
site = i;
}
}
return site; // 返回识别的数字
// } catch (Exception e) {
// // TODO: handle exception
// System.out.println(e);
// }
// return 0;
// }
}

}

源代码打包地址:链接:https://download.csdn.net/download/q651742112/10527190
————————————————
版权声明:本文为CSDN博主「q651742112」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/q651742112/article/details/76405504

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

图片验证码识别,简单写下,做个备忘。

 

一、注册百度账号及新增一个应用,获取百度API所需的AppID,API Key,Secret Key三个参数。


访问http://ai.baidu.com,使用百度账号登录后,出现如下界面

成功创建应用后,出现类似如下界面:

 

二、编写Java代码

身份证正反面图片中的文字识别实现步骤如下:

1.下载百度SDK

https://ai.baidu.com/sdk#ocr中,下载java SDK

2.在MyEclipse等开发工具中,创建Java工程

下面以MyEclipse举例,创建的Java工程目录如下:

 

 

3.集成百度SDK

图片验证码识别代码如下,简单几行代码就搞定,具体如下:

 com.zrscsoft.api.baidu;

import java.util.HashMap;

import org.json.JSONObject;

import com.baidu.aip.ocr.AipOcr;
/**
 * 图片验证码识别
 * 
 * @author admin
 *
 */
public class VerificationCodeRecognitionDemo {
    //设置APPID/AK/SK
    public static final String APP_ID = "你的 App ID";
    public static final String API_KEY = "你的 Api Key";
    public static final String SECRET_KEY = "你的 Secret Key";
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
         // 初始化一个AipOcr
        AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);

        // 可选:设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);

        String path = System.getProperty("user.dir");
        String imgPath=path+"/images/VerificationCodeRecognition1.png";//D:\\1.png
        // 识别图片验证码中的数字
        HashMap<String, String> options2 = new HashMap<String, String>();
        options2.put("detect_direction", "true");
        options2.put("detect_language", "true");
        JSONObject res = client.webImage(imgPath, options2);
        System.out.println("识别返回的字符串为:"+res.toString(2));
        System.out.println("识别出来的验证码为:"+res.getJSONArray("words_result").getJSONObject(0).get("words"));
    }

}

4.运行VerificationCodeRecognitionDemo中main()方法,运行后的结果,大致如下:

识别返回的字符串为:{
  "words_result": [{"words": "CMK8"}],
  "direction": 0,
  "words_result_num": 1,
  "log_id": 549443541293277400
}
识别出来的验证码为:CMK8

 

下载源码

 

 

 

要弄OCR,按照官方的一步步来,外网慢的很,一些要下的我已经传到csdn给大家下载。

官网:http://tess4j.sourceforge.net/codesample.html

中文训练库下载地址:
http://download.csdn.net/detail/d_dmelon/9916532
其他语言库:
https://github.com/tesseract-ocr/tessdata

Tess4J3.4下载地址:
http://download.csdn.net/detail/d_dmelon/9916519

安装Visual C++ 2015 Redistributable Packages(官网:The Windows native libraries were built with VS2015 and therefore depend on the Visual C++ 2015 Redistributable Packages.)
http://download.csdn.net/detail/d_dmelon/9916663

环境: JDK1.8 Intellij IDEA
解压Tess4J 3.4.zip文件,拷贝dist目录下的jar文件到IDEA的工程目录(我是新建了一个libs文件夹),拷贝tessdata文件夹到项目工程下(与src文件夹同级),在把中文训练库chi_sim拷贝到这个tessdata文件夹里。

(如果不行的话,使用IDEA-Project Structure-Libraries-绿色加号add,把解压目录的lib路径添加进去编译,我反正根据上述步骤就行了)
demo

package net.sourceforge.tess4j.example;

import java.io.File;
import net.sourceforge.tess4j.*;

public class TesseractExample {

public static void main(String[] args) {
File imageFile = new File("<图片地址>");
ITesseract instance = new Tesseract();
instance.setLanguage("chi_sim");
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
}
}

 

————————————————
版权声明:本文为CSDN博主「pxM_Wxd」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/d_dmelon/article/details/76560600

 

 

 

 

 

 

 

案例:本文主要描述如何使用Java+Selenium+Chromedriver+OCR破解网页登录验证码并根据快递单号查询出民航快递的跟踪信息
解决问题:验证码图片为渲染生成,直接获取仅会得到空白图片,OCR进行图文识别
环境准备:Chrome浏览器、Chrome浏览器驱动文件(chromedriver.exe)
注:chromedriver.exe下载地址:http://chromedriver.storage.googleapis.com/index.html
一、首先创建一个maven工程,配置依赖包

<dependencies>
<!-- selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.14.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>

<dependency>
<groupId>com.asprise.ocr</groupId>
<artifactId>java-ocr-api</artifactId>
<version>[15,)</version>
</dependency>

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.1.0</version>
</dependency>

<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>3.4.0</version>
<exclusions>
<exclusion>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
二、开始写入自动化测试代码

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.util.ImageHelper;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.TimeUnit;

public class Test {

public static void main(String[] args) throws Exception {

//1.获取网页的浏览器driver
//(1)定义url
String url="http://www.cae.com.cn/webfunction/ExpressQuery/default.aspx";
//(2)设置driver驱动chromedriver.exe(版本:2.39)路径(相对路径)
String path = System.getProperty("user.dir");
System.setProperty("webdriver.chrome.driver",path+"\\chromedriver\\window\\chromedriver.exe");
//(3)建立selenium 驱动
//WebDriver driver = new ChromeDriver(options);
WebDriver driver = new ChromeDriver();
//(4)设置窗口最大化及网页等待时间
driver.manage().window().maximize(); //窗口最大化
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//(5)启动driver浏览网页
driver.get(url); //输入网址

//2.设置等待时间
Thread.sleep(1000);

//3.页面交互操作
//(1)输入订单编号
WebElement input = driver.findElement(By.xpath("//*[@id=\"ctl00_Content_Body_TextBox1\"]"));
input.sendKeys("CAE683160622");
//(2)输入验证码
File srcfile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcfile, new File("picture/source.png"));
//原图片
//String soursePicPath = "D:\\data_dev\\test\\test.png";
String soursePicPath = "picture/source.png";
File sourcePic = new File(soursePicPath);

BufferedImage pic1 = ImageIO.read(sourcePic);
BufferedImage pic2 = pic1.getSubimage(738, 280,
105, 30);
//将截取的子图另行存储
//File desImage = new File("D:\\data_dev\\test\\test02.png");
File desImage = new File("picture/answer.png");
ImageIO.write(pic2, "png", desImage);

//加载待读取图片
//File imageFile = new File("D:\\data_dev\\test\\test02.png");
File imageFile = new File("picture/answer.png");
BufferedImage image = ImageIO.read(imageFile);
//对图片进行处理
image = convertImage(image);
//创建tess对象
ITesseract instance = new Tesseract();
//设置训练文件目录
//instance.setDatapath("E:\\workspace\\workspace_idea\\com_mth_data\\m-kuaidi100-data\\tessdata");
String path02 = System.getProperty("user.dir");
instance.setDatapath(path02 + "\\tessdata");
//设置训练语言
//instance.setLanguage("chi_sim");
instance.setLanguage("eng");
//执行转换
String s = instance.doOCR(image);

System.out.println(s);
String[] split = s.replace(" ", "").split("=|:");
String a = split[split.length - 1].trim();
char[] chars = a.toCharArray();
if (chars.length == 2) {
if (chars[0] == '7') {
chars[0] = '1';
}
}
a = String.valueOf(chars);

System.out.println(a);
String b = s.substring(0, 1);
System.out.println(b);
String answer = String.valueOf(Integer.parseInt(a.trim()) - Integer.parseInt(b.trim()));


WebElement input2 = driver.findElement(By.xpath("//*[@id=\"ctl00_Content_Body_TextBox2\"]"));
input2.sendKeys(answer);
Thread.sleep(4000);
//(3)点击"查询"按钮
driver.findElement(By.xpath("//*[@id=\"ctl00_Content_Body_Button1\"]")).click();

String SecondtHandle = driver.getWindowHandle(); //首先得到最先的窗口 权柄
for (String winHandle1 : driver.getWindowHandles()) { //得到浏览器所有窗口的权柄为Set集合,遍历
if (!winHandle1.equals(SecondtHandle)) { //如果为 最先的窗口 权柄跳出
driver.close();
driver.switchTo().window(winHandle1); //如果不为 最先的窗口 权柄,将 新窗口的操作权柄 给 driver
System.out.println(driver.getCurrentUrl()); //打印是否为新窗口
}
}

Thread.sleep(4000);

//4.关闭浏览器
driver.close();

}


//对图片进行处理 - 提高识别度
public static BufferedImage convertImage(BufferedImage image) throws Exception {
//按指定宽高创建一个图像副本
//image = ImageHelper.getSubImage(image, 0, 0, image.getWidth(), image.getHeight());
//图像转换成灰度的简单方法 - 黑白处理
image = ImageHelper.convertImageToGrayscale(image);
//图像缩放 - 放大n倍图像
image = ImageHelper.getScaledInstance(image, image.getWidth() * 15, image.getHeight() * 15);
return image;
}

}
————————————————
版权声明:本文为CSDN博主「揍坦克的小老虎」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51754359/article/details/109454638

 

 

 

 

 

 

 

 

 

posted on 2021-04-10 11:45  shuzihua  阅读(2069)  评论(0编辑  收藏  举报

导航