Что нового

Поиск изображения, проблемы

systemseos

Новичок
Сообщения
7
Репутация
0
Привет.
Сразу извинюсь за раздел, не знаю куда поместить тему...

Есть игра (2d) в окне, нужно найти определенное изображение, пробую использовать ImageSearch и BmpSearch но у обоих проблемы с "Opt("PixelCoordMode", 2)", если использовать глобальные координаты то все отлично работает, но мне нужно именно режим координат: клиент.

ImageSearch:
Код:
#include <ImageSearch.au3>

Global $WinName = "Game"
Global $state = "stop"
Opt("PixelCoordMode", 2)
Opt("MouseCoordMode", 2)

HotKeySet("{F4}", "_Exit")

HotKeySet("{F3}", "checkForImage")

WinActivate($WinName)
WinWaitActive($WinName)

while 1
sleep(200)
WEnd

Func _Exit()
   Exit
EndFunc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

global $y = 0, $x = 0

Func checkForImage()
   local $search = _ImageSearch('s.bmp', 0, $x, $y, 0)
   If $search = 1 Then
	  MouseMove($x, $y, 10)
   EndIf
EndFunc
завершается с ошибкой:
Код:
 (28) : ==> Variable used without being declared.:
local $search = _ImageSearch('s.bmp', 0, $x, $y, 0)
local $search = _ImageSearch('s.bmp', 0, ^ ERROR

BmpSearch:
Код:
#include <ScreenCapture.au3>
#include "BmpSearch.au3"

Global $WinName = "Game"
Global $state = "stop"
Opt("PixelCoordMode", 2)
Opt("MouseCoordMode", 2)
WinActivate($WinName)
WinWaitActive($WinName)

HotKeySet("{F4}", "_Exit")
HotKeySet("{F3}", "checkForImage")

Func _Exit()
   Exit
EndFunc

_GDIPlus_Startup()

While 1
   Sleep(100)
   ImSerch()
WEnd



Func ImSerch()
   $hSource = _ScreenCapture_Capture()

   $hBmp = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\s.bmp")
   $hFind = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
   $aCoords = _BmpSearch($hSource, $hFind, 1)
   If @error Then
   Else
	  MouseMove($aCoords[1][2], $aCoords[1][3], 10)

   EndIf

EndFunc
Здесь не правильные координаты, со смещением.

Подскажите что делаю не так, заранее спасибо!


Добавлено:
Сообщение автоматически объединено:

спасибо, но это понятно :smile:
а вот на счет ImageSearch? Переменные $x и $y объявлены, думаю что проблема в самом ImageSearch.au3 или .dll
Для меня это темный лес, может что подскажите.

на всякий выложу ImageSearch.au3
Код:
#include-once
; ------------------------------------------------------------------------------
;
; AutoIt Version: 3.0
; Language:       English
; Description:    Functions that assist with Image Search
;                 Require that the ImageSearchDLL.dll be loadable
;
; ------------------------------------------------------------------------------

;===============================================================================
;
; Description:      Find the position of an image on the desktop
; Syntax:           _ImageSearchArea, _ImageSearch
; Parameter(s):
;                   $findImage - the image to locate on the desktop
;                   $tolerance - 0 for no tolerance (0-255). Needed when colors of
;                                image differ from desktop. e.g GIF
;                   $resultPosition - Set where the returned x,y location of the image is.
;                                     1 for centre of image, 0 for top left of image
;                   $x $y - Return the x and y location of the image
;
; Return Value(s):  On Success - Returns 1
;                   On Failure - Returns 0
;
; Note: Use _ImageSearch to search the entire desktop, _ImageSearchArea to specify
;       a desktop region to search
;
;===============================================================================
Func _ImageSearch($findImage,$resultPosition,ByRef $x, ByRef $y,$tolerance, $HBMP=0)
   return _ImageSearchArea($findImage,$resultPosition,0,0,@DesktopWidth,@DesktopHeight,$x,$y,$tolerance,$HBMP)
EndFunc

Func _ImageSearchArea($findImage,$resultPosition,$x1,$y1,$right,$bottom,ByRef $x, ByRef $y, $tolerance,$HBMP=0)
	;MsgBox(0,"asd","" & $x1 & " " & $y1 & " " & $right & " " & $bottom)
	if $tolerance>0 then $findImage = "*" & $tolerance & " " & $findImage
If IsString($findImage) Then
	$result = DllCall("ImageSearchDLL.dll","str","ImageSearch","int",$x1,"int",$y1,"int",$right,"int",$bottom,"str",$findImage,"ptr",$HBMP)
Else
	$result = DllCall("ImageSearchDLL.dll","str","ImageSearch","int",$x1,"int",$y1,"int",$right,"int",$bottom,"ptr",$findImage,"ptr",$HBMP)
EndIf

	; If error exit
    if $result[0]="0" then return 0

	; Otherwise get the x,y location of the match and the size of the image to
	; compute the centre of search
	$array = StringSplit($result[0],"|")

   $x=Int(Number($array[2]))
   $y=Int(Number($array[3]))
   if $resultPosition=1 then
      $x=$x + Int(Number($array[4])/2)
      $y=$y + Int(Number($array[5])/2)
   endif
   return 1
EndFunc

;===============================================================================
;
; Description:      Wait for a specified number of seconds for an image to appear
;
; Syntax:           _WaitForImageSearch, _WaitForImagesSearch
; Parameter(s):
;					$waitSecs  - seconds to try and find the image
;                   $findImage - the image to locate on the desktop
;                   $tolerance - 0 for no tolerance (0-255). Needed when colors of
;                                image differ from desktop. e.g GIF
;                   $resultPosition - Set where the returned x,y location of the image is.
;                                     1 for centre of image, 0 for top left of image
;                   $x $y - Return the x and y location of the image
;
; Return Value(s):  On Success - Returns 1
;                   On Failure - Returns 0
;
;
;===============================================================================
Func _WaitForImageSearch($findImage,$waitSecs,$resultPosition,ByRef $x, ByRef $y,$tolerance,$HBMP=0)
	$waitSecs = $waitSecs * 1000
	$startTime=TimerInit()
	While TimerDiff($startTime) < $waitSecs
		sleep(100)
		$result=_ImageSearch($findImage,$resultPosition,$x, $y,$tolerance,$HBMP)
		if $result > 0 Then
			return 1
		EndIf
	WEnd
	return 0
EndFunc

;===============================================================================
;
; Description:      Wait for a specified number of seconds for any of a set of
;                   images to appear
;
; Syntax:           _WaitForImagesSearch
; Parameter(s):
;					$waitSecs  - seconds to try and find the image
;                   $findImage - the ARRAY of images to locate on the desktop
;                              - ARRAY[0] is set to the number of images to loop through
;								 ARRAY[1] is the first image
;                   $tolerance - 0 for no tolerance (0-255). Needed when colors of
;                                image differ from desktop. e.g GIF
;                   $resultPosition - Set where the returned x,y location of the image is.
;                                     1 for centre of image, 0 for top left of image
;                   $x $y - Return the x and y location of the image
;
; Return Value(s):  On Success - Returns the index of the successful find
;                   On Failure - Returns 0
;
;
;===============================================================================
Func _WaitForImagesSearch($findImage,$waitSecs,$resultPosition,ByRef $x, ByRef $y,$tolerance,$HBMP=0)
	$waitSecs = $waitSecs * 1000
	$startTime=TimerInit()
	While TimerDiff($startTime) < $waitSecs
		for $i = 1 to $findImage[0]
		    sleep(100)
		    $result=_ImageSearch($findImage[$i],$resultPosition,$x, $y,$tolerance,$HBMP)
		    if $result > 0 Then
			    return $i
		    EndIf
		Next
	WEnd
	return 0
EndFunc
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
systemseos
у обоих проблемы с "Opt("PixelCoordMode", 2)"
Эта опция предназначена для собственных функций AutoIt и никакого отношения к указанным UDF не имеет.

Переменные $x и $y объявлены
Выполнение скрипта "упрётся" в цикл и до объявления не дойдёт. Переместите строчку с объявлением переменных вверх - к тем двум глобальным.
 
Автор
S

systemseos

Новичок
Сообщения
7
Репутация
0
разве это не объявление переменных?
global $y = 0, $x = 0

На счет BmpSearch вроде бы разобрался, $hSource = _ScreenCapture_Capture() делает скриншот всего экрана, соответственно я получаю глобальные координаты, а использую их как координаты окна. Вот в чем беда.
Вот интересно, можно ли сделать скриншот только окна игры? А то окно игры в 4-5 раз меньше самого экрана, лишнее телодвижения делает.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
systemseos
разве это не объявление переменных?
Объявление происходит, когда скрипт доходит до нужной строки. Скрипт выполняется сверху вниз. В вашем случае скрипт "остановится" в вечном цикле и до строки с объявлением переменных не дойдёт. Поэтому эту строку нужно переместить наверх - до цикла.

сделать скриншот только окна игры
Смотрите в справке параметры функции _ScreenCapture_Capture() - там можно задать координаты области экрана. В вашем случае нужно определить координаты клиентской области окна (на форуме полно примеров) и передать их в функцию.
Либо используйте функцию _ScreenCapture_CaptureWnd(), которая захватывает указанное окно. Но в этом случае установите соответствующую опцию для мыши (0).
 
Автор
S

systemseos

Новичок
Сообщения
7
Репутация
0
Поэтому эту строку нужно переместить наверх - до цикла
Я понял, цикл переместил в конец скрипта, но в этом случае APPCRASH "Autoit v3 Script", ну да ладно, буду использовать BmpSearch, вроде бы новее и быстрее работает.

установите соответствующую опцию для мыши (0)
Имеете в виду
Opt("MouseCoordMode", 2) >> Opt("MouseCoordMode", 0) ?

Либо используйте функцию _ScreenCapture_CaptureWnd()
Похоже то что надо.

Возвращаемое значение

Если параметр $sFileName - пустая строка, то функция захватывает окно/элемент и возвращает дескриптор HBITMAP. Этот дескриптор должен быть освобожден с помощью _WinAPI_DeleteObject. Если в параметре $sFileName указан путь, то изображение сохраняется в файл и ничего не возвращает.
Я так понимаю должно выглядеть так? (Нет возможности сейчас проверить)
Код:
$hSource =  _ScreenCapture_CaptureWnd ('', $hWnd)

И после использования освободить ресурс с помощью
Код:
_WinAPI_DeleteObject

Не могли бы тут разъяснить, обычно сборщики мусора и все такое :smile: с ручным не когда не сталкивался.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
systemseos
Нет возможности сейчас проверить
Не спешите. Спокойно всё проверьте. Я подожду. :smile:

сборщики мусора и все такое
Когда скрипт закончит работу объекты и "всё такое" будут уничтожены автоматически. Но во время работы система не знает - нужен вам ещё объект или нет. Поэтому, чтобы не расходовать зря память, ненужные объекты удаляют вручную
Код:
_WinAPI_DeleteObject($hSource)
Если за время работы скрипта у вас создаются десятки объектов, то можно и не париться с удалением. Если десятки сотен - лучше задуматься.
 
Автор
S

systemseos

Новичок
Сообщения
7
Репутация
0
За все время будет создаваться сотни тысяч объектов) смотря сколько будет работать конечно.

В итоге получилось так:
Код:
#include <ScreenCapture.au3>
#include <BmpSearch.au3>
#include <WinAPI.au3>

Opt("PixelCoordMode", 2)
Opt("MouseCoordMode", 2)

$hWnd = WinWait("[CLASS:Game]", "", 5)
WinActivate($hWnd)

HotKeySet("{F4}", "_Exit")

Func _Exit()
   Exit
EndFunc

_GDIPlus_Startup()

Func ImSerch()
   ;$hSource = _ScreenCapture_Capture()
   $hSource = _ScreenCapture_CaptureWnd('',$hWnd)
   $hBmp = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\s.bmp")
   $hFind = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
   $aCoords = _BmpSearch($hSource, $hFind, 1)
   If @error Then
   Else
	  MouseClick("left",$aCoords[1][2], $aCoords[1][3], 2, 0)
   EndIf
   _WinAPI_DeleteObject($hSource)
EndFunc

While 1
   Sleep(500)
   ImSerch()
WEnd

Спасибо вам огромное!

Но вот на счет
установите соответствующую опцию для мыши (0)
я так и не понял, вроде бы и так все работает, координаты определяются верно.
 
Автор
S

systemseos

Новичок
Сообщения
7
Репутация
0
InnI
Спасибо вам, тему можно закрывать.
 
Верх