「安卓按鍵」找到圖片上文字的位置(另附切圖+拼圖方法)

大家好,我是公眾號3分鐘學堂的郭立員~

在群里看他們聊天坑赡,因為最近聯(lián)眾打碼不能用了,遇到的過驗證碼問題,有沒有其他解決辦法。

說到這么一個驗證碼,如下圖所示:

驗證碼分兩部分,上部分是傾斜的數(shù)字,下面是4個選項,點擊和上部分相同數(shù)字的選項即為驗證成功。

原本通過這個驗證可以整體截圖對接打碼平臺认臊,然后平臺返回正確選項的位置坐標,腳本點擊此坐標就可以完成驗證了。

要是不用打碼平臺,本地識別可不可以解決呢?

這個驗證的兩部分識別難度是不一樣的竖般,上半部分難度高闭翩,下半部分難度低。

先從下半部分簡單的開始識別,這里我先測試smartocr命令,看看識別的準確率眯搭。

通過測試發(fā)現(xiàn)這個部分的識別率基本接近100%準確允耿,既然準確率非常高蚂蕴,那么就直接使用這個命令低散,不在測試其他的命令。

識別后的結果存入abcd這4個變量中骡楼,分別代表四個選項熔号。

接下來要識別難度大的上半部分,還是測試:

①測試smartocr命令:

正確結果是64217君编,識別結果是66484跨嘉,識別準確是20%

把5個文字分開又重新識別測試川慌,識別準確率依然很低吃嘿,所以smartocr命令可以pass掉了。

這部分之所以難識別梦重,因為數(shù)字是雙層的兑燥,并且每一個字都是傾斜的,關于這類數(shù)字的識別琴拧,我想到了這個軟件降瞳。

這是電腦端的識別,如果安卓端使用,可以把圖片用ftp傳遞電腦上識別挣饥,然后返回識別結果除师。

先看看識別效果:

5個數(shù)字只識別出4個數(shù)字,準確率也很一般扔枫,不過我嘗試把數(shù)字放到一行汛聚,再次識別,發(fā)現(xiàn)準確提高了短荐。

可以看到識別結果倚舀,5個數(shù)字識別正確了4個,準確率是80%忍宋,基本上達到可以用的程度痕貌。

那么怎么把這些數(shù)字放到一行,又是一個難題糠排?

我想到的思路是把每一個數(shù)字截圖出來舵稠,然后再合并到一個圖片上~思路有了我們開始著手去做。

①把每一個圖片的位置找出來

這里每個數(shù)字都不是粘連在一起入宦,那么先橫向把數(shù)字分塊:

分塊原理是縱向遍歷每一列顏色點柱查,如果在一列當中包含任意一個像素是數(shù)字的顏色值,就是有效區(qū)域云石,也就是上圖中紅框唉工,如果一整列都沒有一個符合的顏色點,那么就是非數(shù)字區(qū)域汹忠,也就是紅框以外的淋硝。

這是一個二維遍歷,先遍歷一列的顏色點宽菜,再遍歷所有列谣膳。

為了便于后續(xù)處理,做一個二值化的處理铅乡,具體處理方式是:以列為單位继谚,如果一列中包含數(shù)字的顏色點,記作1阵幸,如果不包含記作0花履,如圖所示:

要實現(xiàn)這個二值化的計算,代碼如下所示:

TracePrintGetBinary(204,179,724,356,"2C4156")FunctionGetBinary(x1,y1,x2,y2,color)Dimbinary,line=""KeepCaptureForj = x1 To x2Fori = y1 To y2IfCmpColor(j, i, color, 0.9)=0 Then binary=1ExitForEndIfIfi = y2 Then binary=0EndIfNextline=line&binaryNextReleaseCaptureGetBinary=lineEndFunction

輸入結果:

結果中有5段連續(xù)的數(shù)字1挚赊,說明驗證圖上有5個數(shù)字诡壁,那問題又來了,怎么提取每個數(shù)字對應連續(xù)1的位置荠割?

可以使用查找命令妹卿,先看示意圖:

示意圖中,先查找“01”就可以找到連續(xù)數(shù)字1的左側,再查找“10”就可以找到連續(xù)數(shù)字1的右側夺克,如果是只有一段連續(xù)數(shù)字1箕宙,那么一次查找即可,但是我們例子中有5段铺纽,所以需要循環(huán)查找扒吁,并且每次查找的起始位置都要在上次查找結果的基礎上向后偏移至少1個位置。

代碼這樣寫:先查找01的

Dimline="00000000000000000000001111111111111111111111111111110000000000000000000000000000000000000000000001111111111111111111111111110000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000"dimleftarr=GetPositions(line,"01")TracePrintjoin(leftarr,"|")FunctionGetPositions(line,str)Dimarr(),i=0DoIfInStr(arr(i - 1) + 1, line, str) = 0 Then ExitDoElsearr(i)=InStr(arr(i - 1) + 1, line, str) + 1i=i+1EndIfLoopGetPositions=arrEndFunction

運算結果:

當前腳本第3行:23|98|188|308|426

把“01”改成“10”在運算一遍:

當前腳本第3行:53|125|227|331|457

兩組數(shù)值都是5個室囊,分別代表5個數(shù)字左側和右側的位置雕崩。

易錯點來了:上面所得到的位置坐標,都是相對坐標融撞,相對的點是數(shù)字區(qū)域左上角的坐標:

還剩下每個數(shù)字的上下位置了盼铁,由于5個數(shù)字之間在縱向是沒有間隙的。

需要單個數(shù)字去獲取上下位置尝偎,方法還是剛剛那樣饶火,不同之處是要先遍歷單行顏色點,再逐行遍歷致扯。

在提醒一遍肤寝,寫代碼的時候還是要注意易錯點——相對坐標

TracePrintGetBinary2(23+204,179,53+204,356,"2C4156")FunctionGetBinary2(x1,y1,x2,y2,color)Dimbinary,line=""KeepCaptureForj = y1 To y2Fori = x1 To x2IfCmpColor(i, j, color, 0.9)=0 Then binary=1ExitForEndIfIfi = x2 Then binary=0EndIfNextline=line&binaryNextReleaseCaptureGetBinary2=lineEndFunction

輸出結果:

當前腳本第1行:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111100000000000000000000000000000000000

獲取位置還是使用查找命令,查找“01”和“10”抖僵,再次強調得到結果是相對坐標鲤看。

把所有的數(shù)字都按照這個方法獲取上下坐標,到此處我們已經可以得到每個數(shù)字的范圍坐標耍群,接下來就是截圖了义桂。

考慮到后面數(shù)字要拼接到一起,所以截圖時外延5像素蹈垢。

擴展計算方式:

加上原始范圍是x1,y1,x2,y2

擴展后的范圍是:x1-5,y1-5,x2+5,y2+5

最終代碼:

截圖(204,179,724,356,"2C4156")Function截圖(x1,y1,x2,y2,color)dimlines= Getbinary(x1,y1,x2,y2,color)TracePrintlinesdimleftarr= GetPositions(lines,"01")TracePrintjoin(leftarr,"|")dimrightarr= GetPositions(lines,"10")TracePrintjoin(rightarr,"|")Fori = 0 To UBOUND(leftarr)dimnewline= GetBinary2(leftarr(i)+x1, y1, rightarr(i)+x1, y2, color)TracePrintnewlineTracePrintleftarr(i)+x1TracePrintinstr(1,newline,"01")+y1TracePrintrightarr(i)+x1TracePrintinstr(1,newline,"10")+y1SnapShot("/sdcard/pictures/yzm/"&i&".png",leftarr(i)+x1-5,instr(1,newline,"01")+y1-5,rightarr(i)+x1+5,instr(1,newline,"10")+y1+5)TracePrint"--------------"NextEndFunctionFunctionGetBinary(x1,y1,x2,y2,color)Dimbinary,line=""KeepCaptureForj = x1 To x2Fori = y1 To y2IfCmpColor(j, i, color, 0.9)=0 Then binary=1ExitForEndIfIfi = y2 Then binary=0EndIfNextline=line&binaryNextReleaseCaptureGetBinary=lineEndFunctionFunctionGetBinary2(x1,y1,x2,y2,color)Dimbinary,line=""KeepCaptureForj = y1 To y2Fori = x1 To x2IfCmpColor(i, j, color, 0.9)=0 Then binary=1ExitForEndIfIfi = x2 Then binary=0EndIfNextline=line&binaryNextReleaseCaptureGetBinary2=lineEndFunctionFunctionGetPositions(line,str)Dimarr(),i=0DoIfInStr(arr(i - 1) + 1, line, str) = 0 Then ExitDoElsearr(i)=InStr(arr(i - 1) + 1, line, str) + 1i=i+1EndIfLoopGetPositions=arrEndFunction

在文件夾里面已經把所有數(shù)字單獨截取出來了慷吊。

截圖部分的內容已經完成,下面開始把所有圖片拼接到一起曹抬。

第一步:獲取所有圖片的尺寸溉瓶,并存入數(shù)組中

DimPicArr()Fori = 0 To 4DimPath = "/sdcard/pictures/yzm/"&i&".png"Dim返回值 = Image.Size(Path)PicArr(i)={返回值[1],返回值[2]}NextDimjson=encode.tabletojson(PicArr)TracePrintjson

運算結果:

當前腳本第9行:[[41,50],[38,46],[50,51],[34,49],[42,49]]

第二步:因為是橫向拼接所有圖片,所以最終合成圖的寬度是所有圖片寬度之和谤民。

Dim PicArr={{41,50},{38,46},{50,51},{34,49},{42,49}}Dim xFor i = 0 To 4? x=x+PicArr[i+1][1]NextTracePrint x

第三步:合成圖的高度堰酿,5張圖中最高的高度就是合成圖的高度。

一組數(shù)字比較大小赖临,可以用冒泡法胞锰,即相鄰兩個數(shù)字比較,前面數(shù)字大于后面數(shù)字兢榨,兩個數(shù)字調換位置,如果前面數(shù)字小于后面數(shù)字,兩個數(shù)字位置不變吵聪,這樣所有大的數(shù)字都被放到后面凌那,那么最后一個數(shù)字就是最大的數(shù)字。

Dim PicArr={{41,50},{38,46},{50,51},{34,49},{42,49}}Dim yFor i = 1 To 4? If PicArr[i][2] > PicArr[i+1][2] Then? ? PicArr[i+1][2]=PicArr[i][2]End IfNexty = PicArr[4][2]TracePrint y

第四步:做一個以驗證圖背景色顏色值的圖片

Dimx=205,y=51DimPixelData = Image.GetScreenData(1,1,x,y)Dimr,g,bDimbackground="C7D1DB"ColorToRGB(background,r,g,b)TracePrintr,g,b Forj = 1 To xFori = 1 To yPixelData[j][i][3]=rPixelData[j][i][2]=gPixelData[j][i][1]=bNextNextImage.SavePixelDataPixelData, "/sdcard/pictures/yzm/aa.png"

第五步:把每張數(shù)字圖片的顏色數(shù)據(jù)吟逝,都賦值給上面的圖片帽蝶。

Dimx=205,y=51DimPicArr={{41,50},{38,46},{50,51},{34,49},{42,49}}DimPixelData =Image.GetPicData("/sdcard/pictures/yzm/aa.png")Forn = 0 To 4Ifn = 0 Then dimm = 0Elsem=m+PicArr[n][1]EndIfdimPixelDataword=Image.GetPicData("/sdcard/pictures/yzm/"&n&".png")Forj = 1 To PicArr[n+1][1]Fori = 1 To PicArr[n + 1][2]Fork = 1 To 3PixelData[m+j][i][k]=PixelDataword[j][i][k]NextNextNextNextImage.SavePixelDataPixelData, "/sdcard/pictures/yzm/ab.png"

完整代碼:

拼圖(4)Function拼圖(num)DimPicArr()Fori = 0 To numDimPath = "/sdcard/pictures/yzm/"&i&".png"Dim返回值 = Image.Size(Path)PicArr(i)={返回值[1],返回值[2]}NextDimjson=encode.tabletojson(PicArr)TracePrintjsonDimxFori = 0 To numx=x+PicArr[i+1][1]NextTracePrintxDimyFori = 1 To numIfPicArr[i][2] > PicArr[i+1][2] Then PicArr[i+1][2]=PicArr[i][2]EndIfNexty=PicArr[num][2]TracePrintyDimPixelData = Image.GetScreenData(1,1,x,y)Dimr,g,bDimbackground="C7D1DB"ColorToRGB(background,r,g,b)TracePrintr,g,b Forj = 1 To xFori = 1 To yPixelData[j][i][3]=rPixelData[j][i][2]=gPixelData[j][i][1]=bNextNextTracePrintx,yPicArr=Encode.JsonToTable(json)Forn = 0 To numIfn = 0 Then dimm = 0Elsem=m+PicArr[n][1]EndIfdimPixelDataword=Image.GetPicData("/sdcard/pictures/yzm/"&n&".png")Forj = 1 To PicArr[n+1][1]Fori = 1 To PicArr[n + 1][2]Fork = 1 To 3PixelData[m+j][i][k]=PixelDataword[j][i][k]NextNextNextNextImage.SavePixelDataPixelData, "/sdcard/pictures/yzm/ab.png"EndFunction

這期文章實現(xiàn)的功能很簡單,但是思考的邏輯過程還是比較復雜的块攒,另外在群里問怎么把兩張圖合并在一起的同學可以來領教程了励稳。

寫到這里有點累了,找到正確答案的識別和比對囱井,不想寫了驹尼,說個大概思路:

(1)比對數(shù)字個數(shù),上部分是5個數(shù)字庞呕,只有選項B/C滿足新翎,排除2個錯誤答案

(2)因為選項的識別準確率非常高,我假定它是完全準確的住练。上部分的數(shù)字和選項比對這么幾個維度地啰,并且用打分形式記錄

①單個數(shù)字對比,一個相同數(shù)字(+5分)

②同位數(shù)字比對讲逛,比如第一位都是6亏吝,每對一位(+10分)

③連續(xù)位數(shù)相同,這個情況比較多盏混,先判斷所有位相同的情況顺呕,如果這個滿足,直接認定為正確答案括饶,后續(xù)是1位不同株茶,2位不同,分值依次降低图焰。

就我們這個例子來說启盛,它非常簡單,幾個選項相差很大技羔,所以這個比對就簡單很多僵闯。

=正文完=

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市藤滥,隨后出現(xiàn)的幾起案子鳖粟,更是在濱河造成了極大的恐慌,老刑警劉巖拙绊,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件向图,死亡現(xiàn)場離奇詭異泳秀,居然都是意外死亡,警方通過查閱死者的電腦和手機榄攀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門嗜傅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人檩赢,你說我怎么就攤上這事吕嘀。” “怎么了贞瞒?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵偶房,是天一觀的道長。 經常有香客問我军浆,道長棕洋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任瘾敢,我火速辦了婚禮拍冠,結果婚禮上,老公的妹妹穿的比我還像新娘簇抵。我一直安慰自己庆杜,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布碟摆。 她就那樣靜靜地躺著晃财,像睡著了一般。 火紅的嫁衣襯著肌膚如雪典蜕。 梳的紋絲不亂的頭發(fā)上断盛,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音愉舔,去河邊找鬼钢猛。 笑死,一個胖子當著我的面吹牛轩缤,可吹牛的內容都是我干的命迈。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼火的,長吁一口氣:“原來是場噩夢啊……” “哼壶愤!你這毒婦竟也來了?” 一聲冷哼從身側響起馏鹤,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤征椒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后湃累,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勃救,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡碍讨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了剪芥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垄开。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡琴许,死狀恐怖税肪,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情榜田,我是刑警寧澤益兄,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站箭券,受9級特大地震影響净捅,放射性物質發(fā)生泄漏。R本人自食惡果不足惜辩块,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一蛔六、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧废亭,春花似錦国章、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至掌动,卻和暖如春四啰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工轩娶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留固耘,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓匙赞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凭迹。 傳聞我的和親對象是個殘疾皇子罚屋,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容