極驗(yàn)第四代滑塊驗(yàn)證碼破解(二):滑塊缺口識(shí)別
一、環(huán)境安裝
1. 第三方庫安裝
pip install Pillow
pip install numpy
pip install opencv-python
二、滑塊缺口識(shí)別
1. 與極驗(yàn)三代滑塊對(duì)比
2. 缺口識(shí)別完整代碼
經(jīng)過測(cè)試,極驗(yàn)3的缺口識(shí)別代碼適用極驗(yàn)4缺口識(shí)別,所有我就不做過都的講解了。
極驗(yàn)3缺口識(shí)別鏈接:極驗(yàn)滑塊驗(yàn)證碼破解與研究(三):滑塊缺口識(shí)別
下面的代碼是基于極驗(yàn)3的缺口識(shí)別代碼,做了一點(diǎn)優(yōu)化,增加了cv2.pyrMeanShiftFiltering(金字塔均值漂移)做預(yù)處理
# -*- coding: utf-8 -*-
from pathlib import Path
import PIL
import cv2
import numpy as np
def imshow(img, winname='test', delay=0):
"""cv2展示圖片"""
cv2.imshow(winname, img)
cv2.waitKey(delay)
cv2.destroyAllWindows()
def pil_to_cv2(img):
"""
pil轉(zhuǎn)cv2圖片
:param img: pil圖像, <type 'PIL.JpegImagePlugin.JpegImageFile'>
:return: cv2圖像, <type 'numpy.ndarray'>
"""
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
return img
def bytes_to_cv2(img):
"""
二進(jìn)制圖片轉(zhuǎn)cv2
:param img: 二進(jìn)制圖片數(shù)據(jù), <type 'bytes'>
:return: cv2圖像, <type 'numpy.ndarray'>
"""
# 將圖片字節(jié)碼bytes, 轉(zhuǎn)換成一維的numpy數(shù)組到緩存中
img_buffer_np = np.frombuffer(img, dtype=np.uint8)
# 從指定的內(nèi)存緩存中讀取一維numpy數(shù)據(jù), 并把數(shù)據(jù)轉(zhuǎn)換(解碼)成圖像矩陣格式
img_np = cv2.imdecode(img_buffer_np, 1)
return img_np
def cv2_open(img, flag=None):
"""
統(tǒng)一輸出圖片格式為cv2圖像, <type 'numpy.ndarray'>
:param img: <type 'bytes'/'numpy.ndarray'/'str'/'Path'/'PIL.JpegImagePlugin.JpegImageFile'>
:param flag: 顏色空間轉(zhuǎn)換類型, default: None
eg: cv2.COLOR_BGR2GRAY(灰度圖)
:return: cv2圖像,
"""
if isinstance(img, bytes):
img = bytes_to_cv2(img)
elif isinstance(img, (str, Path)):
img = cv2.imread(str(img))
elif isinstance(img, np.ndarray):
img = img
elif isinstance(img, PIL.Image):
img = pil_to_cv2(img)
else:
raise ValueError(f'輸入的圖片類型無法解析: {type(img)}')
if flag is not None:
img = cv2.cvtColor(img, flag)
return img
def get_distance(bg, tp, im_show=False, save_path=None):
"""
:param bg: 背景圖路徑或Path對(duì)象或圖片二進(jìn)制
eg: 'assets/bg.jpg'
Path('assets/bg.jpg')
:param tp: 缺口圖路徑或Path對(duì)象或圖片二進(jìn)制
eg: 'assets/tp.jpg'
Path('assets/tp.jpg')
:param im_show: 是否顯示結(jié)果, <type 'bool'>; default: False
:param save_path: 保存路徑, <type 'str'/'Path'>; default: None
:return: 缺口位置
"""
# 讀取圖片
bg_img = cv2_open(bg)
tp_gray = cv2_open(tp, flag=cv2.COLOR_BGR2GRAY)
# 金字塔均值漂移
bg_shift = cv2.pyrMeanShiftFiltering(bg_img, 5, 50)
# 邊緣檢測(cè)
tp_gray = cv2.Canny(tp_gray, 255, 255)
bg_gray = cv2.Canny(bg_shift, 255, 255)
# 目標(biāo)匹配
result = cv2.matchTemplate(bg_gray, tp_gray, cv2.TM_CCOEFF_NORMED)
# 解析匹配結(jié)果
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
distance = max_loc[0]
if save_path or im_show:
# 需要繪制的方框高度和寬度
tp_height, tp_width = tp_gray.shape[:2]
# 矩形左上角點(diǎn)位置
x, y = max_loc
# 矩形右下角點(diǎn)位置
_x, _y = x + tp_width, y + tp_height
# 繪制矩形
bg_img = cv2_open(bg)
cv2.rectangle(bg_img, (x, y), (_x, _y), (0, 0, 255), 2)
# 保存缺口識(shí)別結(jié)果到背景圖
if save_path:
save_path = Path(save_path).resolve()
save_path = save_path.parent / f"{save_path.stem}.{distance}{save_path.suffix}"
save_path = save_path.__str__()
cv2.imwrite(save_path, bg_img)
# 顯示缺口識(shí)別結(jié)果
if im_show:
imshow(bg_img)
return distance
if __name__ == '__main__':
d = get_distance(
bg='assets/bg.png',
tp='assets/slice.png',
im_show=True,
save_path='assets/bg.png'
)
print(d)