JavaSE圖像驗證碼簡單識別程序

首先你應該對圖片進行樣本採集,然後將樣本進行灰度處理,也就是變成黑白兩色。

然後你就可以使用該類,對目標文件進行分析。具體怎麼實現我覺得這個類非常清楚,就是將樣本從左都有這麼橫向移動,匹配出一個合適的就將座標調整到下個位置。  

此程序已是3年多前寫的,後來沒有在深入寫下去,圖像識別一個很深的領域,得需要很深的數學功底跟思維能力,這個java的程序效率不高,也不能識別變形的或者拉伸的圖片,但在那個年代,已經足夠用了,大家如果有更好的開源的圖像識別代碼,請務必來信交流:)

 

/**
 * 圖片解析引擎,適合做網站驗證碼的分析。
 * 首先必須載入樣品,解析器將從左到右橫向掃描,發現於樣本的就自動記錄。
 * 當然本程序不適合樣本不是唯一的,也就是說要識別的圖片被縮放或者座標變動和變形本程序無法進行這樣的識別。
 * 如果圖片中的顏色變化非常大,此程序可能會有問題,當然了你可以選擇一個標準的值做爲轉換成0,1矩陣的標準。
 * 
 * 樣本的製作:請將樣本轉換成灰度模式,只含有兩色最好,當然了不轉換我也幫你轉換了。
 * 
 
*/


import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;

public class ImageParser {

    
// ------------------------------------------------------------ Private Data

    
// 樣本的矩陣
    private static List swatches      = null;

    
// 樣本的值
    private static List swatcheValues = null;

    
// 圖片文件的矩陣化
    private byte[][]    targetColors;
    
    
// ------------------------------------------------------------ Test main method
    public static void main(String[] args) {
        
// 加入樣本與其樣本對應的數值
        String[] files = new String[10];
        String[] values 
= new String[10];
        
for (int i = 0; i < files.length; i++){
            files[i] 
= "D:/workspace/SZXClientAPP/res/" + i + ".jpg";
            values[i] 
= String.valueOf(i);
        }

        
        ImageParser parse 
= new ImageParser(files, values);
        
long startime = System.currentTimeMillis();
        
try {
            
// 解析圖片
            System.out.println(parse.parseValue("D:/workspace/SZXClientAPP/res/ValidateNum"));
            
long sincetime = System.currentTimeMillis();
            System.out.println(
"所花時間 = " + (sincetime - startime));
        }
 catch (Exception e) {
            e.printStackTrace();
        }

    }


    
// ------------------------------------------------------------ Constructors

    
/**
     * 載入所有樣本路徑與其樣本對應的數值
     * 
     * 
@param files
     
*/

    
public ImageParser(String[] files, String[] values) {
        
// 只允許樣本創建一次即可
        if (swatches == null && swatcheValues == null{
            
int fileslength = files.length;
            
int valueslength = values.length;
            
if(fileslength != valueslength){
                System.out.println(
"樣本文件與樣本數值不匹配!請重新設置!");
                
return;
            }

            swatches 
= new ArrayList(fileslength);
            swatcheValues 
= new ArrayList(valueslength);
            
int i = 0;
            
try {
                
for (; i < files.length; i++{
                    swatches.add(imageToMatrix(files[i]));
                    swatcheValues.add(i, values[i]);
                }

            }
 catch (Exception e) {
                System.out.println(files[i] 
+ " can not be parsed");
                e.printStackTrace();
            }

        }

    }


    
public ImageParser() {
        
super();
        
if (swatches == null || swatcheValues == null{
            System.out.println(
"您未載入樣本,請先載入樣本!");
        }

    }


    
/**
     * 解析圖片的值
     * 
     * 
@param parseFilePath
     *            給出圖片路徑
     * 
@return 返回字符串
     * 
@throws Exception
     
*/

    
public String parseValue(String parseFilePath) throws Exception {
        StringBuffer result 
= new StringBuffer();
        targetColors 
= imageToMatrix(parseFilePath);
        
// printMatrix(targetColors);
        int height = targetColors.length;
        
int targetWidth = targetColors[0].length;

        
int width = 0;
        Iterator it 
= swatches.iterator();
        
while (it.hasNext()) {
            
byte[][] bytes = (byte[][]) it.next();
            
int templen = bytes[0].length;
            
if (templen > width)
                width 
= templen;
        }

        
// System.out.println("MaxWidth = " + width);
        
// System.out.println("MaxHeight = " + height);
        int xTag = 0;
        
while ((xTag + width) < targetWidth) {
            cout: 
{
                Iterator itx 
= swatches.iterator();
                
int i = 0;
                
while (itx.hasNext()) {
                    
byte[][] bytes = (byte[][]) itx.next();
                    
byte[][] temp = splitMatrix(targetColors, xTag, 0, width, height);
                    
// System.out.println(i++);
                    if (isMatrixInBigMatrix(bytes, temp)) {
                        xTag 
+= width;
                        
// System.out.println("new maxtrix: ");
                        
// printMatrix(temp);
                        
                        result.append(swatcheValues.get(i));
                        
break cout;
                    }

                    i
++;
                }

                xTag
++;
            }

        }

        
return result.toString();
    }


    
// ------------------------------------------------------------ Private methods

    
/**
     * 判斷一個矩陣是否在另外的矩陣中
     * 
     * 
@param source
     *            源矩陣
     * 
@param bigMatrix
     *            大的矩陣
     * 
@return 如果存在就返回 true
     
*/

    
private static final boolean isMatrixInBigMatrix(byte[][] source, byte[][] bigMatrix) {
        
if (source == bigMatrix)
            
return true;
        
if (source == null || bigMatrix == null)
            
return false;

        
if (source.length > bigMatrix.length)
            
return false;

        
try {
            
for (int i = 0; i < source.length; i++{
                
if (source[i].length > bigMatrix[i].length)
                    
return false;
            }

        }
 catch (ArrayIndexOutOfBoundsException e) {
            
return false;
        }


        
int height = source.length;
        
int width = source[0].length;
        
int x = 0, y = 0;
        
int i = 0, j = 0;
        
int count = 0;

        
int comparecount = height * width;

        
for (; i < bigMatrix.length - height + 1; i++{
            
for (j = 0; j < bigMatrix[i].length - width + 1; j++{
                cout: 
{
                    x 
= 0;
                    count 
= 0;
                    
for (int k = i; k < height + i; k++{
                        y 
= 0;
                        
for (int l = j; l < width + j; l++{
                            
// System.out.println("bytes[" + x + "][" + y + "]"
                            
// + " = " + source[x][y] + ", " + "other["
                            
// + k + "][" + l + "] = " + bigMatrix[k][l]);
                            if ((source[x][y] & bigMatrix[k][l]) == source[x][y]) {
                                count
++;
                            }
 else
                                
break cout;
                            y
++;
                        }

                        x
++;
                    }

                    
// System.out.println("count = " + count);
                    if (count == comparecount)
                        
return true;
                }

            }

        }

        
return false;
    }


    
/**
     * 切割矩陣
     * 
     * 
@param source
     *            源矩陣
     * 
@param x
     *            X座標
     * 
@param y
     *            Y座標
     * 
@param width
     *            矩陣的寬度
     * 
@param height
     *            矩陣的高度
     * 
@return 切割後的矩陣
     
*/

    
private static final byte[][] splitMatrix(byte[][] source, int x, int y, int width, int height) {
        
byte[][] resultbytes = new byte[height][width];
        
for (int i = y, k = 0; i < height + y; i++, k++{
            
for (int j = x, l = 0; j < width + x; j++, l++{

                resultbytes[k][l] 
= source[i][j];
                
// System.out.println("source[" + i + "][" + j + "]" + " = " +
                
// source[i][j] + ", " + "resultbytes["
                
// + k + "][" + l + "] = " + resultbytes[k][l]);
            }


        }

        
return resultbytes;
    }


    
/**
     * 圖片轉換成矩陣數組
     * 
     * 
@param filePath
     *            文件路徑
     * 
@return 返回矩陣
     * 
@throws Exception
     *             可能會拋出異常
     
*/

    
private byte[][] imageToMatrix(String filePath) throws Exception {
        
// 讀入文件
        Image image = ImageIO.read(new File(filePath));
        
int w = image.getWidth(null);
        
int h = image.getHeight(null);
        BufferedImage src 
= new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        src.getGraphics().drawImage(image, 
00null);

        
byte[][] colors = new byte[h][w];

        
for (int i = 0; i < h; i++{
            
for (int j = 0; j < w; j++{
                
int rgb = src.getRGB(j, i);
                
// 像素進行灰度處理
                String sRed = Integer.toHexString(rgb).substring(24);
                String sGreen 
= Integer.toHexString(rgb).substring(46);
                String sBlank 
= Integer.toHexString(rgb).substring(68);
                
long ired = Math.round((Integer.parseInt(sRed, 16* 0.3 + 0.5d));
                
long igreen = Math.round((Integer.parseInt(sGreen, 16* 0.59 + 0.5d));
                
long iblank = Math.round((Integer.parseInt(sBlank, 16* 0.11 + 0.5d));
                
long al = ired + igreen + iblank;

                
// if (al > 127)
                
// System.out.print(" " + " ");
                
// else
                
// System.out.print(" " + "1");
                
// System.out.print(" " + (tempint > = maxint ? 0 : 1));
                
// System.out.println("tempInt = " + tempint);

                
/* 將圖像轉換成0,1 */
                
// 此處的值可以將來修改成你所需要判斷的值
                colors[i][j] = (byte) (al > 127 ? 0 : 1);
            }

            
// System.out.println();
        }


        
return colors;
    }


    
/**
     * 打印矩陣
     * 
     * 
@param matrix
     
*/

    
private static final void printMatrix(byte[][] matrix) {
        
for (int i = 0; i < matrix.length; i++{
            
for (int j = 0; j < matrix[i].length; j++{
                
if (matrix[i][j] == 0)
                    System.out.print(
" ");
                
else
                    System.out.print(
" 1");
            }

            System.out.println();
        }

    }

}

  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章