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