JavaSE圖像驗(yàn)證碼簡(jiǎn)單識(shí)別程序詳解
本文為大家分享了JavaSE圖像驗(yàn)證碼簡(jiǎn)單識(shí)別程序,供大家參考,具體內(nèi)容如下
首先你應(yīng)該對(duì)圖片進(jìn)行樣本采集,然后將樣本進(jìn)行灰度處理,也就是變成黑白兩色。
然后你就可以使用該類,對(duì)目標(biāo)文件進(jìn)行分析。具體怎么實(shí)現(xiàn)我覺(jué)得這個(gè)類非常清楚,就是將樣本從左都有這么橫向移動(dòng),匹配出一個(gè)合適的就將坐標(biāo)調(diào)整到下個(gè)位置。
此程序已是3年多前寫的,后來(lái)沒(méi)有在深入寫下去,圖像識(shí)別一個(gè)很深的領(lǐng)域,得需要很深的數(shù)學(xué)功底跟思維能力,這個(gè)java的程序效率不高,也不能識(shí)別變形的或者拉伸的圖片,但在那個(gè)年代,已經(jīng)足夠用了,大家如果有更好的開(kāi)源的圖像識(shí)別代碼,請(qǐng)務(wù)必來(lái)信交流:)
/**
* 圖片解析引擎,適合做網(wǎng)站驗(yàn)證碼的分析。
* 首先必須載入樣品,解析器將從左到右橫向掃描,發(fā)現(xiàn)于樣本的就自動(dòng)記錄。
* 當(dāng)然本程序不適合樣本不是唯一的,也就是說(shuō)要識(shí)別的圖片被縮放或者坐標(biāo)變動(dòng)和變形本程序無(wú)法進(jìn)行這樣的識(shí)別。
* 如果圖片中的顏色變化非常大,此程序可能會(huì)有問(wèn)題,當(dāng)然了你可以選擇一個(gè)標(biāo)準(zhǔn)的值做為轉(zhuǎn)換成0,1矩陣的標(biāo)準(zhǔn)。
*
* 樣本的制作:請(qǐng)將樣本轉(zhuǎn)換成灰度模式,只含有兩色最好,當(dāng)然了不轉(zhuǎn)換我也幫你轉(zhuǎn)換了。
*
*/
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) {
// 加入樣本與其樣本對(duì)應(yīng)的數(shù)值
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("所花時(shí)間 = " + (sincetime - startime));
} catch (Exception e) {
e.printStackTrace();
}
}
// ------------------------------------------------------------ Constructors
/**
* 載入所有樣本路徑與其樣本對(duì)應(yīng)的數(shù)值
*
* @param files
*/
public ImageParser(String[] files, String[] values) {
// 只允許樣本創(chuàng)建一次即可
if (swatches == null && swatcheValues == null) {
int fileslength = files.length;
int valueslength = values.length;
if(fileslength != valueslength){
System.out.println("樣本文件與樣本數(shù)值不匹配!請(qǐng)重新設(shè)置!");
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("您未載入樣本,請(qǐng)先載入樣本!");
}
}
/**
* 解析圖片的值
*
* @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
/**
* 判斷一個(gè)矩陣是否在另外的矩陣中
*
* @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坐標(biāo)
* @param y
* Y坐標(biāo)
* @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;
}
/**
* 圖片轉(zhuǎn)換成矩陣數(shù)組
*
* @param filePath
* 文件路徑
* @return 返回矩陣
* @throws Exception
* 可能會(huì)拋出異常
*/
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, 0, 0, null);
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);
// 像素進(jìn)行灰度處理
String sRed = Integer.toHexString(rgb).substring(2, 4);
String sGreen = Integer.toHexString(rgb).substring(4, 6);
String sBlank = Integer.toHexString(rgb).substring(6, 8);
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);
/* 將圖像轉(zhuǎn)換成0,1 */
// 此處的值可以將來(lái)修改成你所需要判斷的值
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();
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java swing 圖像處理多種效果實(shí)現(xiàn)教程
- java如何用Processing生成馬賽克風(fēng)格的圖像
- JAVA演示阿里云圖像識(shí)別API,印刷文字識(shí)別-營(yíng)業(yè)執(zhí)照識(shí)別
- Java實(shí)現(xiàn)圖片旋轉(zhuǎn)、指定圖像大小和水平翻轉(zhuǎn)
- java通過(guò)jni調(diào)用opencv處理圖像的方法
- Java獲取彩色圖像中的主色彩的實(shí)例代碼
- Java圖像之自定義角度旋轉(zhuǎn)(實(shí)例)
- Java OCR tesseract 圖像智能文字字符識(shí)別技術(shù)實(shí)例代碼
- 詳解使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像
- java 使用ImageIO.writer從BufferedImage生成jpeg圖像遇到問(wèn)題總結(jié)及解決
- Java利用AlphaComposite類合并圖像
相關(guān)文章
Arrays.sort如何實(shí)現(xiàn)降序排序
這篇文章主要介紹了Arrays.sort如何實(shí)現(xiàn)降序排序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
springboot+redis自定義注解實(shí)現(xiàn)發(fā)布訂閱的實(shí)現(xiàn)代碼
在Redis中客戶端可以通過(guò)訂閱特定的頻道來(lái)接收發(fā)送至該頻道的消息,本文主要介紹了springboot+redis自定義注解實(shí)現(xiàn)發(fā)布訂閱,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
Spring?Boot集成Milvus快速入門demo示例詳解
Milvus是一種高性能向量數(shù)據(jù)庫(kù),支持從筆記本到大型分布式系統(tǒng)的多環(huán)境運(yùn)行,它以開(kāi)源和云服務(wù)形式提供,是LFAI & Data Foundation的項(xiàng)目,采用Apache 2.0許可,Milvus特別支持高并行化和解耦的系統(tǒng)架構(gòu),使其能夠隨數(shù)據(jù)增長(zhǎng)而擴(kuò)展,支持各種復(fù)雜搜索功能,滿足企業(yè)級(jí)AI應(yīng)用需求2024-09-09
OpenFeign在傳遞參數(shù)為對(duì)象類型是為空的問(wèn)題
這篇文章主要介紹了OpenFeign在傳遞參數(shù)為對(duì)象類型是為空的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Spring boot集成Go-FastDFS實(shí)現(xiàn)圖片上傳刪除等功能實(shí)現(xiàn)
這篇文章主要介紹了Spring boot集成Go-FastDFS實(shí)現(xiàn)圖片上傳刪除等功能實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
springboot 熱啟動(dòng)的過(guò)程圖解
這篇文章主要介紹了springboot 熱啟動(dòng)的過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Java替換int數(shù)組中重復(fù)數(shù)據(jù)的方法示例
這篇文章主要介紹了Java替換int數(shù)組中重復(fù)數(shù)據(jù)的方法,涉及java針對(duì)數(shù)組的遍歷、轉(zhuǎn)換、判斷等相關(guān)操作技巧,需要的朋友可以參考下2017-06-06

