分享

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

pig2 发表于 2014-7-11 22:14:33 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 2 26326
算法描述
基于要识别的图像生成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


ShibiesimpleGraphical.java

  1. package zhanlianyzm;
  2. import java.awt.image.BufferedImage;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import javax.imageio.ImageIO;
  6. public class ShibiesimpleGraphical {
  7.         static int[][] pixarr = null;
  8.         static boolean[][] vistedarr = null;
  9.         static int[] dx = new int[8], dy = new int[8];// 方向数组
  10.         static {
  11.                 dx[0] = 0;
  12.                 dy[0] = -1;
  13.                 dx[1] = -1;
  14.                 dy[1] = -1;
  15.                 dx[2] = -1;
  16.                 dy[2] = 0;
  17.                 dx[3] = -1;
  18.                 dy[3] = 1;
  19.                 dx[4] = 0;
  20.                 dy[4] = 1;
  21.                 dx[5] = 1;
  22.                 dy[5] = 1;
  23.                 dx[6] = 1;
  24.                 dy[6] = 0;
  25.                 dx[7] = 1;
  26.                 dy[7] = -1;
  27.         }
  28.         static void resetvistedarr() {
  29.                 for (int row = 0; row < vistedarr.length; row++)
  30.                         for (int col = 0; col < vistedarr[0].length; col++)
  31.                                 vistedarr[row][col] = false;
  32.         }
  33.         static void makematrix(String imgfile) {
  34.                 int plex = -1;
  35.                 try {
  36.                         BufferedImage img = ImageIO.read(new File(imgfile));
  37.                         int width = img.getWidth(null);
  38.                         int height = img.getHeight(null);
  39.                         pixarr = new int[height][width];
  40.                         System.out.println("width=" + width + " height=" + height);
  41.                         for (int y = 0; y < height; y++) {
  42.                                 for (int x = 0; x < width; x++) {
  43.                                         plex = img.getRGB(x, y);
  44.                                         if (plex == -1)
  45.                                                 plex = 0;
  46.                                         else
  47.                                                 plex = 1;
  48.                                         pixarr[y][x] = plex;
  49.                                 }
  50.                         }
  51.                 } catch (IOException e) {
  52.                         // TODO Auto-generated catch block
  53.                         e.printStackTrace();
  54.                 }
  55.                 vistedarr = new boolean[pixarr.length][pixarr[0].length];
  56.         }
  57.         static int getfirst1row(int[][] a) {// 返回首次出现1的行下标,返回-1表示a中没有1
  58.                 for (int i = 0; i < a.length; i++)
  59.                         for (int j = 0; j < a[0].length; j++) {
  60.                                 if (a[i][j] == 1)
  61.                                         return i;
  62.                         }
  63.                 return -1;
  64.         }
  65.         static void displaymatrix(int[][] a) {
  66.                 for (int row = 0; row < a.length; row++) {
  67.                         for (int col = 0; col < a[0].length; col++)
  68.                                 System.out.print(a[row][col] + " ");
  69.                         System.out.println();
  70.                 }
  71.         }
  72.         public static void shibie(String imgfile) {
  73.                 makematrix(imgfile);// 基于图片生成01二维数组
  74.                 displaymatrix(pixarr);
  75.                 Template[] templatearr = MakeTemplate.maketemplate();// 将所有的模板读入内存,保存在templatearr中
  76.                 int[][] matrix = templatearr[9].getMatrix();
  77.                 // displaymatrix(matrix);
  78.                 Templatefeature[] templatefeaturearr = MakeTemplatefeature
  79.                                 .maketemplatefeature();
  80.                 filteroutlier(pixarr); // 考察pixarr整体范围,过滤孤立点
  81.                 int top = getfirst1row(pixarr); // 找到首次出现1的那一行
  82.                 if (top == -1)
  83.                         return;
  84.                 int row = top, col = 0;
  85.                 StringBuilder builder = new StringBuilder();
  86.                 int debug = 0;
  87.                 while (true) {
  88.                         if (debug == 6)
  89.                                 System.out.println();
  90.                         debug++;
  91.             boolean featurematch=false;
  92.                         while (col < pixarr[0].length && !have1(col))
  93.                                 col++;
  94.                         if (col == pixarr[0].length)
  95.                                 break;
  96.                         int max = 0, ps = 0;
  97.                         for (int i = 0; i < templatearr.length; i++) {// 以(top,col)为起点,循环匹配每一个模板
  98.                                 int Consistent_rate = match(top, col, templatearr[i]);
  99.                                 if (Consistent_rate > max) {
  100.                                         max = Consistent_rate;
  101.                                         ps = i;
  102.                                         // System.out.println("max:" + max);
  103.                                 }
  104.                         }
  105.                         System.out.println("ch=" + templatearr[ps].getCh());
  106.                         char ch = templatearr[ps].getCh();
  107.                         if (ch == '-' && max != 100) {
  108.                                 String result = null;
  109.                                 for (int i = 0; i < templatefeaturearr.length; i++) {// 以(top,col-1)为起点,循环匹配每一个特征模板模板
  110.                                         result = featurematch(top, col - 1, templatefeaturearr[i]);// "12,53"
  111.                                         if (result != null) {
  112.                                                 ch = templatefeaturearr[i].getCh();
  113.                                                 int firstfeaturepoint_row = templatefeaturearr[i]
  114.                                                                 .getFeatureps()[0][0];// 0
  115.                                                 int firstfeaturepoint_col = templatefeaturearr[i]
  116.                                                                 .getFeatureps()[0][1];// 5
  117.                                                 int orow = templatefeaturearr[i].getOrow(); // 5
  118.                                                                                                                                         // firstfeaturepoint_row在ch模板中的相对位置
  119.                                                 int ocol = templatefeaturearr[i].getOcol(); // 5
  120.                                                                                                                                         // firstfeaturepoint_col在ch模板中的相对位置
  121.                                                 String[] strarr = result.split("\\,");
  122.                                                 int feature_startrow = Integer.parseInt(strarr[0]);
  123.                                                 int feature_startcol = Integer.parseInt(strarr[1]);
  124.                                                 int template_startrow = feature_startrow
  125.                                                                 + firstfeaturepoint_row - orow;
  126.                                                 int template_startcol = feature_startcol
  127.                                                                 + firstfeaturepoint_col - ocol;
  128.                                                 System.out.println(template_startrow + ","+ template_startcol);
  129.                                                 Template template = null;
  130.                                                 for (int im = 0; im < templatearr.length; im++) { // 寻找ch模板
  131.                                                         template = templatearr[im];
  132.                                                         if (template.getCh() == ch)
  133.                                                                 break;
  134.                                                 }
  135.                                                 int width0=template.getWidth();
  136.                                                 cleared(template_startrow, template_startcol, template.getMatrix(), ch); // 以(top,col)为起点,对比模板template0,将template0对应位置处的1置为0
  137.                                                 filternoise(pixarr, template_startrow, template_startcol, template_startrow + 18, col + width0 - 1); // 扫描局部范围,过滤噪音
  138.                                                 resetvistedarr();
  139.                                                 System.out.println("过滤噪音后=========================================================================");
  140.                                                 displaymatrix(pixarr);
  141.                                                 featurematch=true;
  142.                                                 break;
  143.                                         }//end if (result != null)
  144.                                 }//end for(int i = 0
  145.                                 if (result == null)
  146.                                         break;
  147.                         }
  148.                         builder.append(ch);// 当前阶段吻合率最大的模板是templatearr[ps],记下它所对应的字符
  149.            if(featurematch)
  150.                    continue;
  151.                         int width0 = templatearr[ps].getWidth();
  152.                         if (ch == '1')
  153.                                 System.out.println();
  154.                         displaymatrix(pixarr);
  155.                         cleared(top, col, templatearr[ps].getMatrix(), ch); // 以(top,col)为起点,对比模板template0,将template0对应位置处的1置为0
  156.                         System.out.println("=================================================================================");
  157.                         System.out.println();
  158.                         displaymatrix(pixarr);
  159.                         // filteroutlier(pixarr, top, col, top + 18, col + width0 - 1); //
  160.                         // 扫描局部范围,过滤孤立点
  161.                         filternoise(pixarr, top, col, top + 18, col + width0 - 1); // 扫描局部范围,过滤噪音
  162.                         resetvistedarr();
  163.                         System.out.println("过滤噪音后=========================================================================");
  164.                         displaymatrix(pixarr);
  165.                 }
  166.                 System.out.println(builder.toString());
  167.         }
  168.         private static String featurematch(int top, int col,
  169.                         Templatefeature templatefeature) {// 按特征模板匹配,如果成功,则返回特征模板矩阵当时所处位置
  170.                 int startcol = col;
  171.                 int[][] pixmatrix = templatefeature.getMatrix();
  172.                 int[][] featureps = templatefeature.getFeatureps();
  173.                 int h = pixmatrix.length;
  174.                 for (int x = col; x < col + 2; x++) {// 为保险起见,最多只扫描两列
  175.                         for (int y = top; y <= top + 18 - h; y++) {
  176.                                 if (scanmatch(y, x, pixmatrix, featureps))
  177.                                         return y + "," + x;
  178.                         }
  179.                 }
  180.                 return null;
  181.         }
  182.         private static boolean scanmatch(int y, int x, int[][] pixmatrix,
  183.                         int[][] featureps) {// 从(y,x)起对比pixarr和pixmatrix,重点考察featureps所表示的点是否匹配
  184.                 for (int p = 0; p < featureps.length; p++) {
  185.                         int row = featureps[p][0];// 行
  186.                         int col = featureps[p][1];// 列
  187.                         if (pixmatrix[row][col] != pixarr[row + y][col + x])
  188.                                 return false;
  189.                 }
  190.                 return true;
  191.         }
  192.         static int localtop = 0, localleft = 0, localbottom = 0, localright = 0;
  193.         private static void filternoise(int[][] pixarr, int top, int left,int bottom, int right) {// 扫描局部范围,过滤噪音
  194.                 for (int row = top; row <= bottom; row++)
  195.                         for (int col = left; col <= right; col++) {
  196.                                 if (pixarr[row][col] == 1) {
  197.                                         if (vistedarr[row][col])
  198.                                                 continue;
  199.                                         localtop = row;
  200.                                         localleft = col;
  201.                                         localbottom = row;
  202.                                         localright = col;
  203.                                         int localtop0 = localtop, localleft0 = localleft;
  204.                                         int localbottom0 = localbottom, localright0 = localright;
  205.                                         dfsTraversal(row, col, top, left, bottom);// 以(row,col)点为起点,在该局部范围内,找到一块连通区域
  206.                                         /*
  207.                                          * if(localtop==localtop0&&localleft0==localleft&&localbottom0==localbottom&&localright0==localright)
  208.                                          * continue;
  209.                                          */
  210.                                         if (localright <= right) {// 如果该区域的最右边不超过rectangle右边框,把该区域所有1置为0
  211.                                                 for (int y = localtop; y <= localbottom; y++)
  212.                                                         for (int x = localleft; x <= localright; x++)
  213.                                                                 pixarr[y][x] = 0;
  214.                                         }
  215.                                 }
  216.                         }
  217.         }
  218.         private static void dfsTraversal(int row, int col, int top, int left,
  219.                         int bottom) {// 以(row,col)点为起点,深度优先遍历找到一块连通区域
  220.                 for (int i = 0; i < dx.length; i++) {// 分别往5个方向测探,上边的方向之前已经扫描处理过了,可以不必再考虑
  221.                         int row_1 = row + dy[i];
  222.                         int col_1 = col + dx[i];
  223.                         // if(row_1 <top || row > bottom || col_1 < left)
  224.                         // continue;
  225.                         if (vistedarr[row_1][col_1])
  226.                                 continue;
  227.                         vistedarr[row_1][col_1] = true;
  228.                         if (pixarr[row_1][col_1] == 1) {
  229.                                 if (row_1 > localbottom)
  230.                                         localbottom = row_1;
  231.                                 if (col_1 < localleft)
  232.                                         localleft = col_1;
  233.                                 if (col_1 > localright)
  234.                                         localright = col_1;
  235.                                 dfsTraversal(row_1, col_1, top, left, bottom);
  236.                         }
  237.                 }
  238.         }
  239.         private static void filteroutlier(int[][] pixarr) {
  240.                 filteroutlier(pixarr, 0, 0, pixarr.length - 1, pixarr[0].length - 1);
  241.         }
  242.         private static void filteroutlier(int[][] pixarr, int top, int left,
  243.                         int bottom, int right) {// 扫描pixarr局部,去掉孤立点
  244.                 for (int row = top; row <= bottom; row++)
  245.                         for (int col = left; col <= right; col++) {
  246.                                 changepoint(pixarr, top, left, bottom, right, row, col);
  247.                         }
  248.         }
  249.         private static void changepoint(int[][] pixarr, int top, int left,
  250.                         int bottom, int right, int row, int col) {
  251.                 if (pixarr[row][col] == 0)
  252.                         return;
  253.                 boolean have1 = false;
  254.                 for (int i = 0; i < dx.length; i++) {// 测探八个方向存在1否?
  255.                         int row_1 = row + dy[i];
  256.                         int col_1 = col + dx[i];
  257.                         if (row_1 >= top && row <= bottom && col_1 >= left
  258.                                         && col_1 <= right) {
  259.                                 if (pixarr[row_1][col_1] == 1) {
  260.                                         have1 = true;
  261.                                         break;
  262.                                 }
  263.                         }
  264.                 }
  265.                 if (!have1)
  266.                         pixarr[row][col] = 0;
  267.         }
  268.         private static void cleared(int top, int left, int[][] matrix, char ch) {// 以(top,left)为起点,对比矩阵matrix,将matrix为1的点与pixarr对应位置处的数值置为0
  269.                 for (int row = 0; row < matrix.length; row++)
  270.                         for (int col = 0; col < matrix[0].length; col++) {
  271.                                 if (ch == '8'
  272.                                                 && ((row == 18 && col == 7) || (row == 12 && col == 9)))
  273.                                         System.out.println();
  274.                                 if (matrix[row][col] == 1)
  275.                                         pixarr[row + top][col + left] = 0;
  276.                         }
  277.         }
  278.         private static int match(int top, int left, Template template) {// 以(top,left)为起点,匹配模板template,返回吻合率
  279.                 int[][] matrix = template.getMatrix();
  280.                 double sum = 0.0;
  281.                 for (int row = 0; row < matrix.length; row++)
  282.                         for (int col = 0; col < matrix[0].length; col++) {
  283.                                 if (matrix[row][col] == pixarr[top + row][left + col])
  284.                                         sum++;
  285.                         }
  286.                 // System.out.println("sum="+sum);
  287.                 return (int) (sum * 100 / (matrix.length * matrix[0].length));
  288.         }
  289.         private static boolean have1(int col) {//
  290.                 int sum = 0;
  291.                 int firstrow = 0;
  292.                 for (int row = 0; row < pixarr.length; row++)
  293.                         if (pixarr[row][col] == 1) { // return true;
  294.                                 if (firstrow == 0)
  295.                                         firstrow = row;
  296.                                 sum++;
  297.                         }
  298.                 if (sum == 0)
  299.                         return false;
  300.                 else {
  301.                         if (sum == 1 && firstrow > 9) {
  302.                                 pixarr[firstrow][col] = 0;
  303.                                 return false;
  304.                         }
  305.                         return true;
  306.                 }
  307.         }
  308.         public static void main(String[] args) {
  309.                 String imgfile = "D:/58同城/8.gif";
  310.                 shibie(imgfile);
  311.         }
  312. }
复制代码






已有(2)人评论

跳转到指定楼层
hanchi 发表于 2015-3-7 23:32:42
楼主,您有这道题的数据吗?
回复

使用道具 举报

ainubis 发表于 2015-3-28 01:04:28
不错。谢谢分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条