近日某眾打碼平台被跑路的消息一出,腳本圈中一片嘩然(我並不是腳本圈的,只是喜歡看群裡人吹逼而已 ),仿佛再也聽不到那句熟悉的廣告語了。這也預示著,第三方打碼平台不靠譜了。但打碼功能有時候又必不可少,這時候怎麼辦呢?當然是自己自己動手豐衣足食啦!最近工作不是很忙,准備撸一個用Python識別驗證碼的系列文章,該系列計劃囊括各種時下比較流行的驗證碼形式,如滑塊、四則運算、點選、手勢、空間推理、谷歌等。已經跑通了的所有代碼都放在了我的知識星球上,需要的話請自取。話不多說,開撸!
讓你選出面積最大的區域,不得不說,驗證碼真的是越來越卷了,越來越花了。
不過這吊驗證碼仿佛圖片不多,背景好像就那麼幾種,也就那些線會變來變去,而且線的顏色相對於背景來說區別還是挺大的。所以大致思路就是想辦法把線和背景分離開來,然後做輪廓檢測,把面積最大的輪廓找出來並計算出輪廓的質心就ojbk了。
1.線的顏色都比較明亮,因此這裡把圖轉成HSV顏色空間,並單獨將V通道拿出來用
原圖:
V通道圖:
2.做個伽馬變換,把越亮的地方搞的越亮,把越暗的地方搞的越暗。
adjusted = gamma_trans(v_img, 9.3)
3.由於有些屬於線上的點可能會比較暗淡,因此想了個法子,把所有像素乘以一個比較大的數字,在加上一定的數值。這樣的話,線上比較暗淡的點也會變亮。
adjusted = cv2.convertScaleAbs(adjusted, alpha=13, beta=20)
4.此時線上的點已經大部分比較接近於白色了,這個時候阈值化一波。
_, adjusted = cv2.threshold(adjusted, 200, 255, cv2.THRESH_BINARY)
5.線段中間有空隙,需要把它們補上白色才好計算輪廓,所以撸一發膨脹。這裡為了盡可能的把孔隙補上,所以核搞得比較大。
kernel = np.ones([12, 12], dtype=np.uint8)
adjusted = cv2.dilate(adjusted, kernel, iterations=2)
6.反個相,因為輪廓檢測默認檢測得是白色區域,但我們需要的是黑色區域的輪廓。
adjusted = np.ones([adjusted.shape[0], adjusted.shape[1]], dtype=np.uint8) * 255 - adjusted
7.輪廓檢測,從眾多輪廓中挑選出最大的輪廓。
8.計算最大輪廓的一階矩就能算出輪廓的中心點坐標。
M = cv2.moments(contours[max_contour_index])
center_x = int(M["m10"] / M["m00"])
center_y = int(M["m01"] / M["m00"])
大概測試了20幾次,對了19次。估計這個驗證碼的圖庫本身就不大,所以這麼做就夠用了。
如果想泛化能力更強的話,還是建議多采集一些圖並且用一些網圖生成一些類似的圖,然後訓練出一個分割模型來做分割。畢竟如果驗證碼的圖變騷了,那麼這種純圖像處理的法子可能就不適用了。