算法描述
基于要识别的图像生成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
- 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);
-
- }
-
- }
复制代码
|