使用java + OpenCV破解頂象面積驗(yàn)證碼的示例
前言

我們又來破解驗(yàn)證碼啦,今天上場的是–頂象面積驗(yàn)證碼

根據(jù)場景來看,我們需要根據(jù)圖片中分隔好的區(qū)域找到面積最大的一塊來點(diǎn)擊它。
那么我們把它拆分成以下幾個(gè)步驟:
檢測出圖中標(biāo)記的點(diǎn)將檢測出來的點(diǎn)連成線根據(jù)線分割出的區(qū)域計(jì)算各區(qū)域面積,并得到最大面積在該區(qū)域面積中選取一個(gè)坐標(biāo)點(diǎn)作為結(jié)果
一、檢測出圖中標(biāo)記的點(diǎn)
第一個(gè)問題,怎么檢測出圖片中被標(biāo)記出來的點(diǎn)?
這里使用哈里斯角點(diǎn)檢測,這里采用OpenCV中的cornerHarris()來實(shí)現(xiàn)。
參考下面兩篇文章,感興趣的話可以閱讀一下:
Harris角點(diǎn)檢測原理詳解圖像特征之Harris角點(diǎn)檢測
效果如下圖

/**
* 哈里斯角點(diǎn)檢測
* @param img 原圖地址
* @param img2 新圖地址
*/
public void getHarris(String img,String img2) {
System.load(dllPath);
File bFile = new File(img);
try {
Mat mat = Imgcodecs.imread(bFile.getPath());
// 轉(zhuǎn)灰度圖像
Mat gray = new Mat();
Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY);
// 角點(diǎn)發(fā)現(xiàn)
Mat harris = new Mat();
Imgproc.cornerHarris(gray, harris, 2, 3, 0.04);
// 繪制角點(diǎn)
float[] floats = new float[harris.cols()];
for (int i = 0; i < harris.rows(); i++) {
harris.get(i, 0, floats);
for (int j = 0; j < floats.length; j++) {
if (floats[j] > 0.0001) {// 越接近于角點(diǎn)數(shù)值越大
System.out.println(floats[j]);
Imgproc.circle(mat, new Point(j, i), 1, new Scalar(0, 255, 0));
}
}
}
Imgcodecs.imwrite(img2, mat);
} catch (Throwable e) {
e.printStackTrace();
}
}
那標(biāo)記點(diǎn)的檢測完成了。
二、將檢測出來的點(diǎn)連成線
如何連線就比較簡單了,這里我們只需要在繪制角點(diǎn)的時(shí)候?qū)⒔痉秶O(shè)置大一點(diǎn)就好了,這里設(shè)置為5即可。
Imgproc.circle(mat, new Point(j, i), 5, new Scalar(0, 255, 0));
下面是效果圖

連線做到這樣的效果就可以了。
三、根據(jù)線分割出的區(qū)域計(jì)算各區(qū)域面積,并得到最大面積
這里根據(jù)深度優(yōu)先搜索的原理,劃分不同區(qū)域最終選出最大的一塊面積;
深度優(yōu)先搜索大家不會的話就可以參考這篇文章:
基本算法——深度優(yōu)先搜索(DFS)和廣度優(yōu)先搜索(BFS)
這里直接搜索了所有區(qū)域。將占像素量最多的區(qū)域顯示了出來,效果如圖:

/**根據(jù)線分割出的區(qū)域計(jì)算各區(qū)域面積,并得到最大面積
* @param oldimg 原圖
* @param newimg 繪制角點(diǎn)后的圖
*/
*/
public void getMatrix(String oldimg,String newimg) {
File ofile = new File(oldimg);
File nfile = new File(newimg);
try {
BufferedImage oimage = ImageIO.read(ofile);
BufferedImage nimage = ImageIO.read(nfile);
int matrix[][] = new int[nimage.getWidth()][nimage.getHeight()];
int rank = 0;
int maxRank = 0;
int count = 0;
int maxCount = 0;
//將檢測并高亮部分置1,其余部分置0,得到一個(gè)代替圖的二維數(shù)組
for (int w = 0; w < nimage.getWidth(); w++) {
for (int h = 0; h < nimage.getHeight(); h++) {
int[] bgRgb = new int[3];
bgRgb[0] = (nimage.getRGB(w, h) & 0xff0000) >> 16;
bgRgb[1] = (nimage.getRGB(w, h) & 0xff00) >> 8;
bgRgb[2] = (nimage.getRGB(w, h) & 0xff);
if (!(bgRgb[0] <= 70 && bgRgb[1] >= 180 && bgRgb[2] <= 70)) {
matrix[w][h] = 0;
} else {
matrix[w][h] = -1;
}
}
}
//深度優(yōu)先搜索找出最大區(qū)域
while (true) {
int n = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == 0) {
n++;
rank++;
count = dfs(matrix, rank);
if (count > maxCount) {
maxCount = count;
maxRank = rank;
}
}
}
}
if (n == 0)
break;
}
//改變最大區(qū)域顏色
for (int j = 0; j < matrix[0].length; j++) {
for (int i = 0; i < matrix.length; i++) {
if (matrix[i][j] == maxRank){
nimage.setRGB(i, j, new Color(0, 0, 255).getRGB());
}
}
}
ImageIO.write(image, "png", new File(img));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 深度優(yōu)先搜索
* @param matrix 圖信息數(shù)組
* @param n 標(biāo)記數(shù)
* @return
*/
public int dfs(int matrix[][], int rank) {
int count = 0;
int w = -1;
int h = -1;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == 0) {
w = i;
h = j;
break;
}
}
if (w != -1) {
break;
}
}
Stack<JSONObject> stack = new Stack<JSONObject>();
while (matrix[w][h] == 0 || h == stack.peek().getIntValue("h") && w == stack.peek().getIntValue("w")) {
JSONObject json = new JSONObject();
json.put("w", w);
json.put("h", h);
stack.push(json);
matrix[w][h] = rank;
count++;
if (h + 1 < matrix[0].length) {
if (matrix[w][h + 1] == 0) {
h = h + 1;
continue;
}
}
if (w + 1 < matrix.length) {
if (matrix[w + 1][h] == 0) {
w = w + 1;
continue;
}
}
if (h - 1 >= 0) {
if (matrix[w][h - 1] == 0) {
h = h - 1;
continue;
}
}
if (w - 1 >= 0) {
if (matrix[w - 1][h] == 0) {
w = w - 1;
continue;
}
}
stack.pop();
if (!stack.empty()) {
if (h == stack.peek().getIntValue("h") && w == stack.peek().getIntValue("w")) {
stack.pop();
}
}
if (!stack.empty()) {
w = stack.peek().getIntValue("w");
h = stack.peek().getIntValue("h");
} else {
break;
}
}
return count;
}
四、 在該區(qū)域面積中選取一個(gè)坐標(biāo)點(diǎn)作為結(jié)果
這里我們都已經(jīng)找到面積最大區(qū)域了,就隨意取一個(gè)點(diǎn)就好了
將上面代碼中的
//改變最大區(qū)域顏色
for (int j = 0; j < matrix[0].length; j++) {
for (int i = 0; i < matrix.length; i++) {
if (matrix[i][j] == maxRank){
nimage.setRGB(i, j, new Color(0, 0, 255).getRGB());
}
}
}
改為下面的代碼即可
//標(biāo)記選取到的點(diǎn)
boolean flag = false;
for (int j = 0; j < matrix[0].length; j++) {
for (int i = 0; i < matrix.length; i++) {
if (matrix[i][j] == maxRank) {
oimage.setRGB(i, j, new Color(255, 0, 0).getRGB());
System.out.println("w=" + i + "|h=" + j);
flag = true;
break;
}
}
if (flag) {
break;
}
}
結(jié)果展示:

本文思路參考:https://blog.csdn.net/aaronjny/article/details/110245896
到此這篇關(guān)于使用java + OpenCV破解頂象面積驗(yàn)證碼的示例的文章就介紹到這了,更多相關(guān)java頂象面積驗(yàn)證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java生成條形碼code128(親測有效)
- Java 在PDF中添加條形碼的兩種方法
- Java zxing生成條形碼和二維嗎代碼實(shí)例
- Java創(chuàng)建、識別條形碼和二維碼方法示例
- javaWeb如何實(shí)現(xiàn)隨機(jī)圖片驗(yàn)證碼詳解
- java實(shí)現(xiàn)動態(tài)驗(yàn)證碼
- 使用java + selenium + OpenCV破解騰訊防水墻滑動驗(yàn)證碼功能
- Java 生成隨機(jī)驗(yàn)證碼圖片的示例
- java原生動態(tài)生成驗(yàn)證碼
- java生成圖片驗(yàn)證碼的示例代碼
- java數(shù)字和中文算數(shù)驗(yàn)證碼的實(shí)現(xiàn)
- 詳細(xì)介紹Java阿里云的短信驗(yàn)證碼實(shí)現(xiàn)
- 如何使用Java redis實(shí)現(xiàn)發(fā)送手機(jī)驗(yàn)證碼功能
- Java實(shí)戰(zhàn)之用Spring開發(fā)條形碼和驗(yàn)證碼
相關(guān)文章
java解析xml的4種方式的優(yōu)缺點(diǎn)對比及實(shí)現(xiàn)詳解
這篇文章主要介紹了java解析xml的4種方式的優(yōu)缺點(diǎn)對比及實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
Java網(wǎng)絡(luò)編程TCP實(shí)現(xiàn)文件上傳功能
這篇文章主要為大家詳細(xì)介紹了Java網(wǎng)絡(luò)編程TCP實(shí)現(xiàn)文件上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
Maven pom.xml 添加本地jar包依賴以及打包方法
這篇文章主要介紹了Maven pom.xml 添加本地jar包依賴以及打包方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Google?Kaptcha驗(yàn)證碼生成的使用實(shí)例說明
這篇文章主要為大家介紹了Google?Kaptcha驗(yàn)證碼的使用實(shí)例說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03

