Как заядлый читатель HAD я был заинтересован этим постом, описывающим способ взлома аудио капчи MintEye. Графическая версия также выглядела довольно интересто, так что я подумал, что будет забавно взломать и её.
Вот один из примеров графической капчи MintEye:
Для решения нужно всего лишь подвигать слайдер и выбрать неискажённый вариант изображения. В комментариях на HAD было несколько довольно наивных на мой взгляд предложений решения капчи, основанных на поиске прямых линий. Однако, подобные варианты не сработают с примерами, подобными указанному выше (т. е. содержащим малое количество прямых линий).
После некоторых раздумий я нашёл хороший, надёжный и на удивление простой способ разгадывания капчи. Вот вся его реализация на Python:
import cv2
import sys
import numpy as np
import os
import matplotlib.pyplot as plt
if __name__ == '__main__':
for dir in range(1,14):
dir = str(dir)
total_images = len(os.listdir(dir))+1
points_sob = []
for i in range(1,total_images):
img = cv2.imread(dir+'/'+str(i)+'.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sob = cv2.Sobel(gray, -1, 1, 1)
points_sob.append(np.sum(sob))
x = range(1,total_images)
res = np.argmin(points_sob)+1
print res
plt.plot(res,points_sob[res-1], marker='o', color='r', ls='')
plt.plot(x, points_sob)
plt.savefig(dir+'.png')
plt.show()
(Обратите внимание, что большая часть кода относится к открытию изображения и построению графика. Такие функции, как автоматический разбор изображений и возврат готового результата оставим спаммерам как домашнее задание).
Суть метода в следующем: чем больше изображение «скручено», тем длинне границы. Это можно заметить на картинке, представленной выше, но есть и более наглядный пример:
Обратите внимание на увеличение длины чёрного прямоугольника. Для того, чтобы использовать это, нам нужно посчитать сумму длин границ изображения. Простейший способ сделать это — взять производную изображения (в предложенной выше реализации используется оператор Собеля) и сложить результаты (рекомендуется к прочтению статья о том, как работает оператор Собеля). Затем мы просто выбираем изображение с наименьшей «длиной границ» — оно и будет верным ответом.
Результаты впечатляют, 13 из 13 мною скачанных капч были решены верно этим способом. Эти графики показывают номер изображения на оси Х и «длину границ» на оси Y. Красной точкой отмечен верный ответ.
Интересно, что зачастую абсолютно неискажённое изображение на графике отображается как пик. Это обычно значит, что мы промахнулись с верным ответом на одну картинку влево или вправо (что, впрочем, принимается MintEye как корректный ответ). Происходит это обычно потому, что неискажённое изображение кое-где выглядит чётче и границы выделяются точнее, что влияет на конечную сумму длин.
В завершении хотелось бы сказать, что данная CAPTCHA по своей архитектуре не устойчива ко взлому. Простое «скручивание» изображения всегда может быть легко замечено вышеописанным методом вне зависимости от исходного изображения.
Автор: thevar1able