zoukankan      html  css  js  c++  java
  • Java识别静态验证码和动态验证码

    写了一个简单java工具类,用于验证码点阵打印+自动识别。为了提升识别精度和程序性能,此工具类是针对特定类型的验证码的,若要用于其他类型的验证码识别,需要做相应调整。

    文章分两部分演示了此java工具类如何识别静态验证码图片和动态验证码gif。

    一、静态验证码图片识别

    输入验证码:

    程序运行结果:

    ======= print and recognize captchapic  =======
    "................................................................................",
    "................................................................................",
    "................................................................................",
    "................##.##........#####..............................................",
    "................##.##.......##...##.............................................",
    "................##.##.............##............................................",
    "............###.##.##.###........##....#####....................................",
    "...........##..###.###..##.....###....##...##...................................",
    "..........##....##.##....##......##........##...................................",
    "..........##....##.##....##.......##..#######...................................",
    "..........##....##.##....##.......##.##....##...................................",
    "...........##..###.##....##.##...##..##...###...................................",
    "............###.##.##....##..#####....####.##...................................",
    "................................................................................",
    "................................................................................",
    "................................................................................",
    "................................................................................",
    "................................................................................",
    "................................................................................",
    "................................................................................"
    recognize: dh3a
    

    相应代码如下:

    package com.demo.check;
    
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.HttpStatus;
    import org.apache.commons.httpclient.methods.GetMethod;
    import org.apache.commons.io.IOUtils;
    
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    
    public class CaptchaRecognizer {
    
        public static void main(String[] args) {
            HttpClient httpClient = new HttpClient();
            GetMethod getMethod = new GetMethod("https://img2020.cnblogs.com/blog/1039974/202011/1039974-20201119224011928-1654538410.png"); // 验证码链接
            for (int i = 0; i < 5; i++) {
                try {
                    // 执行get请求
                    int statusCode = httpClient.executeMethod(getMethod);
                    if (statusCode != HttpStatus.SC_OK) {
                        System.err.println("Method failed: " + getMethod.getStatusLine());
                    } else {
                        File captcha = File.createTempFile("ybt", ".png");
                        OutputStream outStream = new FileOutputStream(captcha);
                        InputStream inputStream = getMethod.getResponseBodyAsStream();
                        IOUtils.copy(inputStream, outStream);
                        outStream.close();
    
                        BufferedImage image = ImageIO.read(captcha);
                        System.out.println("======= print and recognize captchapic  =======");
                        printImage(image);
                        System.out.printf("recognize: %s
    ", recognizeCaptcha(image));
                    }
    
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 释放连接
                    getMethod.releaseConnection();
                }
            }
        }
    
        /**
         * @param colorInt 像素点的RGB值
         * @return
         */
        private static boolean isBlack(int colorInt) {
            Color color = new Color(colorInt);
            if (color.getRed() + color.getGreen() + color.getBlue() <= 10) {
                return true;
            }
            return false;
        }
    
        /**
         * @param image 需要打印的图像
         * @throws IOException
         */
        private static void printImage(BufferedImage image) {
            int h = image.getHeight();
            int w = image.getWidth();
    
            // 矩阵打印
            for (int y = 0; y < h; y++) {
                System.out.printf(""");
                for (int x = 0; x < w; x++) {
                    if (isBlack(image.getRGB(x, y))) {
                        System.out.print("#");
                    } else {
                        System.out.print(".");
                    }
                }
                System.out.printf("%s", y == h-1 ? """ : "",");
                System.out.println();
            }
        }
    
        /**
         * @param image 待识别的符号图片
         * @return
         */
        private static char recognizeSymbol(BufferedImage image) {
            int h = image.getHeight();
            int w = image.getWidth();
    
            int minDiff = 999999;
            char symAns = 0;
            // 对于某个给定数值
            for (int i = 0; i < 10; i++) {
                int curDiff = 0;
                for (int y = 0; y < h; y++) {
                    for (int x = 0; x < w; x++) {
                        boolean pixel1 = digitals[i][y].charAt(x) == '#';
                        boolean pixel2 = isBlack(image.getRGB(x, y));
                        if (pixel1 != pixel2) {
                            ++curDiff;
                        }
                    }
                }
                if (curDiff < minDiff) {
                    minDiff = curDiff;
                    symAns = (char) ('0' + i);
                }
                if (minDiff == 0) {
                    return symAns;
                }
            }
    
            // 对于某个给定字母
            for (int i = 0; i < 26; i++) {
                int curDiff = 0;
                for (int y = 0; y < h; y++) {
                    for (int x = 0; x < w; x++) {
                        boolean pixel1 = alphas[i][y].charAt(x) == '#';
                        boolean pixel2 = isBlack(image.getRGB(x, y));
                        if (pixel1 != pixel2) {
                            ++curDiff;
                        }
                    }
                }
                if (curDiff < minDiff) {
                    minDiff = curDiff;
                    symAns = (char) ('a' + i);
                }
                if (minDiff == 0) {
                    return symAns;
                }
            }
    
            return symAns;
        }
    
        /**
         * @param image 需要被分割的验证码
         * @return
         */
        private static List<BufferedImage> splitImage(BufferedImage image) {
            List<BufferedImage> subImgs = new ArrayList<BufferedImage>();
            subImgs.add(image.getSubimage(10, 3, 8, 12));
            subImgs.add(image.getSubimage(19, 3, 8, 12));
            subImgs.add(image.getSubimage(28, 3, 8, 12));
            subImgs.add(image.getSubimage(37, 3, 8, 12));
            return subImgs;
        }
    
        /**
         * @param image 待识别的验证码
         * @return
         */
        public static String recognizeCaptcha(BufferedImage image) {
            StringBuilder ans = new StringBuilder();
    
            List<BufferedImage> subImgs = splitImage(image);
            for (BufferedImage subImg : subImgs) {
                // 依次识别子图片
                ans.append(recognizeSymbol(subImg));
            }
            return ans.toString();
        }
    
        private static String[][] digitals = new String[][]{
                {
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........"
                },
                {
                        "..####..",
                        ".##..##.",
                        "##....##",
                        "......##",
                        ".....##.",
                        "....##..",
                        "...##...",
                        "..##....",
                        ".##.....",
                        "########",
                        "........",
                        "........"
                },
                {
                        ".#####..",
                        "##...##.",
                        "......##",
                        ".....##.",
                        "...###..",
                        ".....##.",
                        "......##",
                        "......##",
                        "##...##.",
                        ".#####..",
                        "........",
                        "........"
                },
                {
                        ".....##.",
                        "....###.",
                        "...####.",
                        "..##.##.",
                        ".##..##.",
                        "##...##.",
                        "########",
                        ".....##.",
                        ".....##.",
                        ".....##.",
                        "........",
                        "........"
                },
                {
                        "#######.",
                        "##......",
                        "##......",
                        "##.###..",
                        "###..##.",
                        "......##",
                        "......##",
                        "##....##",
                        ".##..##.",
                        "..####..",
                        "........",
                        "........"
                },
                {
                        "..####..",
                        ".##..##.",
                        "##....#.",
                        "##......",
                        "##.###..",
                        "###..##.",
                        "##....##",
                        "##....##",
                        ".##..##.",
                        "..####..",
                        "........",
                        "........"
                },
                {
                        "########",
                        "......##",
                        "......##",
                        ".....##.",
                        "....##..",
                        "...##...",
                        "..##....",
                        ".##.....",
                        "##......",
                        "##......",
                        "........",
                        "........"
                },
                {
                        "..####..",
                        ".##..##.",
                        "##....##",
                        ".##..##.",
                        "..####..",
                        ".##..##.",
                        "##....##",
                        "##....##",
                        ".##..##.",
                        "..####..",
                        "........",
                        "........"
                },
                {
                        "..####..",
                        ".##..##.",
                        "##....##",
                        "##....##",
                        ".##..###",
                        "..###.##",
                        "......##",
                        ".#....##",
                        ".##..##.",
                        "..####..",
                        "........",
                        "........"
                }
        };
    
        private static String[][] alphas = new String[][]{
                {
                        "........",
                        "........",
                        "........",
                        "..#####.",
                        ".##...##",
                        "......##",
                        ".#######",
                        "##....##",
                        "##...###",
                        ".####.##",
                        "........",
                        "........"
                },
                {
                        "##......",
                        "##......",
                        "##......",
                        "##.###..",
                        "###..##.",
                        "##....##",
                        "##....##",
                        "##....##",
                        "###..##.",
                        "##.###..",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "..#####.",
                        ".##...##",
                        "##......",
                        "##......",
                        "##......",
                        ".##...##",
                        "..#####.",
                        "........",
                        "........"
                },
                {
                        "......##",
                        "......##",
                        "......##",
                        "..###.##",
                        ".##..###",
                        "##....##",
                        "##....##",
                        "##....##",
                        ".##..###",
                        "..###.##",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "..####..",
                        ".##..##.",
                        "##....##",
                        "########",
                        "##......",
                        ".##...##",
                        "..#####.",
                        "........",
                        "........"
                },
                {
                        "...####.",
                        "..##..##",
                        "..##..##",
                        "..##....",
                        "..##....",
                        "######..",
                        "..##....",
                        "..##....",
                        "..##....",
                        "..##....",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        ".#####.#",
                        "##...###",
                        "##...##.",
                        "##...##.",
                        ".#####..",
                        "##......",
                        ".######.",
                        "##....##",
                        ".######."
                },
                {
                        "##......",
                        "##......",
                        "##......",
                        "##.###..",
                        "###..##.",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        "........",
                        "........"
                },
                {
                        "...##...",
                        "...##...",
                        "........",
                        "..###...",
                        "...##...",
                        "...##...",
                        "...##...",
                        "...##...",
                        "...##...",
                        ".######.",
                        "........",
                        "........"
                },
                {
                        ".....##.",
                        ".....##.",
                        "........",
                        "....###.",
                        ".....##.",
                        ".....##.",
                        ".....##.",
                        ".....##.",
                        ".....##.",
                        "##...##.",
                        "##...##.",
                        ".#####.."
                },
                {
                        ".##.....",
                        ".##.....",
                        ".##.....",
                        ".##..##.",
                        ".##.##..",
                        ".####...",
                        ".####...",
                        ".##.##..",
                        ".##..##.",
                        ".##...##",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "#.##.##.",
                        "##.##.##",
                        "##.##.##",
                        "##.##.##",
                        "##.##.##",
                        "##.##.##",
                        "##.##.##",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##.###..",
                        "###..##.",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##.###..",
                        "###..##.",
                        "##....##",
                        "##....##",
                        "##....##",
                        "###..##.",
                        "##.###..",
                        "##......",
                        "##......"
                },
                {
                        "........",
                        "........",
                        "........",
                        "..###.##",
                        ".##..###",
                        "##....##",
                        "##....##",
                        "##....##",
                        ".##..###",
                        "..###.##",
                        "......##",
                        "......##"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##.####.",
                        ".###..##",
                        ".##.....",
                        ".##.....",
                        ".##.....",
                        ".##.....",
                        ".##.....",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        ".######.",
                        "##....##",
                        "##......",
                        ".######.",
                        "......##",
                        "##....##",
                        ".######.",
                        "........",
                        "........"
                },
                {
                        "........",
                        "..##....",
                        "..##....",
                        "######..",
                        "..##....",
                        "..##....",
                        "..##....",
                        "..##....",
                        "..##..##",
                        "...####.",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        ".##..###",
                        "..###.##",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##....##",
                        "##....##",
                        ".##..##.",
                        ".##..##.",
                        "..####..",
                        "..####..",
                        "...##...",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##....##",
                        "##....##",
                        "##.##.##",
                        "##.##.##",
                        "##.##.##",
                        "########",
                        ".##..##.",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##....##",
                        ".##..##.",
                        "..####..",
                        "...##...",
                        "..####..",
                        ".##..##.",
                        "##....##",
                        "........",
                        "........"
                },
                {
                        "........",
                        "........",
                        "........",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        "##....##",
                        ".##..###",
                        "..###.##",
                        "#.....##",
                        ".######."
                },
                {
                        "........",
                        "........",
                        "........",
                        ".######.",
                        ".....##.",
                        "....##..",
                        "...##...",
                        "..##....",
                        ".##.....",
                        ".######.",
                        "........",
                        "........"
                }
        };
    }
    

    二、动态验证码gif识别

    动态验证码gif的识别和静态验证码图片的识别非常相识,两者之间唯一的区别在于gif是由多帧静态图片所构成的。所以我们处理gif的思路很简单,从特定帧的静态图片中,识别需要的验证符号。

    输入验证码:

    程序运行结果:

    ======= print and recognize captchapic  =======
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "....................#####.........................................................................................................................",
    ".................###.....###......................................................................................................................",
    ".................#.........#......................................................................................................................",
    ".................#..........#.....................................................................................................................",
    "................#...........#.....................................................................................................................",
    "................#.#######....#..........................######....................................................................................",
    "................###########.#.........................##########..................................................................................",
    "................#############........................###########..................................................................................",
    "................##.....#####.........................##.....#####.................................................................................",
    ".................##.....####................................#####.................................................................................",
    "...................###.####..................................####........................#######..................................................",
    "......................#####.................................#######....................##########.................................................",
    ".....................#####..................................####....#..................###########................................................",
    ".................########..................................####......#.................#.....#####................................................",
    ".................#######..................................####.......#........................####................................................",
    ".................#########...............................####.........#.......................####................................................",
    ".....................######.............................###.#........#...................########.................................................",
    "....................#######...........................####...#.......#.................##########.................................................",
    "..................##...######........................####.....##..###.................####...####.................................................",
    ".................#.....####..#......................####.........#...................####....####.................................................",
    ".................#....#####..#.....................####..............................####....####.................................................",
    "..............#...##.#####.##.....................####...............................####...#####.................................................",
    ".............##############......................#############.......................#############................................................",
    ".............###########.........................#############.......................######..#####................................................",
    "...............#######...........................#############........................####...#####................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    ".................................................................................................................................................."
    <<< frame >>>
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    "..................................................................................................................................................",
    ".................................................................................................................................#####............",
    "...............................................................................................................................########...........",
    "........................................................######................................................................########............",
    "......................................................##########.........................................##...................####...#............",
    ".....................................................###########........................................#..#.................####.................",
    ".....................................................##.....#####.......................................#..#.................####.................",
    "............................................................#####......................................#....#................####.................",
    ".............................................................####........................#######.......#....#..............##########.............",
    "............................................................####.......................##########......#....#.............##########..............",
    "............................................................####.......................###########.....#....#.............##########..............",
    "...........................................................####........................#.....#####.....#....#...............####..................",
    "..........................................................####................................####......#..#................####..................",
    ".........................................................####.................................####......#..#................####..................",
    "........................................................###..............................########........##................####...................",
    "......................................................####.............................##########..........................####...................",
    ".....................................................####.............................####...####..........................####...................",
    "....................................................####......................####...####....####..........................####...................",
    "...................................................####......................#....#..####....####.......####...............####...................",
    "..................................................####.......................#....#..####...#####.....##....###............####...................",
    ".................................................#############...............#.....#.#############...#.........#..........####....................",
    ".................................................#############...............#....#..######..#####...#.........#..........####....................",
    ".................................................#############...............#....#...####...#####..#...........#.........####....................",
    "..............................................................................##.#..................#...........#.................................",
    "................................................................................#...................#............#................................",
    "....................................................................................................#...........#.................................",
    ".....................................................................................................#..........#.................................",
    ".....................................................................................................#.........#..................................",
    ".....................................................................................................##.......##.................................."
    recognize: 32af
    

    以下贴出gif的分割函数,其它过程和第一部分基本相同,之后逐个解析静态子图片即可。

        /**
         * @param file 需要被分割的gif文件
         * @throws Exception
         */
        private static List<BufferedImage> splitGif(File file) throws IOException {
            FileImageInputStream in = new FileImageInputStream(file);
            ImageReaderSpi readerSpi = new GIFImageReaderSpi();
            GIFImageReader gifReader = (GIFImageReader) readerSpi.createReaderInstance();
            gifReader.setInput(in);
            int num = gifReader.getNumImages(true);
    
            ImageWriterSpi writerSpi = new GIFImageWriterSpi();
            GIFImageWriter writer = (GIFImageWriter) writerSpi.createWriterInstance();
            List<BufferedImage> subImgs = new ArrayList<BufferedImage>();
            for (int i = 0; i < num; i++) {
                File frame = File.createTempFile("mxt", ".png");
                FileImageOutputStream out = new FileImageOutputStream(frame);
                writer.setOutput(out);
                writer.write(gifReader.read(num - i - 1));
                out.close();
    
                // 分割每一帧图片,进行识别
                BufferedImage image = ImageIO.read(frame);
                if (i == 1 || i == 2) {
                    printImage(image);
                    System.out.println("<<< frame >>>");
                }
                subImgs.add(image.getSubimage(7 + i * 36, 5, 30, 27));
            }
            in.close();
            return subImgs;
        }
    

    参考链接

    [1] https://blog.csdn.net/problc/article/details/5794460#commentBox
    [2] https://blog.csdn.net/lmj623565791/article/details/23960391/
    [3] https://blog.csdn.net/chwshuang/article/details/64923354

  • 相关阅读:
    RTMP协议安防视频直播点播平台EasyDSS点播目录绑定用户接口无响应问题排查
    RTMP协议安防视频平台EasyDSS在Linux下运行提示-bash .start.sh Permission denied问题解决
    RTMP协议视频直播点播平台EasyDSS内Go语言使用反射优化代码技巧说明
    IP摄像头RTMP协议互联网直播点播平台EasyDSS配置录像/直播计划无法生效是什么原因?
    将IP网络摄像头通过RTMP协议推送到视频直播点播平台EasyDSS时,如何通过抓包RTMP协议保存视频流为H264文件
    hdu2795 Billboard 线段树
    hdu1394 Minimum Inversion Number 线段树和树状数组
    poj 3468 A Simple Problem with Integers 线段树
    CF round #292 解题报告
    棋盘问题 poj1321
  • 原文地址:https://www.cnblogs.com/zzzz76/p/14008582.html
Copyright © 2011-2022 走看看