阅读本文可能会解决的问题:
① Java识别验证码
② Tess4J的使用和OCR识别
③ JavaCV的使用二值化和灰度测试
④ Java裁剪和缩放图片
⑤ 如何生成数字&字母验证码
⑥ ...
这里老样子先说几句无关的话,去年毕业的时候帮同学做了一个验证码识别系统,按部就班的参考了大神的操作,对于二值化这些操作都没有深入了解,最近做项目遇到了要实现机器登录的操作,验证码自然绕不过去所以就又翻出来参考总结一下,方便自己也分享给大家。同时我也发现现在除了一些政府网站外,基本很少有采用下面我列出的这种数字&字母验证码了,所以针对项目需求做的这个识别可能目前并没有什么参考价值,但是在学习的过程中也了解了很多比如Tess4J和JavaCV这些技术,图像处理比如缩放和裁剪等,话不多说,下面就搞起吧。
一、常见的验证码识别
1.常见验证码
这里我主要针对第四种验证码进行识别,其实试验后我发现前面三个都是可以识别的,只是裁剪和二值化的阈值需要调整。
2.识别思路
输入原始验证码之后,先对图片进行干扰像素去除,再裁剪边角,最后利用Tess4J进行识别。
3.主要代码
main方法调用具体实现方法
public static void main(String[] args){
//原始验证码地址
String OriginalImg = "C:\\mysoftware\\images\\upload\\OcrImg\\oi.jpg";
//识别样本输出地址
String ocrResult = "C:\\mysoftware\\images\\upload\\OcrResult\\or.jpg";
//去噪点
ImgUtils.removeBackground(OriginalImg, ocrResult);
//裁剪边角
ImgUtils.cuttingImg(ocrResult);
//OCR识别
String code = Tess4J.executeTess4J(ocrResult);
//输出识别结果
System.out.println("Ocr识别结果: \n" + code);
}
其中removeBackground方法去除验证码噪点,首先我定义了一个临界阈值,这个值代表像素点的亮度,我们在实际扫描验证码的每一个像素块时通过判断该像素块的亮度(获取该像素块的三原色)是否超过该自定义值,从而判断出是否删除或保留该像素块,因此针对不同的验证码我们可以调整这个阈值,比如像我上面列出的几种验证码波动一般都在100~600之间,通过测试就得出一个比较适中的阈值可以大大提高验证码的提纯度。
public static void removeBackground(String imgUrl, String resUrl){
//定义一个临界阈值
int threshold = 300;
try{
BufferedImage img = ImageIO.read(new File(imgUrl));
int width = img.getWidth();
int height = img.getHeight();
for(int i = 1;i < width;i++){
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
Color color = new Color(img.getRGB(x, y));
System.out.println("red:"+color.getRed()+" | green:"+color.getGreen()+" | blue:"+color.getBlue());
int num = color.getRed()+color.getGreen()+color.getBlue();
if(num >= threshold