Что нового

Алгоритм распознования капчи. С чего начинать.

Black_Hole

Знающий
Сообщения
126
Репутация
11
inververs

усложняем задачу делаем скрин куска экрана.
Apng_9780081_7195862.png

преобразуем пиксели для наглядности в текстовый файл (фон сайта "-", капча пробел, остальное "+")
Bpng_4723740_7195871.png

Вопрос, смогу ли я внутри белого фона 43х20 клеток, отделить 8х8 бит которые идут друг за другом ;)
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Black_Hole [?]
Вопрос, смогу ли я внутри белого фона 43х20 клеток, отделить 8х8 бит которые идут друг за другом
Незнаю, сможите ли вы. Мне вот не понятно как работать с картинкой в памяти. А вы наверное для каждого пикселя будете 860 раз вызывать _GDIPlus_BitmapGetPixel что бы сформировать массив?
 

Black_Hole

Знающий
Сообщения
126
Репутация
11
inververs

в вашей капче длина, ширина и положение цифр статическое, если вы найдете в цифрах 0-9 уникальное различие в 3-5px, в массив будет поменьше, может кто приложит другой вариант сравнения =)
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
ну это и понятно, если найти 2 -3 уникальные позиции, то весь алгоритм сведется к получению пикселей через _GDIPlus_BitmapGetPixel и простейшей конструкции
IF AND AND...
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
inververs
Я отредактировал код выше, теперь без огромных строк текста(изменил на их хэши).
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
С длиными текстами было нормально, не нужно было подключать дополнительную библиотеку. Ну раз сделали, спасибо.
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
А вот и без текстов, и доп библиотеки, просто по соотношению количества пикселей)

Код:
#include <GDIP.au3>
#include <Color.au3>

Global $delta = 10 ; допустимое отклонение цвета фона от образца
$sImage = @ScriptDir & '\7678.png'

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($sImage)
Global $iWidth = _GDIPlus_ImageGetWidth($hImage)
Global $iHeight = _GDIPlus_ImageGetHeight($hImage)
$iBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
Global $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($iBitmap)

Global $Ground = 0x0402FC

$xLeft = 0
$xRight = 0
$x = 0
$sTring1 = ''

While $x < $iWidth - 1
	While _BlackLine($x) And $x < $iWidth - 1
		$x += 1
	WEnd
	$xLeft = $x
	While Not _BlackLine($x) And $x < $iWidth
		$x += 1
	WEnd
	$xRight = $x - 1
	$hClone = _GDIPlus_BitmapCloneArea($hBitmap, $xLeft, 0, $xRight - $xLeft + 1, $iHeight, $GDIP_PXF24RGB)
	$countstring = _SegmentMatrix($hClone)
	
	Switch $countstring
		Case '745'
			$sTring1 &= '1'
		Case '1044'
			$sTring1 &= '2'
		Case '843'
			$sTring1 &= '3'
		Case '741'
			$sTring1 &= '4'
		Case '1243'
			$sTring1 &= '5'
		Case '938'
			$sTring1 &= '6'
		Case '949'
			$sTring1 &= '7'
		Case '1039'
			$sTring1 &= '8'
		Case '1040'
			$sTring1 &= '9'
		Case '1037'
			$sTring1 &= '0'
	EndSwitch
	_GDIPlus_ImageDispose($hClone)
WEnd

_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($iBitmap)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_Shutdown()

MsgBox(0, 'Заголовок', $sTring1)


Func _SegmentMatrix($hBitmap1)
	Local $tMap1, $Width1, $Height1, $bData1, $bData2, $bData3
	
	$Width1 = _GDIPlus_ImageGetWidth($hBitmap1)
	$Height1 = _GDIPlus_ImageGetHeight($hBitmap1)
	$tMap1 = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $Width1, $Height1, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$bData1 = DllStructGetData(DllStructCreate('byte[' & ($Width1 * $Height1 * 4) & ']', DllStructGetData($tMap1, 'Scan0')), 1)
	_GDIPlus_BitmapUnlockBits($hBitmap1, $tMap1)
	_GDIPlus_BitmapDispose($hBitmap1)
	$bData2 = StringMid($bData1, 1, StringLen($bData1) / 2)
	$bData3 = StringMid($bData1, StringLen($bData1) / 2)
	$aTemp1 = StringRegExp($bData2, '(FCFEFC)FF', 3)
	$aTemp2 = StringRegExp($bData3, '(FC0204)FF', 3)	
	Return Ubound($aTemp1) - 1 & Ubound($aTemp2) - 1
EndFunc   ;==>_SegmentMatrix

Func _BlackLine($stolb)
	Local $color
	For $i = 0 To $iHeight - 1
		$color = '0x' & Hex(_GDIPlus_BitmapGetPixel($hBitmap, $stolb, $i), 6)
		If Abs(_ColorGetRed($color) - _ColorGetRed($Ground)) > $delta Or _
				Abs(_ColorGetGreen($color) - _ColorGetGreen($Ground)) > $delta Or _
				Abs(_ColorGetBlue($color) - _ColorGetBlue($Ground)) > $delta Then Return False
	Next
	Return True
EndFunc   ;==>_BlackLine
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Вот что получилось в итоге:
Код:
Func _Capcha_Rec(ByRef $hBitmap)
	$iRes = ''
	For $f = 9 To 30 Step 7
		$tagGDIPBD = _GDIPlus_BitmapLockBits($hBitmap, $f, 7, 6, 8, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
		$bData = DllStructGetData(DllStructCreate('byte[' & (6 * 8 * 4) & ']', DllStructGetData($tagGDIPBD, 'Scan0')), 1)
		$bData = StringReplace($bData, 'FC0204FF', 0)
		$bData = StringReplace($bData, 'FCFEFCFF', 1)
		_GDIPlus_BitmapUnlockBits($hBitmap, $tagGDIPBD)
		Switch $bData
			Case '0x011110110011110011110111111011110011110011011110' ;0
				$iRes &= 0
			Case '0x001100011100101100001100001100001100001100111111' ;1
				$iRes &= 1
			Case '0x011110110011110011000011001110011000110000111111' ;2
				$iRes &= 2
			Case '0x011110110011000011011110000011000011110011011110' ;3
				$iRes &= 3
			Case '0x000011000111001111011011110011111111000011000011' ;4
				$iRes &= 4
			Case '0x111111110000111110110011000011000011110011011110' ;5
				$iRes &= 5
			Case '0x011110110011110000111110110011110011110011011110' ;6
				$iRes &= 6
			Case '0x111111000011000110000110001100001100011000011000' ;7
				$iRes &= 7
			Case '0x011110110011110011011110110011110011110011011110' ;8
				$iRes &= 8
			Case '0x011110110011110011110011011111000011110011011110' ;9
				$iRes &= 9
			Case Else
		EndSwitch
	Next
	Return SetError(0, 0, $iRes)
EndFunc
 

vskut

Новичок
Сообщения
5
Репутация
0
Копался и наткнулся на знакомый код... ;D

С автором, который писал мне это распознавание, связатся не смог - помогите подогнать код под немного изменённую капчу...
Могу символично отблагодарить "на пиво" ;)
765399c374ea.gif

b46099888fd7.gif

cb6b14994962.gif

abf6f0077d9b.gif


Используется в скрипте "Что получилось в итоге" из поста выше.

-----
Если быть точнее, то не могу разобратся как добавить распознавание ещё 1 цифру т.к. 4 разпознаются, а 5-ая остаётся пустой.
 

vskut

Новичок
Сообщения
5
Репутация
0
:D часа 4 копался ночью...
Превелико благодарю ;)
 

AlexNrt12

Новичок
Сообщения
2
Репутация
0
Re: Алгоритм распознования капчи. С чего начинать

WSWR сказал(а):
inververs

Хотел сделать с поворотом всей картинки, но какие-то глюки с этим вариантом, поэтому взял пример от C2H5OH с разрезанием картинки на части с сильной разницой в цвете http://autoit-script.ru/index.php?topic=11556.0
Скрипт "режет" капчу и сравнивает каждую часть с текстовым образцом цифры.
Вроде работает. Только нужно изменить получение картинки с диска на получение из буфера.

Код:
#include <GDIP.au3>
#include <Color.au3>
#include <Crypt.au3>
_Glob()

Global $delta = 10 ; допустимое отклонение цвета фона от образца
$sImage = @ScriptDir & '\1327.png'

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($sImage)
Global $iWidth = _GDIPlus_ImageGetWidth($hImage)
Global $iHeight = _GDIPlus_ImageGetHeight($hImage)
$iBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
Global $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($iBitmap)

Global $Ground = '0x' & Hex(_GDIPlus_BitmapGetPixel($hBitmap, 1, 1), 6) ; получаем образец цвета фона

$xLeft = 0
$xRight = 0
$x = 0
$sTring1 = ''

While $x < $iWidth - 1
	While _BlackLine($x) And $x < $iWidth - 1
		$x += 1
	WEnd
	$xLeft = $x
	While Not _BlackLine($x) And $x < $iWidth
		$x += 1
	WEnd
	$xRight = $x - 1
	$hClone = _GDIPlus_BitmapCloneArea($hBitmap, $xLeft, 0, $xRight - $xLeft + 1, $iHeight, $GDIP_PXF24RGB)
	$countstring = _SegmentMatrix($hClone)	
	Switch _Crypt_HashData($countstring, $CALG_MD5)
		Case $countstring1			
			$sTring1 &= '1'
		Case $countstring2
			$sTring1 &= '2'
		Case $countstring3
			$sTring1 &= '3'
		Case $countstring4
			$sTring1 &= '4'
		Case $countstring5
			$sTring1 &= '5'
		Case $countstring6
			$sTring1 &= '6'
		Case $countstring7
			$sTring1 &= '7'
		Case $countstring8
			$sTring1 &= '8'
		Case $countstring9
			$sTring1 &= '9'
		Case $countstring0
			$sTring1 &= '0'
	EndSwitch
	_GDIPlus_ImageDispose($hClone)
WEnd

_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($iBitmap)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_Shutdown()

MsgBox(0, 'Заголовок', $sTring1)

Func _SegmentMatrix($hBitmap1)
	Local $tMap1, $bData, $Width1, $Height1
	_GDIPlus_Startup()
	$Width1 = _GDIPlus_ImageGetWidth($hBitmap1)
	$Height1 = _GDIPlus_ImageGetHeight($hBitmap1)
	$tMap1 = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $Width1, $Height1, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$bData1 = DllStructGetData(DllStructCreate('byte[' & ($Width1 * $Height1 * 4) & ']', DllStructGetData($tMap1, 'Scan0')), 1)
	_GDIPlus_BitmapUnlockBits($hBitmap1, $tMap1)
	_GDIPlus_BitmapDispose($hBitmap1)
	Return StringTrimLeft($bData1, 2)
EndFunc   ;==>_SegmentMatrix

Func _BlackLine($stolb)
	Local $color
	For $i = 0 To $iHeight - 1
		$color = '0x' & Hex(_GDIPlus_BitmapGetPixel($hBitmap, $stolb, $i), 6)
		If Abs(_ColorGetRed($color) - _ColorGetRed($Ground)) > $delta Or _
				Abs(_ColorGetGreen($color) - _ColorGetGreen($Ground)) > $delta Or _
				Abs(_ColorGetBlue($color) - _ColorGetBlue($Ground)) > $delta Then Return False
	Next
	Return True
EndFunc   ;==>_BlackLine

Func _Glob()
	Global $countstring1 = '0xE1AFE94DC29AF51804FC8C75E952BB00'
	Global $countstring2 = '0x08224666CF1D9524B7A6E323AC9C8424'
	Global $countstring3 = '0x2AFE694C5E3FC663315FB6D65983F86E'
	Global $countstring4 = '0xEA0C6F46E4B6BFFEC67E23F89AAA55EF'
	Global $countstring5 = '0x4C4FA1B0B5CAFB68E86FF8ECD87CC490'
	Global $countstring6 = '0xFBD76FFAA30C61E29D0ABB74C43F5C8E'
	Global $countstring7 = '0x3AB9ED7A8DE0A26AEA2056954567B6C2'
	Global $countstring8 = '0xD4A7A881A0E00E656DF05F7FDC857E47'
	Global $countstring9 = '0x82A5549839B3602EF5CDEBA21FEA6061'
	Global $countstring0 = '0x8E99DA0D20F02A3CA3781326B45A98B5'
EndFunc   ;==>_Glob


GDIP.au3 здесь http://autoit-script.ru/index.php?topic=1384.0
подгони скрипт под буквы, пожалуйста.
 
Верх