簡單驗證碼圖片識別BMP,C,C++,C#,JAVA,指令碼-網路攻防大賽筆記(1)

來源:互聯網
上載者:User

本文章於2010-04-24 16:09:50發布在本人百度空間.後因某些原因臨時和諧了.現在拿出來看看還是能感覺到自己一直在技術的道路上成長著.緬懷即將逝去的大學校園生活.

//////////////////////////////////////本文開始

應邀和朋友一起組隊參加了學校今年的網路攻防大賽,到目前拿分不算很多,位列第五,題目類型大部分是注入和破解,難度不算太大,不過範圍很廣,感覺能把所有的題都靠自己的能力解出來也算是小了不起了。想把做過的幾道題拿出來思考一下,總結一下對付這種比賽的少許經驗。
=================================================================

題目:validate code
Key Words: Script, bmpget_the_file
今有一壓縮包,其內圖片不知幾許。
請君算出所有圖片上的數與其檔案名稱之乘積,所有乘積的和為KEY。
例:
檔案名稱為1.bmp,圖片上的數為:1234
檔案名稱為5.bmp,圖片上的數為:5678
……
檔案名稱為233.bmp,圖片上的數為:2345
key為:1234 x 1 + 5678 x 5 + ... + 2345 x 233 = ?
解題步驟友情提示:
1、下載壓縮包。
2、求出乘積的和。
3、提交答案。
4、過關,擷取積分。

=================================================================================

其中給定的圖片檔案是9999張(對,就是這麼多:XD)BMP格式的識別碼檔案。解決思路:對於Image Recognition經常用的思路是分割,轉換,採樣,然後和模板資料對比,智能點的都是模糊比對然後在匹配度的某個範圍內確定映像內容。當然針對不同的目的,可以選取某些步驟,省略一些不必要且消耗時間的步驟。所以在開始實現程式之前還是先分析一片吧。用Photoshop來分析這些BMP位元影像檔案,發現這些識別碼比較簡單都是非常格式化的數字,並且無雜訊像素點背景是白色,每張圖片上顯示4位元字。檔案格式是40*10*24bi。並且仔細計算一下後,得到每個數字只佔用了10*6的像素矩陣,當然這個可以不需要顧及,按照10*10來做也是沒有任何問題的,只是程式運行效率的問題。而且映像無任何雜訊像素,統一的白色填充背景。知道了這些我們就可以決定如何對映像進行採樣了。可以先構造一個6*10的二位元組dataTemp[][]所以如果我們直接得到位元影像資料的數組後,對位元影像的每個像素點求RGB值,如果等於背景色的RGB值我們就就讓dataTemp的對應位置的值取0,否則取1.,這樣做就可以不用考慮其他色彩的問題了。採樣完成後我們就得到了一個從源影像地圖過來的數組,把這個數組和模板資料匹配就可以得到這個映像顯示的數字了。這樣做我們就可以省略了講映像轉換為單色映像的步驟,也正因為如此本文中的實現方法不具有通用性。

這隻是說明了處理的大致思路,至於實現方法有很多,純C預言檔案操作,C+windowsAPI,C#,PHP指令碼,當然還有JAVA。不過是工作量的問題,因為純C和windowsAPI需要知道BMP檔案格式的相關知識,比如BMP檔案中位元影像資料起始位移量等,而且需要用數學控制採樣時的掃描次序,所以比較繁雜。這樣一來,指令碼或者JAVA或者C#就成了高效的實現方法。這裡我採用JAVA來實現。

實現先導步驟:
第一步,分割圖片,因為每張圖片四位元,所以分割成四個子圖。
第二步,對一個子圖進行像素點採樣,然後產生映射的數組。
第三步,將得到的數組與模板數組匹配,得到圖片顯示內容。
註:模板數組的產生方法需要對單張圖片進行採樣然後對照圖片內容添加到程式中。

程式碼範例:

/*************************************************************BMP image process routine*2011/04/20tishion @ CUIT*tishion@163.com*************************************************************/import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.File;import java.io.InputStream;import javax.imageio.ImageIO;public class RecgBmp {public static void main(String args[]) throws Exception {//對9999張圖片識別,求乘積,求和long SUM = 0;for(int i=1;i<=9999;i++){String filename = "c:\\bmp\\".concat(String.valueOf(i)).concat(".bmp");String s = Bmp2Num.recognize(ImageIO.read(new File(filename)));System.out.println(s);SUM = SUM + i*Long.parseLong(s);}System.out.println("SUM = " + SUM);}}//驗證碼識別類class Bmp2Num{// 數字模板 0-9static int[][] value = {// num 0;{ 0,1,1,1,1,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0 },// num 1{ 0,0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,1,1,1,0 },// num2{ 0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1 },// num3{ 0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0 },// num4{ 0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,1,1 },// num5{ 1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0 },// num6{ 0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0 },// num7{ 1,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0 },// num8{ 0,1,1,1,1,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0 },// num9{ 0,1,1,1,1,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,0,0 } };public static String recognize(byte[] byteArray) throws Exception {InputStream is = new ByteArrayInputStream(byteArray);BufferedImage image = ImageIO.read(is);return recognize(image);}/*識別映像*/ public static String recognize(BufferedImage image) throws Exception {StringBuffer sb = new StringBuffer("");BufferedImage newim[] = new BufferedImage[4];if(null == image){throw new RuntimeException("iamage is null");}// 映像分成四塊newim[0] = image.getSubimage(0, 0, 6, 10);newim[1] = image.getSubimage(10, 0, 6, 10);newim[2] = image.getSubimage(20, 0, 6, 10);newim[3] = image.getSubimage(30, 0, 6, 10);for (int k = 0; k < 4; k++) {int iw = newim[k].getWidth(null);int ih = newim[k].getHeight(null);int[] pix = new int[iw * ih];// 轉換為0,1的映像數組。掃描映像資料,像素為白色的取值為0,否則取值1;for (int i = 0; i < ih; i++) {for (int j = 0; j < iw; j++) {pix[i * (iw) + j] = newim[k].getRGB(j, i);//System.out.print(pix[i * (iw) + j]);if (pix[i * (iw) + j] == -1118482)//-1118482是空白像素的值pix[i * (iw) + j] = 0;elsepix[i * (iw) + j] = 1;//System.out.print(pix[i * (iw) + j]);}//System.out.println();}//System.out.println();System.out.println();// 得到像匹配的數字。int r = getMatchNum(pix);sb.append(r);}return sb.toString();}/*位元影像轉換成的0、1數組和模板數組進行比較,返回匹配的數字*/private static int getMatchNum(int[] pix) {int result = -1;int temp = 100;int x;for (int k = 0; k <= 9; k++) {x = 0;for (int i = 0; i < pix.length; i++) {x = x + Math.abs(pix[i] - value[k][i]);}if(x == 0){result = k;break;}else if (x < temp){temp = x;result = k;}}return result;}}

網上有很多關於驗證碼識別的解決方案,其中大多數都是比較智能化的,因為都採用了映像轉換的步驟,所以與通用性很強。這裡只是為瞭解決臨時問題而實現的一種比較偷懶的解決方案。畢竟重在結果,能節省時間也不失為一種明智的選擇。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.