Что нового

Очередной аналог ImageSearch

Castellan

Новичок
Сообщения
32
Репутация
2
Собственно понравилась идея создания масок и работа с ними из .ini, описанная тут: http://autoit-script.ru/index.php/topic,5107.msg69220.html, однако работать с чужой длл-кой не получилось, не совсем все понятно и работает ужасно нестабильно! Решил попробовать написать оное средствами AutoIt. Вот что вышло:
Код:
;собственно сама функция
Func MaskSearch ($MaskName, $x0, $y0, $x, $y, $NameINI)
Global $error = 1
Local $fNameINI = @ScriptDir & "\" & $NameINI
Local $cv = IniRead($fNameINI, $MaskName, "cv", "error") ;берем цвет из маски
If $cv = "error" Then
	MsgBox (0, "Ошибка!", "ошибка чтения файла " & $NameINI & ", не найден параметр CV для" &  $MaskName)
	Exit
EndIf
Local $sh = IniRead($fNameINI, $MaskName, "sh", "error") ; берем погрешность
If $sh = "error" Then
	MsgBox (0, "Ошибка!", "ошибка чтения файла " & $NameINI & ", не найден параметр SH для" &  $MaskName)
	Exit
EndIf
Local $i = 0, $j = 0
Local $str[100], $strX, $StrK, $Nstr, $Nstb, $mask[100] [100], $coord1[3], $XX = $x0, $YY = $y0, $coord1obs
; далее переводим нашу маску из построчного текста в двумерный массив, параллельно определяем размер маски и где находиться первый символ #
For $i = 1 To 100
	Local $strK = IniRead($fNameINI, $MaskName, $i, "error") ; считываем построчно маску
	If $strK = "error" Then ;если ошибка - значит строки закончились - находим число строк
		$Nstr = $i-1
		ExitLoop
	Else ;до тех пор пока строки еще есть - каждую запоминаем в отдельную переменную
	$str[$i] = $strK
	EndIf
	$strX = StringSplit ( $str[$i] , "") ;а теперь каждую строку разбиваем на отдельные символы
	$Nstb = $strX[0] ;число столбцов
	For $j = 1 To $Nstb ;теперь для удобства загоним все символы в двумерный массив
	$mask [$i] [$j] = $strX [$j]
	If $coord1[0] <> "Ok" Then ;тут мы находим первый символ #
		If $mask [$i] [$j] = "#" Then
			$coord1 [0] = "Ok"
			$coord1 [1] = $j
			$coord1 [2] = $i
		EndIf
	EndIf
	Next
Next
;уф, дальше самое сложное 
While $YY < ($y-$Nstr) ;перебираем каждый пиксель
	While $XX < ($x-$Nstb)
		$coord1obs = PixelSearch ($XX+$coord1[1]-1, $YY+$coord1[2]-1, $x-$Nstb+$coord1[1], $y-$Nstr+$coord1[2], $cv, $sh) ; собственно в начале ищем первый пиксель нужного цвета, в следующем цикле, если маска не будет найдена уже будем искать след. ближайшую точку с этим цветом (естественно проверять наличие маски во всех позициях просто смысла нет)
		if Not @error Then ;как только нашли первый пиксель запускаем сравнение с маской
			For $i = 1 To $Nstr
				For $j = 1 To $Nstb
					PixelSearch ($coord1obs[0] + $j - $coord1[1], $coord1obs[1] + $i - $coord1[2], $coord1obs[0] + $j - $coord1[1], $coord1obs[1] + $i - $coord1[2], $cv, $sh) ; начинаем проверять с учетом того, что наш первый пиксель нужного цвета не является первым в маске
					If $mask [$i] [$j] = "#" Then ;тут ничего сложного  = сравниваем найденный пиксель с аналогичным символом в маске
						If Not @error Then ;если совпадает то идем дальше
							If $i = $Nstr And $j = $Nstb Then ;если это последний символ в маске и все совпало - ура мы нашли маску - выводим координаты первого символа найденной маски
								$error = 0
								Return $coord1obs
							EndIf
							ContinueLoop
						Else ;если символ не совпал, прекращаем сравнивать маску в данной позиции (идем на ХХ+1 и(или) УУ+1
							ExitLoop(2)
						EndIf
					Else ;все тоже самое только уже мы не должны найти данный цвет в данном месте :)
						If $mask [$i] [$j] = "-" Then
							If @error Then
								If $i = $Nstr And $j = $Nstb Then
									$error = 0
									Return $coord1obs
								EndIf
								ContinueLoop
							Else
								ExitLoop(2)
							EndIf
						Else ;если не нашли оба символа, значит маска записана некорректно
							MsgBox (0, "Ошибка!", "ошибка чтения " & $NameINI & ", в маске " & $MaskName & " обнаружены неопознанные символы")
							Exit
						EndIf
					EndIf
				Next
			Next
		Else ;если не находим вообще ни одного пикселя нужного цвета, то вообще не сравниваем с маской а сразу выходим и выводим ошибку
			$error = 1
			Return 0
		EndIf
		$XX = $coord1obs[0]+1 ;это чтоб не перебирать все подряд, а только те позиции, которые нам подходят по первому искокому пикселю
	WEnd
	$YY = $coord1obs[1]+1
	$XX = $x0
WEnd
;если все прочесав до сих пор не нашли совпадения - выводим в конце функции ошибку
$error = 1
Return 0
EndFunc
Global $coordMask = MaskSearch ("test2", 700, 50, 780, 230, "mask.ini") ;тут и вызываем нашу функцию с заданными параметрами: имя маски, область поиска и имя ини файла, если маску находим - получаем эррор=0 и координаты первого символа маски, иначе эррор=1 и вместо координат "0"
If $error = 0 Then
	MouseMove ($coordMask[0], $coordMask[1])
	MsgBox (0, "test", "маска найдена!")
Else
	MsgBox (0, "test", "маска не найдена")
EndIf

Вот содержание .ini:
Код:
[test1]
cv = 0xFFFFFF
sh = 30
1 = ----
2 = -###
3 = -#--

[test2]
cv = 0xD4D5D5
sh = 30
1 = ----
2 = -###
3 = ----
4 = -###
5 = ----
Собственно, работает весьма неплохо, но есть несколько но:
1) скорость поиска приемлема только при узком диапазоне поиска и небольшом размере маски - прочесал форум в поисках более быстрой альтернативе пиксельсерчу, но однозначного решения не нашел...
2) при увеличении диапазона поиска по Х все ОК, но при увеличении диапазона по У перестает находить маску О_о, видимо что-то я перемудрил :(
П.С. после отлшифовки Масксерча сразу займусь генератором масок :smile:
П.П.С. надо будет еще добавить возможность пропускать пиксели (пометить в маске например "*") - в купе с генератором получится почти готовый эффективный ОКР =)
 
Верх