验证码识别(一)

     开始做简单的ORC,从昨天到今天总算有个小小的成绩了。

    图像的文字识别我拿验证码开刀,因为验证码稍微简单点,说说验证思路:
    一、获取验证图片
    二、程序加载要验证的字体库
    三、程序加载需匹配的文字库(字符数组即可)
    四、将验证码图片进行中值滤波处理,然后再将其锐化(也可进行取色彩最多的几个点进行采样再锐化)
    五、将验证码的字符进行拆字(扫描行、列的间隙,然后就可以将字找出来),然后将拆分之后的图像保存到内存中,为以后提供匹配
    六、此步骤为循环
        6.0依次取字体库中的字符
        6.1将取出的字符的字体设置成需验证的字体
        6.2图像化此字符
        6.3将内存的字与验证的字放大至同样的大小(高或者宽取最小公倍数)
        6.4然后开始记录源与目标的验证点(用数组保存值,如果在像素点上有待验证的点,值为1,否则为0)
        6.5然后将验证点进行匹配像素块,记录块的匹配度(我这里拿4方格,4个像素做匹配块,一个像素0.25个匹配度)
        6.6累加匹配度,匹配完成之后再计算均值
        6.7当均值大于某个值时则匹配成功
    七、退出循环
    八、××程序上的业务逻辑××

    当然,思路是这样的,中间有几个地方在今天的代码中没有体现出来:
    1.中值滤波(现在暂时还没有搞懂图像的计算公式)
    2.字体库(这个确实不晓得我的电脑今天是不是大姨夫来了,字体库居然加载不上)
    3.拆字(从图片中我都能够把字取出来,扫描行、列的文字也暂时不用实现)
    4.字体缩放(节约时间没有做)

测试的来源是两个bmp的图片,一个作为匹配,一个作为待验证的,字体、大小不要太过于差异了,位置可以随便放,只要目测能够看出来是那个字。


当然,验证的时候不可能把验证库保存为图片文件,这是不科学的…… 

图片
图片 
这两个字是不同的字体,匹配度只有那么多点了……
图片
图片
这个是当图形处理的。
图片
图片
 虽然字体不一样,但匹配度是很高的(这个好像……没有做锐化处理)
 
贴代码:
 import java.awt.Color;
import java.awt.Point;
import java.awt.RenderingHints;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * 读取验证码
 * @author Administrator
 */
public class ReadSerCode {
 
    public static final int east = 1;//东
    public static final int south = 2;//南
    public static final int west = 3;//西
    public static final int north = 4;//北
    public static final int northeast = 5;//东北
    public static final int southwest = 6;//西南
    public static final int southeast = 7;//东南
    public static final int northwest = 8;//西北
 
    /**
     *
     * @param sourceFile 源
     * @param objectFile 目标
     * @throws Exception
     */
    public static void readImage(String sourceFile,String objectFile) throws Exception {
 
        //读取源
        java.awt.image.BufferedImage s_img = javax.imageio.ImageIO.read(new File(sourceFile));
        int s_width = s_img.getWidth();
        int s_height = s_img.getHeight();
        java.util.HashMap<String, Integer> s_colors = new java.util.HashMap<String, Integer>();
        java.util.HashMap<String, java.util.List<java.awt.Point>> s_colorP = new java.util.HashMap<String, java.util.List<java.awt.Point>>();
        for (int i = 0; i < s_width; i++) {
            for (int j = 0; j < s_height; j++) {
                String c = "" + s_img.getRGB(i, j);
                if (s_colors.get(c) == null) {
                    s_colors.put(c, 1);
                    java.util.List<java.awt.Point> plist = new java.util.ArrayList<java.awt.Point>();
                    s_colorP.put(c, plist);
                } else {
                    s_colors.put(c, s_colors.get(c) + 1);
                    java.awt.Point p = new java.awt.Point(i, j);
                    s_colorP.get(c).add(p);
                }
            }
        }
 
        //将像素最多的几个色素排序
        List<Map.Entry<String, Integer>> s_infoIds =
                new ArrayList<Map.Entry<String, Integer>>(s_colors.entrySet());
        Collections.sort(s_infoIds, new Comparator<Map.Entry<String, Integer>>() {
 
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return (o2.getValue() - o1.getValue());
                //return (o1.getKey()).toString().compareTo(o2.getKey());
            }
        });
 
 
        //for(java.util.Map.Entry<String,Integer> m : s_infoIds){
        //    System.out.println("value:"+m.getValue()+"  key:"+m.getKey());
        //}
        //开始处理点,将点规范在一个矩形框内
        //java.util.List<Point> sourcePoints = s_colorP.get(s_infoIds.get(s_infoIds.size() - 1).getKey());
        java.util.List<Point> sourcePoints = s_colorP.get(s_infoIds.get(1).getKey());
        int s_left = -1;
        int s_right = -1;
        int s_top = -1;
        int s_bottom = -1;
        for (Point p : sourcePoints) {
            //System.out.println("("+p.x+","+p.y+")");
            if (s_left == -1) {
                s_left = p.x;
            }
            if (s_top == -1) {
                s_top = p.y;
            }
            if (p.x <= s_left) {
                s_left = p.x;
            }
            if (p.x >= s_right) {
                s_right = p.x;
            }
            if (p.y <= s_top) {
                s_top = p.y;
            }
            if (p.y >= s_bottom) {
                s_bottom = p.y;
            }
        }
        System.out.println("匹配源s_top=" + s_top + "\ts_left=" + s_left + "\ts_bottom=" + s_bottom + "\ts_right=" + s_right);
 
        //读目标
        java.awt.image.BufferedImage o_img = javax.imageio.ImageIO.read(new File(objectFile));
        int o_width = o_img.getWidth();
        int o_height = o_img.getHeight();
        java.util.HashMap<String, Integer> o_colors = new java.util.HashMap<String, Integer>();
        java.util.HashMap<String, java.util.List<java.awt.Point>> o_colorP = new java.util.HashMap<String, java.util.List<java.awt.Point>>();
        for (int i = 0; i < o_width; i++) {
            for (int j = 0; j < o_height; j++) {
                String c = "" + o_img.getRGB(i, j);
                if (o_colors.get(c) == null) {
                    o_colors.put(c, 1);
                    java.util.List<java.awt.Point> plist = new java.util.ArrayList<java.awt.Point>();
                    o_colorP.put(c, plist);
                } else {
                    o_colors.put(c, o_colors.get(c) + 1);
                    java.awt.Point p = new java.awt.Point(i, j);
                    o_colorP.get(c).add(p);
                }
            }
        }
 
        //将像素最多的几个色素排序
        List<Map.Entry<String, Integer>> o_infoIds =
                new ArrayList<Map.Entry<String, Integer>>(o_colors.entrySet());
        Collections.sort(o_infoIds, new Comparator<Map.Entry<String, Integer>>() {
 
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return (o2.getValue() - o1.getValue());
                //return (o1.getKey()).toString().compareTo(o2.getKey());
            }
        });
 
 
        //开始处理点,将点规范在一个矩形框内
        //java.util.List<Point> objectPoints = o_colorP.get(o_infoIds.get(o_infoIds.size() - 1).getKey());
        java.util.List<Point> objectPoints = o_colorP.get(o_infoIds.get(1).getKey());
        int o_left = -1;
        int o_right = -1;
        int o_top = -1;
        int o_bottom = -1;
        for (Point p : objectPoints) {
            if (o_left == -1) {
                o_left = p.x;
            }
            if (o_top == -1) {
                o_top = p.y;
            }
            if (p.x <= o_left) {
                o_left = p.x;
            }
            if (p.x >= o_right) {
                o_right = p.x;
            }
            if (p.y <= o_top) {
                o_top = p.y;
            }
            if (p.y >= o_bottom) {
                o_bottom = p.y;
            }
        }
        System.out.println("目标o_top=" + o_top + "\to_left=" + o_left + "\to_bottom=" + o_bottom + "\to_right=" + o_right);
 
 
        int sourceWidth = s_right + 1 - s_left;//匹配源的图片宽度
        int sourceHeight = s_bottom + 1 - s_top;//匹配源的图片高度
        System.out.println("匹配源 width=" + sourceWidth + "\theight=" + sourceHeight);
        //数据初始化
        int sourceData[][] = new int[sourceWidth][sourceHeight];
        for (int i = 0; i < sourceWidth; i++) {
            for (int j = 0; j < sourceHeight; j++) {
                sourceData[i][j] = 0;
            }
        }
        //开始赋值
        for (Point p : sourcePoints) {
            sourceData[p.x - s_left][p.y - s_top] = 1;
        }
        /*
        for (int i = 0; i < sourceWidth; i++) {
        for (int j = 0; j < sourceHeight; j++) {
        System.out.print(sourceData[i][j] + ",");
        }
        System.out.println();
        }
         */
 
        int objectWidth = o_right + 1 - o_left;//目标的图片宽度
        int objectHeight = o_bottom + 1 - o_top;//目标的图片高度
        System.out.println("目标 width=" + objectWidth + "\theight=" + objectHeight);
        //数据初始化
        int objectData[][] = new int[objectWidth][objectHeight];
        for (int i = 0; i < objectWidth; i++) {
            for (int j = 0; j < objectHeight; j++) {
                objectData[i][j] = 0;
            }
        }
        //开始赋值
        for (Point p : objectPoints) {
            objectData[p.x - o_left][p.y - o_top] = 1;
        }
        /*
        for (int i = 0; i < objectWidth; i++) {
        for (int j = 0; j < objectHeight; j++) {
        System.out.print(objectData[i][j] + ",");
        }
        System.out.println();
        }
         *
         */
 
        //宽与高都取两者最大值
        int maxWidth = objectWidth > sourceWidth ? objectWidth : sourceWidth;
        int maxHeight = objectHeight > sourceHeight ? objectHeight : sourceHeight;
        //按四方格扫描匹配
        int scanColTimes = maxWidth / 2 + maxWidth % 2;//扫描列最大的次数
        int scanRowTimes = maxHeight / 2 + maxHeight % 2;//扫描行最大的次数
 
        float totalCount = 0.0f;//比对总共百分比
        int count = 0;//比对次数
        for (int row = 0; row < scanRowTimes; row++) {
            for (int col = 0; col < scanColTimes; col++) {
 
                System.out.print("匹配次数:"+count+" row:"+row+";col:"+col+"\t");
                int s_d[] = new int[4];
                int o_d[] = new int[4];
                for (int i = 0; i < 4; i++) {
                    s_d[i] = 0;
                    o_d[i] = 0;
                }
                int morecol = 0;//轮询时多了多少列
                int morerow = 0;//轮询时多了多少行
                //源矩阵填充
                if (col * 2+2 > sourceWidth) {
                    morecol = col * 2+2 - sourceWidth;
                }
                if (row * 2+2 > sourceHeight) {
                    morerow = row * 2+2 - sourceHeight;
                }
                if (morecol > 0 && morerow > 0) {
                    //s_d[0] = sourceData[col * 2 - morecol][row * 2 - morerow];
                } else if (morecol > 0 && morerow <= 0) {
                    if (morecol == 2) {
                    } else if (morecol == 1) {
                        s_d[0] = sourceData[col*2][row*2];
                        s_d[3] = sourceData[col*2][row*2+1];
                    }
                } else if (morerow > 0 && morecol <= 0) {
                    if (morerow == 2) {
                    } else if (morerow == 1) {
                        s_d[0] = sourceData[col*2][row*2];
                        s_d[1] = sourceData[col*2+1][row*2];
                    }
                } else {
                    s_d[0] = sourceData[col*2][row*2];
                    s_d[1] = sourceData[col*2+1][row*2];
                    s_d[2] = sourceData[col*2][row*2+1];
                    s_d[3] = sourceData[col*2+1][row * 2 + 1];
                }
                System.out.print("[");
                for (int i = 0; i < 4; i++) {
                    System.out.print(s_d[i] + ",");
                }
                System.out.print("]");
                System.out.println();
                morecol = 0;//轮询时多了多少列
                morerow = 0;//轮询时多了多少行
                //目标矩阵填充
                if (col * 2+2 > objectWidth) {
                    morecol = col * 2+2 - objectWidth;
                }
                if (row * 2+2 > objectHeight) {
                    morerow = row * 2+2 - objectHeight;
                }
 
                if (morecol > 0 && morerow > 0) {
                    //o_d[0] = objectData[col * 2 - morecol][row * 2 - morerow];
                } else if (morecol > 0 && morerow <= 0) {
                    if (morecol == 2) {
                    } else if (morecol == 1) {
                        o_d[0] = objectData[col*2][row*2];
                        o_d[3] = objectData[col*2][row*2+1];
                    }
                } else if (morerow > 0 && morecol <= 0) {
                    if (morerow == 2) {
                    } else if (morerow == 1) {
                        o_d[0] = objectData[col*2][row*2];
                        o_d[1] = objectData[col*2+1][row*2];
                    }
                } else {
                    o_d[0] = objectData[col*2][row*2];
                    o_d[1] = objectData[col*2+1][row*2];
                    o_d[2] = objectData[col*2][row*2+1];
                    o_d[3] = objectData[col*2+1][row * 2 + 1];
                }
                System.out.print("[");
                for (int i = 0; i < 4; i++) {
                    System.out.print(o_d[i] + ",");
                }
                System.out.print("]");
                System.out.println();
 
                //开始对比
                count++;
                for (int i = 0; i < 4; i++) {
                    if (s_d[i] == o_d[i]) {
                        totalCount += 0.25f;
                    } else {
                        totalCount += 0f;
                    }
                }
                System.out.println("匹配比:" + totalCount);
            }
        }
        totalCount = totalCount / count;
        System.out.println("匹配度:" + totalCount);
    }
 
    public static void main(String[] args) throws Exception {
        readImage("d:/matchImage/邹汶珂.bmp","d:/matchImage/邹汶珂3.bmp");
    }
}

有点乱,整理下就ok。 

过几天继续。。感冒了,休息。

你可能感兴趣的:(java,验证码,识别)