精华内容
下载资源
问答
  • 基于 Java 的简单图形验证码识别
  • java简单图形验证码识别样例,java简单图形验证码识别样例
  • 对于简单的图形验证码(字体规则,没有杂点或杂点容易过滤掉),用模板匹配的方式可以比较容易地识别出来.0.图片黑白化,用1表示有字的像素,0表示无字的像素1.字块分隔,将图片分隔成只包含成单字的最小块2.生成模板,将字...

    对于简单的图形验证码(字体规则,没有杂点或杂点容易过滤掉),用模板匹配的方式可以比较容易地识别出来.

    0.图片黑白化,用1表示有字的像素,0表示无字的像素

    1.字块分隔,将图片分隔成只包含成单字的最小块

    2.生成模板,将字块与字符关联

    3.识别,将新图片分块并与模板匹配

    java(jdk1.5)实现:

    //先运行TemplateCreator创建模板,再运行Recognize2识别

    //图片数据表示,也用来表示字块

    package pay365;

    import java.awt.image.BufferedImage;

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.FileReader;

    import java.io.IOException;

    import java.util.ArrayList;

    import java.util.Iterator;

    public class ImageData {

    public int[][] data;

    public int w;

    public int h;

    public char code;

    public ImageData() {

    }

    public ImageData(BufferedImage bi) {

    this(bi,new WhiteFilter());

    }

    public ImageData(BufferedImage bi,Filter filter) {

    h = bi.getHeight();

    w = bi.getWidth();

    data = new int[h][w];

    for (int i = 0; i < h; i++) {

    for (int j = 0; j < w; j++) {

    int p = bi.getRGB(j, i);

    data[i][j] = p;

    }

    }

    filter.doFilter(data);

    }

    public ImageData[] split() {

    ArrayList list = new ArrayList();

    ImageIterator ite = new ImageIterator(this);

    while (ite.hasNext()) {

    list.add(ite.next());

    }

    return (ImageData[]) list.toArray(new ImageData[0]);

    }

    int skipEmpty(int begin, boolean isX, int value) {

    if (isX) {

    for (int i = begin; i < w; i++) {

    for (int j = 0; j < h; j++) {

    if (data[j][i] != value) {

    return i;

    }

    }

    }

    return -1;

    } else {

    for (int i = begin; i < h; i++) {

    for (int j = 0; j < w; j++) {

    if (data[i][j] != value) {

    return i;

    }

    }

    }

    return -1;

    }

    }

    int skipEntity(int begin, boolean isX, int value) {

    if (isX) {

    for (int i = begin; i < w; i++) {

    for (int j = 0; j < h; j++) {

    if (data[j][i] == value) {

    break;

    }

    if (j == h - 1)

    return i;

    }

    }

    return -1;

    } else {

    for (int i = begin; i < h; i++) {

    for (int j = 0; j < w; j++) {

    if (data[i][j] == value) {

    break;

    }

    if (j == w - 1)

    return i;

    }

    }

    return -1;

    }

    }

    class ImageIterator implements Iterator {

    int x;

    ImageData ia;

    ImageData next;

    public ImageIterator(ImageData ia) {

    this.ia = ia;

    }

    public boolean hasNext() {

    if (next != null)

    return true;

    next = getNext();

    return next != null;

    }

    ImageData getNext() {

    int x1 = skipEmpty(x, true, 0);

    if (x1 == -1) {

    return null;

    }

    int x2 = skipEntity(x1, true, 1);

    if (x2 == -1) {

    x2 = w;

    }

    x = x2;

    int y1 = skipEmpty(0, false, 0);

    if (y1 == -1)

    return null;

    int y2 = skipEntity(y1, false, 1);

    if (y2 == -1)

    y2 = h;

    return ia.clone(x1, y1, x2 - x1, y2 - y1);

    }

    public Object next() {

    ImageData temp = next;

    next = null;

    return temp;

    }

    public void remove() {

    }

    }

    ImageData clone(int x, int y, int w0, int h0) {

    ImageData ia = new ImageData();

    ia.w = w0;

    ia.h = h0;

    ia.data = new int[ia.h][ia.w];

    for (int i = 0; i < h0; i++) {

    for (int j = 0; j < w0; j++) {

    ia.data[i][j] = data[i + y][j + x];

    }

    }

    return ia;

    }

    public void show() {

    System.out.println();

    for (int i = 0; i < h; i++) {

    for (int j = 0; j < w; j++) {

    System.out.print((data[i][j] == 1 ? "1" : " ") + "");

    }

    System.out.println();

    }

    System.out.println();

    }

    public int hashCode() {

    int code = w ^ h;

    int count = 0;

    for (int i = 0; i < h; i++) {

    for (int j = 0; j < w; j++) {

    if (data[i][j] == 1)

    count++;

    }

    }

    code ^= count;

    return code;

    }

    public boolean equals(Object obj) {

    if (this == obj) {

    return true;

    }

    if (obj instanceof ImageData) {

    ImageData o = (ImageData) obj;

    if (o.h != h)

    return false;

    if (o.w != w)

    return false;

    for (int i = 0; i < h; i++) {

    for (int j = 0; j < w; j++) {

    if (o.data[i][j] != data[i][j])

    return false;

    }

    }

    return true;

    } else {

    return false;

    }

    }

    public static ImageData[] decodeFromFile(String path) throws IOException {

    BufferedReader reader = new BufferedReader(new FileReader(

    new File(path)));

    String line;

    ArrayList list = new ArrayList();

    while ((line = reader.readLine()) != null) {

    ImageData ia = decode(line);

    if (ia != null) {

    list.add(ia);

    }

    }

    return (ImageData[]) list.toArray(new ImageData[0]);

    }

    public static ImageData decode(String s) {

    String[] ss = s.split("\\,", 4);

    if (ss.length != 4)

    return null;

    if (ss[0].length() != 1)

    return null;

    ImageData ia = new ImageData();

    ia.code = ss[0].charAt(0);

    ia.w = Integer.parseInt(ss[1]);

    ia.h = Integer.parseInt(ss[2]);

    if (ss[3].length() != ia.w * ia.h) {

    return null;

    }

    ia.data = new int[ia.h][ia.w];

    for (int i = 0; i < ia.h; i++) {

    for (int j = 0; j < ia.w; j++) {

    if (ss[3].charAt(i * ia.w + j) == '1') {

    ia.data[i][j] = 1;

    } else {

    ia.data[i][j] = 0;

    }

    }

    }

    return ia;

    }

    public String encode() {

    StringBuffer sb = new StringBuffer();

    sb.append(code).append(",");

    sb.append(w).append(",");

    sb.append(h).append(",");

    for (int i = 0; i < h; i++) {

    for (int j = 0; j < w; j++) {

    if (data[i][j] == 1) {

    sb.append('1');

    } else {

    sb.append('0');

    }

    }

    }

    return sb.toString();

    }

    }

    //像素过滤接口

    package pay365;

    public interface Filter {

    void doFilter(int[][] data);

    }

    //

    package pay365;

    public abstract class AbstractFilter  implements Filter {

    public void doFilter(int[][] data) {

    int h = data.length;

    if (h<=0)

    return;

    int w = data[0].length;

    if (w<=0)

    return ;

    for(int i=0;i

    for(int j=0;j

    data[i][j] = filter(data[i][j]);

    }

    }

    }

    protected abstract int filter(int p);

    }

    //过滤csdn验证码的过滤器

    package pay365;

    public class CsdnFilter extends AbstractFilter {

    protected int filter(int p) {

    return isNotWhite(p)?1:0;

    }

    private boolean isNotWhite(int p) {

    boolean b = (p & 0x0ff) == 255 && (p >> 8 & 0x0ff) == 255

    && (p >> 16 & 0xff) == 255;

    return !b;

    }

    }

    //过滤前景色为白色的过滤器

    package pay365;

    public class WhiteFilter extends AbstractFilter {

    protected int filter(int p) {

    if (isWhite(p)) {

    return 1;

    }

    else {

    return 0;

    }

    }

    private boolean isWhite(int p) {

    return (p & 0x0ff) > 240 && (p >> 8 & 0x0ff) > 240

    && (p >> 16 & 0xff) > 240;

    }

    }

    //模板创建类

    package pay365;

    import java.awt.image.BufferedImage;

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.InputStreamReader;

    import java.io.PrintWriter;

    import java.net.URL;

    import java.util.HashSet;

    import java.util.Iterator;

    import java.util.Set;

    import javax.imageio.ImageIO;

    public class TemplateCreator {

    /**

    * @param args

    */

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

    Set set = new HashSet();

    String url = "http://passport.csdn.net/member/ShowExPwd.aspx";

    String filterClazz = "pay365.CsdnFilter";

    if (args.length>=1) {

    url = args[0];

    }

    if (args.length>=2) {

    filterClazz = args[1];

    }

    Filter csdnFilter = (Filter) Class.forName(filterClazz).newInstance();

    for (int i = 1; i < 10; i++) {

    URL u = new URL(url);

    BufferedImage bi = ImageIO.read(u);

    ImageData ia2 = new ImageData(bi,csdnFilter);

    ImageData[] ii = ia2.split();

    for (int x = 0; x < ii.length; x++) {

    ImageData imageArr = ii[x];

    set.add(imageArr);

    }

    // set.addAll(Arrays.asList(ia2.split()));

    }

    System.out.println(set.size());

    for (Iterator iter = set.iterator(); iter.hasNext();) {

    ImageData ele = (ImageData) iter.next();

    ele.show();

    System.out.print("char:");

    String s = readLine();

    if (s.length() == 1) {

    ele.code = s.charAt(0);

    }

    }

    PrintWriter pw = new PrintWriter(new File("template.data"));

    for (Iterator iter = set.iterator(); iter.hasNext();) {

    ImageData ele = (ImageData) iter.next();

    pw.println(ele.encode());

    }

    pw.flush();

    pw.close();

    }

    private static BufferedReader reader = new BufferedReader(

    new InputStreamReader(System.in));

    private static String readLine() {

    try {

    return reader.readLine();

    } catch (Exception e) {

    e.printStackTrace();

    return "";

    }

    }

    }

    //识别类

    package pay365;

    import java.awt.image.BufferedImage;

    import java.io.File;

    import java.io.IOException;

    import java.net.URL;

    import java.util.ArrayList;

    import java.util.HashMap;

    import java.util.Iterator;

    import javax.imageio.ImageIO;

    public class Recognize2 {

    static Filter filter;

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

    if (args.length >= 1) {

    url = args[0];

    }

    String filterClazz = "pay365.CsdnFilter";

    if (args.length >= 2) {

    filterClazz = args[1];

    }

    filter = (Filter) Class.forName(filterClazz).newInstance();

    int total = 10;

    int count = 0;

    for (int i = 0; i < total; i++) {

    boolean b = recognize(i);

    if (b)

    count++;

    }

    System.out.println("rate:" + (count * 1.0 / total * 100) + "%100");

    }

    /**

    * @throws IOException

    */

    private static boolean recognize(int num) throws IOException {

    BufferedImage bi = ImageIO.read(new URL(url));

    ImageIO.write(bi,"png",new File(num+".png"));

    ImageData ia2 = new ImageData(bi, filter);

    ImageData[] ii = ia2.split();

    ArrayList list = new ArrayList();

    ImageData[] template = ImageData.decodeFromFile("template.data");

    HashMap map = new HashMap();

    for (int i = 0; i < template.length; i++) {

    map.put(template[i], new Character(template[i].code));

    }

    for (int x = 0; x < ii.length; x++) {

    ImageData imageArr = ii[x];

    if (imageArr.w > 15)

    continue;

    Character c = (Character) map.get(imageArr);

    if (c != null) {

    list.add(c);

    }

    }

    String s = "";

    System.out.print(num + ":");

    for (Iterator iter = list.iterator(); iter.hasNext();) {

    Character c = (Character) iter.next();

    s += c;

    System.out.print(c);

    }

    System.out.println();

    return s.length() != 0;

    }

    }

    展开全文
  • Java识别图像、验证码

    2021-03-06 03:51:24
    前言这是一个学习案例,看最后一张图,识别率应该有90%以上吧!提高识别度代码处理,放大图像不清晰的图像,像素不好的,如果已经是最好效果了,建议不要处理(放大),就这样子直接识别。/** 对图片进行处理 - 提高...

    前言

    这是一个学习案例,看最后一张图,识别率应该有90%以上吧!

    提高识别度

    代码处理,放大图像

    不清晰的图像,像素不好的,如果已经是最好效果了,建议不要处理(放大),就这样子直接识别。

    /** 对图片进行处理 - 提高识别度 **/

    private 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() * 3, image.getHeight() * 3);

    return image;

    }

    图片倾斜处理

    BufferedImage bi = ImageIO.read(imageFile);

    ImageDeskew id = new ImageDeskew(bi);

    double imageSkewAngle = id.getSkewAngle(); //获取倾斜角度

    if ((imageSkewAngle > 0.05d || imageSkewAngle < -(0.05d))) {

    bi = ImageHelper.rotateImage(bi, -imageSkewAngle); //纠偏图像

    }

    1.识别模糊图像

    /**

    * 模糊图像,像素不好,建议不放大。

    */

    testMHYzm();

    40394b3f7fab46a0f2403a45d4830845.png

    2.识别清晰图像

    /**

    * 清晰图像,建议放大,识别度更精准。

    */

    testConvertYzm();

    efbf94c4ad8cade183c11562f4833eeb.png

    3.识别英文图像

    /**

    * 识别英文图像

    */

    testConvertEn();

    a2c82dadde697607a66b25b9cb563c9e.png

    4.识别中文图像

    /**

    * 识别中文图像

    */

    testConvertZh();

    b4888934f7fb6ee2fe6b2cdc036677fc.png

    源代码地址

    展开全文
  • 使用机器学习端到端图片验证码识别,通杀所有图片类型验证码类型(包括复杂的连在一起、重叠的验证码),支持java,python, c#等语言, 识别精度达95%以上。 机器学习识别验证码,提供了一个完整的图片验证码识别...
  • 图片验证码识别,简单写下,做个备忘。   一、注册百度账号及新增一个应用,获取百度API所需的AppID,API Key,Secret Key三个参数。 访问http://ai.baidu.com,使用百度账号登录后,出现如下界面 成功创建...

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

     

    一、注册百度账号及新增一个应用,获取百度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

     

    下载源码

     

     

    展开全文
  • Java识别验证码和图像处理

    万次阅读 多人点赞 2018-06-07 12:07:47
    这里老样子先说几句无关的话,去年毕业的时候帮同学做了一个验证码识别系统,按部就班的参考了大神的操作,对于二值化这些操作都没有深入了解,最近做项目遇到了要实现机器登录的操作,验证码自然绕不过去所以就又翻...

    阅读本文可能会解决的问题:

    ① 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){
                                img.setRGB(x, y, Color.WHITE.getRGB());
                            }
                        }
                    }
                }
                for(int i = 1;i<width;i++){
                    Color color1 = new Color(img.getRGB(i, 1));
                    int num1 = color1.getRed()+color1.getGreen()+color1.getBlue();
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            Color color = new Color(img.getRGB(x, y));
    
                            int num = color.getRed()+color.getGreen()+color.getBlue();
                            if(num==num1){
                                img.setRGB(x, y, Color.BLACK.getRGB());
                            }else{
                                img.setRGB(x, y, Color.WHITE.getRGB());
                            }
                        }
                    }
                }
                File file = new File(resUrl);
                if (!file.exists())
                {
                    File dir = file.getParentFile();
                    if (!dir.exists())
                    {
                        dir.mkdirs();
                    }
                    try
                    {
                        file.createNewFile();
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }
                ImageIO.write(img, "jpg", file);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    

    这样就能得到一个降噪之后的验证码,再后续通过颜色反转将验证码的内容显示出来就完成了干扰像素的去除工作,接下来非必要的一项工作就是将验证码进行裁边。为什么要裁边呢,通过观察我们发现验证码的边角部分没有干扰素涂抹,在我们的去除干扰素过程中可能会影响到这部分像素块导致最后边角有噪点,这时将边角裁掉几个像素就可以了。

    public static void cuttingImg(String imgUrl){
            try{
                File newfile=new File(imgUrl);
                BufferedImage bufferedimage=ImageIO.read(newfile);
                int width = bufferedimage.getWidth();
                int height = bufferedimage.getHeight();
                if (width > 52) {
                    bufferedimage=ImgUtils.cropImage(bufferedimage,(int) ((width - 52) / 2),0,(int) (width - (width-52) / 2),(int) (height));
                    if (height > 16) {
                        bufferedimage=ImgUtils.cropImage(bufferedimage,0,(int) ((height - 16) / 2),52,(int) (height - (height - 16) / 2));
                    }
                }else{
                    if (height > 16) {
                        bufferedimage=ImgUtils.cropImage(bufferedimage,0,(int) ((height - 16) / 2),(int) (width),(int) (height - (height - 16) / 2));
                    }
                }
                ImageIO.write(bufferedimage, "jpg", new File(imgUrl));
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    其中裁剪图片我们需要预先读取宽高度,确认需要裁剪的像素宽度,我这里将60*20的图像宽度两边各裁剪4像素,高度上下各裁剪2像素,输出就得到了一个清晰的图像。到这里基本完成了对验证码的简单处理,不出意外的话验证码由

      变为了 

    到这里就很简单了,我们可以利用裁切将图片平均剪成四份,再通过简单的训练比对完成匹配,详细操作可以看这里,我就不再赘述了。我这里提供另一个思路,就是要说的Tess4J文本识别工具,通过这个工具我可以直接对当前生成的验证码进行OCR识别,准确率接近100%,注意我项目里是采用Tess4J进行最终的验证码图片内容识别的。

    二、Tess4J的使用

    1.首先需要到官网下载Tess4J的压缩包,下载后先将解压出来的包内tessdata文件拷入项目根目录,然后引入Tess4J\lib包,最后还要单独引入Tess4J\dist\tess4j-3.4.8.jar包

    2.编写简单的识别代码

    public static String executeTess4J(String imgUrl){
            String ocrResult = "";
            try{
                ITesseract instance = new Tesseract();
                //instance.setLanguage("chi_sim");
                File imgDir = new File(imgUrl);
                //long startTime = System.currentTimeMillis();
                ocrResult = instance.doOCR(imgDir);
            }catch (TesseractException e){
                e.printStackTrace();
            }
            return ocrResult;
        }

    ocrResult 即为最终是别的结果,代码相当简单,其中我注释掉的 instance.setLanguage("chi_sim"); 这部分是指定需要识别文本的语言,如果是识别中文按照我注释的chi_sim填写即可,当然这是一个中文包,需要先在这里找到中文包下载后放到Tess4J\tessdata目录下即可使用。

    到这里基本就完成了对这个验证码的简单识别,在这个过程中基本没遇到什么有难度的工作,毕竟是站在大佬们的肩膀上操作,其实还是学到了很多东西的,需求这东西说不定哪天就遇到了呢。接下来我在研究验证码识别的过程中了解到了JavaCV,比较感兴趣就记录下来,方便之后使用吧。

    三、JavaCV的使用

    1. 首先就是去官网下载包啦,点 这里,引入很简单,解压后将javacv-bin包引入项目即可(可以看到封装了OpenCV)

    2. 基本操作:获取灰度图像、获取二值化处理图像

    public static void main(String[] args) {
            //图片地址
            String imgUrl = "C:\\mysoftware\\images\\upload\\OcrImg\\20180607004153.png";
            //得到灰度图像
            getHuidu(imgUrl);
            //得到二值化处理图像
            getErzhihua(imgUrl);
        }
    
        //得到灰度图像
        public static void getHuidu(String imgUrl){
            Mat image=imread(imgUrl,CV_LOAD_IMAGE_GRAYSCALE);
            //读入一个图像文件并转换为灰度图像(由无符号字节构成)
            Mat image1=imread(imgUrl,CV_LOAD_IMAGE_COLOR);
            //读取图像,并转换为三通道彩色图像,这里创建的图像中每个像素有3字节
            //如果输入图像为灰度图像,这三个通道的值就是相同的
            System.out.println("image has "+image1.channels()+" channel(s)");
            //channels方法可用来检查图像的通道数
            flip(image,image,1);//就地处理,参数1表示输入图像,参数2表示输出图像
            //在一窗口显示结果
            namedWindow("输入图片显示窗口");//定义窗口
            imshow("输入图片显示窗口",image);//显示窗口
            waitKey(0);//因为他是控制台窗口,会在mian函数结束时关闭;0表示永远的等待按键,正数表示等待指定的毫秒数
        }
    
        //得到二值化处理图像
        public static void getErzhihua(String imgUrl){
            // TODO Auto-generated method stub
            Mat image=imread(imgUrl);	//加载图像
            if(image.empty())
            {
                System.out.println("图像加载错误,请检查图片路径!");
                return ;
            }
            imshow("原始图像",image);
            Mat gray=new Mat();
            cvtColor(image,gray,COLOR_RGB2GRAY);		//彩色图像转为灰度图像
            imshow("灰度图像",gray);
            Mat bin=new Mat();
            threshold(gray,bin,120,255,THRESH_TOZERO); 	//图像二值化
            imshow("二值图像",bin);
            waitKey(0);
        }

    看一下效果:

    四、生成验证码

    生成验证码大致思路:
    加载登录界面时向后台请求一个随机验证码code存入session,并在页面以图形显示出来,用户输入登录信息后点击登录,后台读出session的验证码code比对是否一致,不一致返回错误信息,一致则进行登录账号密码校验。
    1. 首先在login的页面添加一个img
    <div class="form-group">
                       <label class="col-sm-2 control-label">验证</label>
                       <div class="col-sm-10">
                           <input id = "code" type="text" name="vcode" value="请输入验证码" maxlength="4" tabindex="3" style="width:123px;padding: 6px 12px;border: 1px solid #ccc;font-size: 14px;line-height: 1.42857143;color: #555;background-color: #fff;border-radius: 4px;box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;" οnfοcus="if(this.value=='请输入验证码'){this.value='';}"  οnblur="if(this.value==''){this.value='请输入验证码';}"/>
                           <a href="#" id="js-get_mobile_vcode" class="button btn-disabled">
                               <img src="../recordHome/getRand" id="randImg"  οnclick="changeValidateCode(this)"/>
                           </a>
                       </div>
                   </div>
    其中为了方便用户使用,需要做点击图片自动获取新的验证码,所以changeValidateCode()方法是动态去后台请求验证码并设置到页面上
    function changeValidateCode() {
        var timestamp = new Date().getTime();
        $("#randImg").attr('src','../recordHome/getRand?flag='+timestamp);
    }
    请求时添加时间戳是为了防止浏览器缓存导致获取失败
    2. 后台生成验证码
    /**
    	 * 随机生成4位验证码
    	 * @param httpSession
    	 * @param request
    	 * @param response
    	 */
    	@RequestMapping(value="/getRand")
    	public void rand(HttpSession httpSession, HttpServletRequest request, HttpServletResponse response){
    		// 在内存中创建图象
    		int width = 65, height = 20;
    		BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
    		// 获取图形上下文
    		Graphics g = image.getGraphics();
    		// 生成随机类
    		Random random = new Random();
    		// 设定背景色
    		g.setColor(getRandColor(200, 250));
    		g.fillRect(0, 0, width, height);
    		// 设定字体
    		g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
    		// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
    		g.setColor(getRandColor(160, 200));
    		for (int i = 0; i < 155; i++) {
    			int x = random.nextInt(width);
    			int y = random.nextInt(height);
    			int xl = random.nextInt(12);
    			int yl = random.nextInt(12);
    			g.drawLine(x, y, x + xl, y + yl);
    		}
    		// 取随机产生的认证码(6位数字)
    		String sRand = "";
    		for (int i = 0; i < 4; i++) {
    			String rand = String.valueOf(random.nextInt(10));
    			sRand += rand;
    			// 将认证码显示到图象中
    			g.setColor(new Color(20 + random.nextInt(110), 20 + random
    					.nextInt(110), 20 + random.nextInt(110)));
    			// 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
    			g.drawString(rand, 13 * i + 6, 16);
    		}
    		// 将认证码存入SESSION
    		ContextHolderUtils.getSession().setAttribute("rand", sRand);
    		//httpSession.setAttribute("rand", sRand);
    		// 图象生效
    		g.dispose();
    		try{
    			ImageIO.write(image, "JPEG", response.getOutputStream());
    			response.getOutputStream().flush();
    		}catch (Exception e){
    		}
    	}
    
    	/**
    	 * 给定范围获得随机颜色
    	 * @param fc
    	 * @param bc
    	 * @return
    	 */
    	private Color getRandColor(int fc, int bc) {
    		Random random = new Random();
    		if (fc > 255)
    			fc = 255;
    		if (bc > 255)
    			bc = 255;
    		int r = fc + random.nextInt(bc - fc);
    		int g = fc + random.nextInt(bc - fc);
    		int b = fc + random.nextInt(bc - fc);
    		return new Color(r, g, b);
    	}
    使用ContextHolderUtils.getSession().setAttribute("rand", sRand);将验证码存入session中
    @RequestMapping("/login")
    	public String login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password, @RequestParam String vcode) {
    		if(!vcode.equals(ContextHolderUtils.getSession().getAttribute("rand"))){
    			request.setAttribute("failMsg", "验证码不正确!");
    			return "/base/login";
    		}
    		logger.info("用户登录用户:" + username );
    		...
    	}
    登录时进行校验,就酱so easy


    最后是全部代码,这里说到的我都集成到了项目里,直接下载就可以运行,欢迎大家指正。

    有用的话可以☆star一下哦

    https://github.com/jwwam/OcrImage.git


    本文完 2018-6-7

    有问题欢迎大家留言指正大笑

    来自 https://blog.csdn.net/zhulier1124/article/details/80606647

    转载请注明,谢谢。

    展开全文
  • 通过OpenCV实现的全自动图形图片验证码识别软件,可以识别出绝大多数验证码,操作简单方便。
  • 1,目前简单的验证码识别可以使用tess4J进行图像识别,前提是需要将验证码图片处理好(清晰,黑白色,无其他干扰素,字体大小一样,间距合适),这样才能保证识别正确 2,简单验证码图片处理方法,二值化,去干扰线...
  • 点击上方关注 “终端研发部”设为“星标”,和你一起掌握更多数据库知识来源:https://gitee.com/whvse/EasyCaptcha简介Java图形验证码,支持Gif、中文、算...
  • 1.能够识别么有背景的图形验证码。 2.使用OCR工具
  • 随着安全性的要求越来越高,如今的验证码已经不再是简单的四个数字或者字母了,更复杂的图形验证码和行为验证码已经成为了更流行的趋势,但更难的实现也让很多开发者头秃,Gitee 已经替你们想到了这一点。...
  • 本地图片识别 网络图片识别 二、免费api接口 接口地址:http://www.bhshare.cn/imgcode/ 请求类型:post 接口参数: 参数名 类型 是否必需 备注 token String 是 用户标识(token 免费获取:...
  • JAVA识别图形验证码

    万次阅读 热门讨论 2009-04-23 08:11:00
    但是碰到了图形验证码的问题了,对单数字的验证码,通过一些OCR引擎,如:tesseract,AspriseOCR很容易解决问题。但碰到如CSDN论坛这中图形验证码就比较麻烦,必须先通过预处理。使图象二值化,黑白灰度,增加亮度。...
  • 1、Tess4j最近在GitHub上看到一个图像识别的开源框架tess4j,而且是Java版的,为此利用此框架来识别验证码中的信息,利用它提供的字体库,来提取信息,对于没有什么干扰线的验证码准确率还是蛮高的,对于有一些干扰...
  • Java图形验证码开源软件SimpleCaptcha

    千次阅读 2014-06-05 11:23:01
    Java中有很多开源xi
  • Java简单验证码识别(附源码)

    千次阅读 2017-07-30 20:27:42
    识别图形:该验证码下载网址为:http://www.quanjing.com/createImg.aspx (这个验证码可以采集,在我上一篇http://blog.csdn.net/q651742112/article/details/76177275有源代码)思路:这个验证码比较规则,...
  • java解析图片验证码

    热门讨论 2014-01-20 10:31:13
    java解析图片验证码
  • Java 验证码识别库 Tess4j学习【在用java的Jsoup做爬虫爬取数据时遇到了验证码识别的问题(基于maven),找了网上挺多的资料,发现Tess4j可以自动识别验证码,在这里简单记录下学习过程及遇到的一些问题。】步骤:需要...
  • Java 图形验证码模块

    2021-08-29 19:20:10
    可以支持Gif、中文、算术等类型,可用于Java Web、JavaSE等项目 步骤: 1.pom文件添加引用: <dependencies> <dependency> <groupId>com.github.whvcse</groupId> <artifactId>...
  • JAVA识别复杂验证码+图像处理

    千次阅读 2018-12-13 17:42:45
    先对验证码进行简单的处理噪点和纯色 例未曾处理的图片 public static void main(String[] args) throws Exception { //源文件 String picName = "C:\\Users\\syxy101\\Desktop\\6.jpg"; File file...
  • Tesseract-OCR学习一安装测试数字识别英文识别中文文字识别python对接 安装 按照官方文档提示进行安装 语言库选择math,chinese simplified. windows下需要添加环境变量 变量名TESSDATA_PREFIX 变量值F:\Program ...
  • ##mavenorg.bytedeco.javacpp-presetstesseract-platform3.04.01-1.3##配置 在resources目录下新建tessdata目录,然后从tessdata获取一个ENG.traineddata,再在tessdata目录下新建configs目录,设置几个配置文件api_...
  • 图形验证码 Gif动画验证码 手机短信验证码 手机语音验证码 视频验证码 手势验证码 四.简单验证码识别流程和一些算法 五.基本案例 案例1:字体固定,大小固定,位置固定的验证码 案例2:字体固定,大小固定...
  • 下面借我之前完成的一个数字验证码识别的小项目来简单认识一下图象识别领域的知识。  如果在阅读这篇文章时有什么疑问,可以参考一下之前的一些文章:   Java应用OpenCV指南其一:在Java中安装与配置OpenCV  ...
  • 一、资源 ... 2.chromedriver的版本要与你使用的chrome版本对应,查看位置:设置->...3.尖叫科技第三方验证码识别(这个效率比较高,如需账号可以与本人联系):http://www.jianjiaoshuju.com/ 二、抛出...
  • 活动介绍缘起是 GitChat 作者群有一位作者提出是否应该定期组织一些写作活动,活跃一下社区氛围,刚好 GitChat 内容组的小伙伴们也有这个想法,既然想法碰到一起,那就说做就做。既然是第一期,那么我们就定一个比较...
  • 现在在一些重要些的环节大多都有图形验证码进行保护,以前的自动程序由于验证码的保护而无法实现全自动化,这样就有了验证码识别的研究--图形验证码的识别。 1、识别程序以dll的方式提供使用,通过简单的函数调用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,394
精华内容 957
关键字:

java图形验证码识别

java 订阅