訂閱
糾錯
加入自媒體

如何對圖像進行去噪來繞過驗證碼的方法

?通過使用廣度優(yōu)先搜索算法對圖像進行去噪來繞過驗證碼的新方法

驗證碼被廣泛用作確保對系統(tǒng)執(zhí)行的操作是由人類而不是機器人完成的一種方式。然而,這種方法并不是萬無一失的,尤其是在OCR和計算機視覺技術如此發(fā)達的今天。讓我們從用戶的角度來看,每次想要訪問某個網(wǎng)站時都必須解決驗證碼是一件非常痛苦的事情,尤其是當你每天都需要這樣做時!在本文中,將探索我自己的繞過特定類型驗證碼的方法。該方法利用廣度優(yōu)先搜索 (BFS) 和OpenCV在將圖像傳遞給OCR引擎 (Tesseract) 之前對圖像進行去噪。由于有太多不同類型的文本驗證碼具有不同形式的失真/增強,因此我的方法僅適用于我試圖繞過的特定驗證碼源。但也許你會在我的文章中找到一些對你自己解決驗證碼問題有用的細節(jié)!驗證碼

正如我所提到的,有許多不同類型的文本驗證碼。我試圖繞過的驗證碼的變化對單詞應用傾斜失真,同時用雪狀圖案覆蓋圖像。從根本上(并且幸運的是),這種類型的驗證碼并不太難解決。這是因為驗證碼文本本身沒有任何噪音,可以被 OCR 引擎識別。如果文本被進一步扭曲,像 Tesseract 這樣的開源 OCR 庫將無法讀取文本。因此,我們現(xiàn)在需要做的是一系列圖像過濾以去除所有噪聲并僅保留驗證碼文本。方法我將要討論的方法具有概率特性,這意味著它不能保證在每次試驗中都有效。但是,我們可以利用驗證碼和系統(tǒng)的一些先驗知識來確保我們最大化驗證碼的成功概率。但首先,讓我們談談驗證碼圖像的去噪方法。該過程可以概括為以下步驟:轉換為灰度中值濾波器(內(nèi)核大小 3)圖像閾值處理島嶼去除中值濾波器(內(nèi)核大小 3)

圖像首先轉換為灰度,以將通道數(shù)減少到僅 1。然后注意到在現(xiàn)有的隨機雪花噪聲之上放置了一致的明暗像素點圖案。中值濾波器可以有效去除這種密集和重復的噪聲模式。盡管有輕微的模糊,但經(jīng)過中值濾波器后的圖像更加清晰。我們要做的下一步是對圖像進行閾值處理,將所有像素強度推到 1 或 0。閾值通過反復試驗進行微調(diào),以確保保留文本的所有像素。

在此之后,我們留下了驗證碼文本,周圍是點狀噪聲,這是閾值化的殘留物。這些點分散在圖像周圍,但更多地集中在文本周圍。這就是使用 BFS 的地方,因為我們將使用這種我稱之為“島嶼去除”的方法來去除所有的點狀噪聲。該方法訪問了圖像上的所有黑色像素。在每個黑色像素上,它使用 BFS 找到所有也是黑色的鄰居。

本質(zhì)上,該函數(shù)識別圖像上的所有黑色像素簇,如果簇大小小于預定閾值,則將其移除(即轉換為白色像素)。這種“去除島嶼”方法的靈感來自于相當流行的編程問題Number of Islands,你應該使用 BFS 或 DFS 來計算二維數(shù)組(即島嶼)中 1 的簇數(shù)。最后一步是應用另一個內(nèi)核大小為 3 的中值濾波器來平滑圖像的邊緣。然后,它準備好傳遞到 Tesseract OCR 進行文本提取。從上面的步驟圖可以看出,去噪過程產(chǎn)生了相當積極的輸出。最重要的是,Tesseract 能夠識別輸出正確驗證碼文本的單詞就足夠了。下面是去噪的代碼片段。

def bfs(visited, queue, array, node):
   # I make BFS itterative instead of recursive
   def getNeighboor(array, node):
       neighboors = []
       if node[0]+1           if array[node[0]+1,node[1]] == 0:
               neighboors.a(chǎn)ppend((node[0]+1,node[1]))
       if node[0]-1>0:
           if array[node[0]-1,node[1]] == 0:
               neighboors.a(chǎn)ppend((node[0]-1,node[1]))
       if node[1]+1           if array[node[0],node[1]+1] == 0:
               neighboors.a(chǎn)ppend((node[0],node[1]+1))
       if node[1]-1>0:
           if array[node[0],node[1]-1] == 0:
               neighboors.a(chǎn)ppend((node[0],node[1]-1))
       return neighboors
   queue.a(chǎn)ppend(node)
   visited.a(chǎn)dd(node)
   while queue:
       current_node = queue.pop(0)
       for neighboor in getNeighboor(array, current_node):
           if neighboor not in visited:
   #             print(neighboor)
               visited.a(chǎn)dd(neighboor)
               queue.a(chǎn)ppend(neighboor)
def removeIsland(img_arr, threshold):
   # !important: the black pixel is 0 and white pixel is 1
   while 0 in img_arr:
       x,y = np.where(img_arr == 0)
       point = (x[0],y[0])
       visited = set()
       queue = []
       bfs(visited, queue, img_arr, point)
       
       if len(visited) <= threshold:
           for i in visited:
               img_arr[i[0],i[1]] = 1
       else:
           # if the cluster is larger than threshold (i.e is the text),
           # we convert it to a temporary value of 2 to mark that we
           # have visited it.
           for i in visited:
               img_arr[i[0],i[1]] = 2
               
   img_arr = np.where(img_arr==2, 0, img_arr)
   return img_arr
img  = cv2.imread("temp.png")
# Convert to grayscale
c_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# Median filter
kernel = np.ones((3,3),np.uint8)
out = cv2.medianBlur(c_gray,3)
# Image thresholding
a = np.where(out>195, 1, out)
out = np.where(a!=1, 0, a)
# Islands removing with threshold = 30
out = removeIsland(out, 30)
# Median filter
out = cv2.medianBlur(out,3)
# Convert to Image type and pass it to tesseract
im = Image.fromarray(out*255)
print(pytesseract.image_to_string(im))

結果上面顯示的示例是該方法性能較好的結果之一。就像我之前說的,方法是要看概率的。因此,對于許多輸入,它將無法輸出正確的驗證碼。這是關于驗證碼的先驗知識派上用場的地方,因為我們可以使用它們來創(chuàng)建過濾器檢查,以確保預測的驗證碼文本滿足這些基本標準。

如果方法輸出未通過檢查,我們肯定知道它預測錯誤,只需刷新即可獲得新的驗證碼樣本。我們可以通過查看驗證碼數(shù)據(jù)集得出的一些先驗信息是:它包含正常和大寫的字母數(shù)字字符。驗證碼字符串大小為 4 或 5。因此,我們可以得出以下檢查來確保預測的驗證碼:必須僅包含字母數(shù)字字符。長度在 4 到 5 之間。盡管此過濾器檢查并不能保證預測的驗證碼始終正確,但它有助于增加預測文本正確的可能性。

以上是此方法在輸出正確驗證碼之前進行的試驗次數(shù)分布的直方圖。數(shù)據(jù)是我自己記錄的,因為我個人每天都使用這種方法超過 3 個月?梢钥闯,大多數(shù)試驗次數(shù)低于 20,精確平均值為 9.02。結論本文中介紹的方法有一定的優(yōu)缺點。優(yōu)點是該方法不需要任何訓練,因此不需要標記數(shù)據(jù)集。計算速度快,實現(xiàn)簡單。然而,缺點是該方法是概率性的,因此對于在多次錯誤嘗試驗證碼后阻止用戶的系統(tǒng),使用這種方法可能會鎖定你的帳戶。此外,該方法針對非常特定類型的驗證碼,需要微調(diào),甚至可能不適用于其他類型的驗證碼。

聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內(nèi)容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

人工智能 獵頭職位 更多
掃碼關注公眾號
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯
x
*文字標題:
*糾錯內(nèi)容:
聯(lián)系郵箱:
*驗 證 碼:

粵公網(wǎng)安備 44030502002758號