图标点选验证码是一种常见的防止自动化攻击的手段,用户需要点击指定的图标来完成验证。这种验证码的破解需要图像处理和目标检测技术的结合。本文将介绍如何通过使用ONNX模型和Siamese神经网络来识别和分割图标点选验证码。
一、技术背景
图标点选验证码的破解分为两部分:图标分割和相似度对比。图标分割用于检测并裁剪出验证码图片中的各个图标;相似度对比则用于确定这些图标是否与指定的目标图标相匹配。
二、图标分割
1. 图像处理
首先,加载并处理图像。为了适应模型的输入要求,需要对图像进行缩放和填充。
python
def padded_resize(im, new_shape=(640, 640), stride=32):
shape = im.shape[:2]
r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]
dw /= 2
dh /= 2
if shape[::-1] != new_unpad:
im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114))
im = im.transpose((2, 0, 1))[::-1]
im = np.ascontiguousarray(im)
im = torch.from_numpy(im).float()
im /= 255
im = im[None].cpu().numpy()
return im
2. ONNX模型推理
加载ONNX模型并进行目标检测。
python
def onnx_model_main(path):
session = onnxruntime.InferenceSession("./models/图标点选_分割图片.onnx", providers=["CPUExecutionProvider"])
image = open(path, "rb").read()
img = np.array(Image.open(BytesIO(image)))
img = img[:, :, :3]
im = padded_resize(img)
pred = session.run([session.get_outputs()[0].name], {session.get_inputs()[0].name: im})[0]
pred = torch.tensor(pred)
pred = non_max_suppression(pred, conf_thres=0.6, iou_thres=0.6, max_det=1000)
coordinate_list = []
for i, det in enumerate(pred):
det[:, :4] = scale_coords(im.shape[2:], det[:, :4], img.shape).round()
for *xyxy, conf, cls in reversed(det):
coordinates = return_coordinates(xyxy, conf)
coordinate_list.append(coordinates)
return sorted(coordinate_list, key=lambda a: a["Confidence"])
3. 画框与裁剪
根据检测结果画出边框并裁剪图标。
python
def drow_rectangle(coordinate, path):
img = cv2.imread(path)
result = cv2.rectangle(img, coordinate.get("leftTop"), coordinate.get("rightBottom"), (0, 0, 255), 2)
cv2.imwrite("new_%s" % path, result)
def cut_image(image, point, name):
lists = point.split('|')
box = (int(lists[0]), int(lists[1]), int(lists[2]) + int(lists[0]), int(lists[3]) + int(lists[1]))
images = image.crop(box)
images.save('{}.png'.format(name), 'PNG')
三、相似度对比
1. Siamese神经网络
使用Siamese网络进行相似度对比。
python
class Siamese(object):
_defaults = {
"model_path": './models/图标点选_相似度.h5',
"input_shape": [60, 60],
"letterbox_image": True,
}
def __init__(self, **kwargs):
self.__dict__.update(self._defaults)
for name, value in kwargs.items():
setattr(self, name, value)
self.generate()
def generate(self):
model_path = os.path.expanduser(self.model_path)
assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.'
self.model = siamese([self.input_shape[0], self.input_shape[1], 3])
self.model.load_weights(self.model_path)
@tf.function
def get_pred(self, photo):
preds = self.model(photo, training=False)
return preds
def detect_image(self, image_1, image_2):
image_1 = cvtColor(image_1)
image_2 = cvtColor(image_2)
image_1 = letterbox_image(image_1, [self.input_shape[1], self.input_shape[0]], self.letterbox_image)
image_2 = letterbox_image(image_2, [self.input_shape[1], self.input_shape[0]], self.letterbox_image)
photo1 = np.expand_dims(preprocess_input(np.array(image_1, np.float32)), 0)
photo2 = np.expand_dims(preprocess_input(np.array(image_2, np.float32)), 0)
return self.get_pred(photo1, photo2)
四、测试与结果
进行模型测试并展示结果。
python
if __name__ == '__main__':
path = r'C:\Users\qiu_feng\Desktop\d1e81bb61df84abfaa41ae92a5e6c787.jpg'
coordinate_onnx = onnx_model_main(path)
num = 0
for j in coordinate_onnx:
num += 1
image = Image.open(path)
name = path[:-4:] + '__切割后图片_' + str(num)
cut_image(image, j['point'], name)
更多内容联系q1436423940