58同城电话号码识别核心算法

来源:互联网 发布:编程 算法 数学 编辑:程序博客网 时间:2024/05/16 17:52
算法描述
基于要识别的图像生成01二维数组pixarr
将所有的模板读入内存
将所有的特征模板读入内存
将pixarr扫描一遍,去掉孤立点。(孤立点就是指其附近都是0的1点)
找到首次出现1的那一行,记为top,以后就在(top--->top+18)行的范围内识别
row=top  col=0
while(true)
  while(col列没出现1&&col<width)
    col++
  if(col==width)
   break
  以(top,col)为起点,沿着右和下的方向匹配每一个模板,找到吻合率最大的那个模板template0
  那么这块区域所代表的字符就应该是模板template0对应的字符
  if(该字符为'-'并且匹配率不等于1)
     表明匹配有误,往后倒退一列,基于特征模板进行匹配,为保险起见,最多只扫描三列
     将当前得到的字符修改为基于特征模板匹配得到的字符
     记录下该字符
     清理当前区域,为下一步迭代做准备
  else
     记录下该字符
     width0=模板template0的宽度
     以(top,col)为起点,沿着右和下的方向对比模板template0,将template0对应位置处的1置为0
     在(top,col)--->(top+18,col+width0-1)rectangle范围内以深度优先搜寻的方式递归遍历,每次找到一块连通区域,考察该区域

           如果该区域的最右边不超过rectangle右边框,把该区域所有1置为0


package zhanlianyzm;


import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;


import javax.imageio.ImageIO;


public class ShibiesimpleGraphical {
        static int[][] pixarr = null;
        static boolean[][] vistedarr = null;
        static int[] dx = new int[8], dy = new int[8];// 方向数组
        static {
                dx[0] = 0;
                dy[0] = -1;
                dx[1] = -1;
                dy[1] = -1;
                dx[2] = -1;
                dy[2] = 0;
                dx[3] = -1;
                dy[3] = 1;
                dx[4] = 0;
                dy[4] = 1;
                dx[5] = 1;
                dy[5] = 1;
                dx[6] = 1;
                dy[6] = 0;
                dx[7] = 1;
                dy[7] = -1;
        }


        static void resetvistedarr() {
                for (int row = 0; row < vistedarr.length; row++)
                        for (int col = 0; col < vistedarr[0].length; col++)
                                vistedarr[row][col] = false;
        }


        static void makematrix(String imgfile) {
                int plex = -1;
                try {
                        BufferedImage img = ImageIO.read(new File(imgfile));
                        int width = img.getWidth(null);
                        int height = img.getHeight(null);
                        pixarr = new int[height][width];
                        System.out.println("width=" + width + " height=" + height);
                        for (int y = 0; y < height; y++) {
                                for (int x = 0; x < width; x++) {
                                        plex = img.getRGB(x, y);
                                        if (plex == -1)
                                                plex = 0;
                                        else
                                                plex = 1;
                                        pixarr[y][x] = plex;
                                }
                        }


                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                vistedarr = new boolean[pixarr.length][pixarr[0].length];
        }


        static int getfirst1row(int[][] a) {// 返回首次出现1的行下标,返回-1表示a中没有1
                for (int i = 0; i < a.length; i++)
                        for (int j = 0; j < a[0].length; j++) {
                                if (a[i][j] == 1)
                                        return i;
                        }
                return -1;
        }


        static void displaymatrix(int[][] a) {
                for (int row = 0; row < a.length; row++) {
                        for (int col = 0; col < a[0].length; col++)
                                System.out.print(a[row][col] + " ");
                        System.out.println();
                }
        }


        public static void shibie(String imgfile) {
                makematrix(imgfile);// 基于图片生成01二维数组
                displaymatrix(pixarr);
                Template[] templatearr = MakeTemplate.maketemplate();// 将所有的模板读入内存,保存在templatearr中
                int[][] matrix = templatearr[9].getMatrix();
                // displaymatrix(matrix);
                Templatefeature[] templatefeaturearr = MakeTemplatefeature
                                .maketemplatefeature();
                filteroutlier(pixarr); // 考察pixarr整体范围,过滤孤立点


                int top = getfirst1row(pixarr); // 找到首次出现1的那一行
                if (top == -1)
                        return;
                int row = top, col = 0;
                StringBuilder builder = new StringBuilder();
                int debug = 0;
                while (true) {
                        if (debug == 6)
                                System.out.println();
                        debug++;
            boolean featurematch=false;
                        while (col < pixarr[0].length && !have1(col))
                                col++;
                        if (col == pixarr[0].length)
                                break;
                        int max = 0, ps = 0;
                        for (int i = 0; i < templatearr.length; i++) {// 以(top,col)为起点,循环匹配每一个模板
                                int Consistent_rate = match(top, col, templatearr[i]);
                                if (Consistent_rate > max) {
                                        max = Consistent_rate;
                                        ps = i;
                                        // System.out.println("max:" + max);
                                }
                        }
                        System.out.println("ch=" + templatearr[ps].getCh());
                        char ch = templatearr[ps].getCh();
                        if (ch == '-' && max != 100) {
                                String result = null;
                                for (int i = 0; i < templatefeaturearr.length; i++) {// 以(top,col-1)为起点,循环匹配每一个特征模板模板
                                        result = featurematch(top, col - 1, templatefeaturearr[i]);// "12,53"
                                        if (result != null) {
                                                ch = templatefeaturearr[i].getCh();
                                                int firstfeaturepoint_row = templatefeaturearr[i]
                                                                .getFeatureps()[0][0];// 0
                                                int firstfeaturepoint_col = templatefeaturearr[i]
                                                                .getFeatureps()[0][1];// 5
                                                int orow = templatefeaturearr[i].getOrow(); // 5
                                                                                                                                        // firstfeaturepoint_row在ch模板中的相对位置
                                                int ocol = templatefeaturearr[i].getOcol(); // 5
                                                                                                                                        // firstfeaturepoint_col在ch模板中的相对位置
                                                String[] strarr = result.split("\\,");
                                                int feature_startrow = Integer.parseInt(strarr[0]);
                                                int feature_startcol = Integer.parseInt(strarr[1]);
                                                int template_startrow = feature_startrow
                                                                + firstfeaturepoint_row - orow;
                                                int template_startcol = feature_startcol
                                                                + firstfeaturepoint_col - ocol;
                                                System.out.println(template_startrow + ","+ template_startcol);
                                                Template template = null;
                                                for (int im = 0; im < templatearr.length; im++) { // 寻找ch模板
                                                        template = templatearr[im];
                                                        if (template.getCh() == ch)
                                                                break;
                                                }
                                                int width0=template.getWidth();
                                                cleared(template_startrow, template_startcol, template.getMatrix(), ch); // 以(top,col)为起点,对比模板template0,将template0对应位置处的1置为0
                                                filternoise(pixarr, template_startrow, template_startcol, template_startrow + 18, col + width0 - 1); // 扫描局部范围,过滤噪音
                                                resetvistedarr();
                                                System.out.println("过滤噪音后=========================================================================");
                                                displaymatrix(pixarr);
                                                featurematch=true;
                                                break;
                                        }//end if (result != null)


                                }//end for(int i = 0
                                if (result == null)
                                        break;
                        }
                        builder.append(ch);// 当前阶段吻合率最大的模板是templatearr[ps],记下它所对应的字符
           if(featurematch)
                   continue;
                        int width0 = templatearr[ps].getWidth();


                        if (ch == '1')
                                System.out.println();
                        displaymatrix(pixarr);
                        cleared(top, col, templatearr[ps].getMatrix(), ch); // 以(top,col)为起点,对比模板template0,将template0对应位置处的1置为0
                        System.out.println("=================================================================================");
                        System.out.println();
                        displaymatrix(pixarr);
                        // filteroutlier(pixarr, top, col, top + 18, col + width0 - 1); //
                        // 扫描局部范围,过滤孤立点
                        filternoise(pixarr, top, col, top + 18, col + width0 - 1); // 扫描局部范围,过滤噪音
                        resetvistedarr();
                        System.out.println("过滤噪音后=========================================================================");
                        displaymatrix(pixarr);
                }
                System.out.println(builder.toString());
        }


        private static String featurematch(int top, int col,
                        Templatefeature templatefeature) {// 按特征模板匹配,如果成功,则返回特征模板矩阵当时所处位置
                int startcol = col;
                int[][] pixmatrix = templatefeature.getMatrix();
                int[][] featureps = templatefeature.getFeatureps();
                int h = pixmatrix.length;


                for (int x = col; x < col + 2; x++) {// 为保险起见,最多只扫描两列
                        for (int y = top; y <= top + 18 - h; y++) {
                                if (scanmatch(y, x, pixmatrix, featureps))
                                        return y + "," + x;
                        }
                }
                return null;
        }


        private static boolean scanmatch(int y, int x, int[][] pixmatrix,
                        int[][] featureps) {// 从(y,x)起对比pixarr和pixmatrix,重点考察featureps所表示的点是否匹配
                for (int p = 0; p < featureps.length; p++) {
                        int row = featureps[p][0];// 行
                        int col = featureps[p][1];// 列
                        if (pixmatrix[row][col] != pixarr[row + y][col + x])
                                return false;
                }
                return true;
        }


        static int localtop = 0, localleft = 0, localbottom = 0, localright = 0;


        private static void filternoise(int[][] pixarr, int top, int left,int bottom, int right) {// 扫描局部范围,过滤噪音
                for (int row = top; row <= bottom; row++)
                        for (int col = left; col <= right; col++) {
                                if (pixarr[row][col] == 1) {
                                        if (vistedarr[row][col])
                                                continue;
                                        localtop = row;
                                        localleft = col;
                                        localbottom = row;
                                        localright = col;
                                        int localtop0 = localtop, localleft0 = localleft;
                                        int localbottom0 = localbottom, localright0 = localright;
                                        dfsTraversal(row, col, top, left, bottom);// 以(row,col)点为起点,在该局部范围内,找到一块连通区域
                                        /*
                                         * if(localtop==localtop0&&localleft0==localleft&&localbottom0==localbottom&&localright0==localright)
                                         * continue;
                                         */


                                        if (localright <= right) {// 如果该区域的最右边不超过rectangle右边框,把该区域所有1置为0
                                                for (int y = localtop; y <= localbottom; y++)
                                                        for (int x = localleft; x <= localright; x++)
                                                                pixarr[y][x] = 0;
                                        }
                                }
                        }


        }


        private static void dfsTraversal(int row, int col, int top, int left,
                        int bottom) {// 以(row,col)点为起点,深度优先遍历找到一块连通区域
                for (int i = 0; i < dx.length; i++) {// 分别往5个方向测探,上边的方向之前已经扫描处理过了,可以不必再考虑
                        int row_1 = row + dy[i];
                        int col_1 = col + dx[i];
                        // if(row_1 <top || row > bottom || col_1 < left)
                        // continue;
                        if (vistedarr[row_1][col_1])
                                continue;
                        vistedarr[row_1][col_1] = true;
                        if (pixarr[row_1][col_1] == 1) {
                                if (row_1 > localbottom)
                                        localbottom = row_1;
                                if (col_1 < localleft)
                                        localleft = col_1;
                                if (col_1 > localright)
                                        localright = col_1;
                                dfsTraversal(row_1, col_1, top, left, bottom);
                        }


                }


        }


        private static void filteroutlier(int[][] pixarr) {
                filteroutlier(pixarr, 0, 0, pixarr.length - 1, pixarr[0].length - 1);


        }


        private static void filteroutlier(int[][] pixarr, int top, int left,
                        int bottom, int right) {// 扫描pixarr局部,去掉孤立点
                for (int row = top; row <= bottom; row++)
                        for (int col = left; col <= right; col++) {
                                changepoint(pixarr, top, left, bottom, right, row, col);


                        }


        }


        private static void changepoint(int[][] pixarr, int top, int left,
                        int bottom, int right, int row, int col) {
                if (pixarr[row][col] == 0)
                        return;
                boolean have1 = false;
                for (int i = 0; i < dx.length; i++) {// 测探八个方向存在1否?
                        int row_1 = row + dy[i];
                        int col_1 = col + dx[i];
                        if (row_1 >= top && row <= bottom && col_1 >= left
                                        && col_1 <= right) {
                                if (pixarr[row_1][col_1] == 1) {
                                        have1 = true;
                                        break;
                                }
                        }
                }
                if (!have1)
                        pixarr[row][col] = 0;
        }


        private static void cleared(int top, int left, int[][] matrix, char ch) {// 以(top,left)为起点,对比矩阵matrix,将matrix为1的点与pixarr对应位置处的数值置为0
                for (int row = 0; row < matrix.length; row++)
                        for (int col = 0; col < matrix[0].length; col++) {
                                if (ch == '8'
                                                && ((row == 18 && col == 7) || (row == 12 && col == 9)))
                                        System.out.println();
                                if (matrix[row][col] == 1)
                                        pixarr[row + top][col + left] = 0;
                        }


        }


        private static int match(int top, int left, Template template) {// 以(top,left)为起点,匹配模板template,返回吻合率
                int[][] matrix = template.getMatrix();
                double sum = 0.0;
                for (int row = 0; row < matrix.length; row++)
                        for (int col = 0; col < matrix[0].length; col++) {
                                if (matrix[row][col] == pixarr[top + row][left + col])
                                        sum++;
                        }
                // System.out.println("sum="+sum);
                return (int) (sum * 100 / (matrix.length * matrix[0].length));
        }


        private static boolean have1(int col) {//
                int sum = 0;
                int firstrow = 0;
                for (int row = 0; row < pixarr.length; row++)
                        if (pixarr[row][col] == 1) { // return true;
                                if (firstrow == 0)
                                        firstrow = row;
                                sum++;
                        }
                if (sum == 0)
                        return false;
                else {
                        if (sum == 1 && firstrow > 9) {
                                pixarr[firstrow][col] = 0;
                                return false;
                        }
                        return true;
                }
        }


        public static void main(String[] args) {
                String imgfile = "D:/58同城/8.gif";
                shibie(imgfile);


        }


}

0 0
原创粉丝点击