Что нового

Поиск кнопки в окне по шаблону картинки

Iniar

Новичок
Сообщения
9
Репутация
0
Здравствуйте, у меня такой вопрос.
Подскажите пожалуйста способ желательно с практическим примером в котором производился бы поиск и нажатие на кнопку по заранее вырезанному из скрина шаблоны части изображения кнопки. Я пока на нулевой стадии разработки увы.
Заранее спасибо.
 
Автор
I

Iniar

Новичок
Сообщения
9
Репутация
0
Хорошо. Вот по Вашей ссылке нашёл пример, но к нему явно что-то не прикреплено до конца...
Код:
#include <ScreenCapture.au3>
#include "BmpSearch.au3"

_GDIPlus_Startup()

$hSource = _ScreenCapture_Capture()
$hBmp = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\test.bmp")
$hFind = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)

$aCoords = _BmpSearch($hSource, $hFind, 1)

If @error Then
  ConsoleWrite("Не найдено" & @CRLF)
Else
  ConsoleWrite("X:" & $aCoords[1][2] & " Y:" & $aCoords[1][3] & " time:" & @extended & @CRLF)
EndIf


Ошибка:
Код:
"C:\BmpSearch.au3" (46) : ==> Variable must be of type "Object".:
Local $iRowInc = ($tSizeSource.X - $tSizeFind.X) * 4
Local $iRowInc = ($tSizeSource.X - $tSizeFind^ ERROR
>Exit code: 1    Time: 0.4355


На том сайте так и не ответили по той же ошибке. Помогите пожалуйста разобраться.
И на счёт ImageSearch.au3
Имею вот этот пример:
Код:
#include <ImageSearch.au3>

;
; Demo on the functions of ImageSearch
; Assumes that you have a Recycle Bin icon at the top left of your screen
; Assumes that you have IE6 or 7 icon visible
; Please make the icon visible or we won't be able to find it
;

MsgBox(0,"MSG","You need to have the should have recycle bin, and preferably, an IE icon, a PDF icon and folder icon for the demo to go nicely. All of them should be visible on the desktop")

$x1=0
$y1=0
;
; find recycle bin and move to the center of it
; change 2nd argument to 0 to return the top left coord instead
$result = _ImageSearch("recycle2.bmp",1,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a empty recycle bin here...")
EndIf

; find recycle bin and move to the center of it
$result = _ImageSearch("recycle2.bmp",0,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a empty recycle bin here... cursor move to top left of image")
EndIf


; find recycle bin and move to the center of it
; change 2nd argument to 0 to return the top left coord instead
$result = _ImageSearch("recycle.bmp",1,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a recycle bin with stuff here...")
EndIf

; find recycle bin and move to the center of it
$result = _ImageSearch("recycle.bmp",0,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a recycle bin with stuff here... cursor move to top left of image")
EndIf



MsgBox(0,"MSG","Search for a recycle bin in the top left corner in a 200x200 box")

; find recycle bin if it is in the top left corner of screen
; change 2nd argument to 0 to return the top left coord instead
$result = _ImageSearchArea("recycle2.bmp",1,0,0,200,200,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a empty recycle bin in top left corner")
EndIf

; find recycle bin if it is in the top left corner of screen
; change 2nd argument to 0 to return the top left coord instead
$result = _ImageSearchArea("recycle.bmp",1,0,0,200,200,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a recycle bin with stuff in top left corner")
EndIf


; I guess most people should at least have an IE icon on the desktop
$result = _ImageSearch("ie7Desktop.bmp",0,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found an IE icon here")
EndIf

; I guess most people should at least have an PDF icon on the desktop
$result = _ImageSearch("pdf.bmp",0,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a PDF icon here")
EndIf

; I guess most people should at least have an Folder icon on the desktop
$result = _ImageSearch("folder.bmp",0,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Found a Folder icon here")
EndIf

; wait for a non empty recycle bin to appear
MsgBox(0,"MSG","Empty your recycle bin and then click OK. Then throw something in the bin within 15s")
$result = _WaitForImageSearch("recycle.bmp",15,1,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Hey... your recycle bin now has stuff")
EndIf

; wait 15s for either the full or empty recycle bin
MsgBox(0,"MSG","Using WaitForImages to see whether you have a full or empty bin")
Dim $anArray[10]
$anArray[0]=2  ; two images to wait to appear
$anArray[1]="recycle.bmp"  ; image 1 to wait for
$anArray[2]="recycle2.bmp"  ; image 2 to wait for
$result = _WaitForImagesSearch($anArray,15,1,$x1,$y1,0)
if $result=1 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Hey... your recycle bin has stuff")
EndIf
if $result=2 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Hey... your recycle bin is empty")
EndIf
if $result=0 Then
	MouseMove($x1,$y1,3)
	MsgBox(0,"Found","Hey... cannot find your recycle bin")
EndIf
Но однозначно понять его не удаётся. При его работе он выполняется будто с середины. Расскажите его работу пожалуйста по пунктам если не сложно.
А так же есть это:
Код:
#include <ImageSearch.au3>

HotKeySet("{F9}","Start")
HotKeySet("{F10}","Stop")

global $y = 0, $x = 0

Func Start()
local $search = _ImageSearchArea('123.jpg', 1, 194, 408, 21, 212, $x, $y, 0)
If $search = 1 Then
MouseMove($x, $y, 10)
EndIf
EndFunc

Func stop()
    Exit
 EndFunc

while 1
sleep(200)
WEnd
Всё лежит в папке с скриптом, но мышь не переходит по координатам, значит не происходит поиск. И верно ли я указал область для поиска? - 194, 408, 21, 212. В AutoIt Info на вкладке mouse вначале поставил точку в левом верхнем углу - x,y - 194, 408, потом поставил точку в нижнем правом углу x,y - 21, 212...
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Iniar
А вы хоть попытались понять, что этот пример делает? Если нет, то он ищет на рабочем столе картинку из файла test.bmp, который находится в папке со скриптом.

на счёт ImageSearch.au3
Ничего не скажу - ни разу не пользовался.
 

Yura

Знающий
Сообщения
36
Репутация
7
Вот вам пример ImageSearch.
По интернету гуляет несколько версий библиотеки с разными dll. Ссылака на скачивание той, что использую сам: https://dl.dropboxusercontent.com/s/43z29kgpgjyeo2m/ImageSearchDLLwithHBmp.zip?dl=1
Оттуда возьмите только ImageSearchDLL.dll! ImageSearch.au3 я правил, потому что там были мелкие ошибки. Его я прикрепляю к сообщению, используйте мой, а не из архива.
Эта версия хороша тем, что с ее помощью можно искать картинку в неактивном перекрытом окне (можно поверх вашего окна открыть другие), а не только с экрана. В свернутом окне искать не получится.

Файлы ImageSearch.au3 и ImageSearchDLL.dll перед запуском положите в ту же папку, где ваш скрипт.
Все что от вас требуется - написать в скрипте название вашего файла в формате BMP с искомым изображением (должен лежать в папке со скриптом) и название окна, в котором ищете. На изображении не должно быть никаких белых лишних полей вокруг.

Еще, если у вас х64, то не знаю будет работать или нет.

Поиск в окне (координаты получите относительно левого верхнего угла окна):
Код:
#include "ImageSearch.au3"
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Array.au3>

_GDIPlus_Startup()

$image = _Load_img("image.bmp") ;вместо Image.bmp пишем название картинки, которую ищем
;_WinAPI_SaveHBITMAPToFile("1.bmp", $image);можно сохранить картинку и проверить все ли правильно загрузили

Global $hwnd_win = WinGetHandle("Window title") ;вместо Window title пишем название окна, в котором ищем
Global $win_pos = WinGetPos($hwnd_win);получаем размеры окна и позицию

$hBMP = _WinCapture($hwnd_win, $win_pos[2], $win_pos[3]) ;делаем скриншот окна
;_WinAPI_SaveHBITMAPToFile("2.bmp", $hBMP) ;можно сохранить скриншот и проверить все ли правильно сфоткали

$img_coord = _Img_search($hBMP, $image, 0);ищем картинку на скриншоте, вместо 0 можно задать отклонение цветов
_ArrayDisplay($img_coord);смотрим координаты цетра найденой картинки

Func _Img_search($hBitmap, $image_for_search, $ShadeVariation) ;поиск картинки
	$x = 0
	$y = 0
	$image_for_search_clone = _WinAPI_CopyImage($image_for_search)
	$result = _ImageSearch($image_for_search_clone, 1, $x, $y, $ShadeVariation, $hBitmap) ;если вместо "1"
	;написать, то получим координаты не центра картинки, а левого верхнего угла
	_WinAPI_DeleteObject($image_for_search_clone)

	If $result == 1 Then
		Local $img_coord[2] = [$x, $y]
	Else
		Local $img_coord[2] = [-1, -1]
	EndIf
	Return $img_coord
EndFunc

Func _Load_img($img_name) ;загрузка картинки, которую ищем
	$hImage =_GDIPlus_ImageLoadFromFile(@ScriptDir & $img_name)
;ConsoleWrite($hImage)
	$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
	_GDIPlus_ImageDispose($hImage)
	Return $hBitmap
EndFunc

Func _WinCapture($hWnd, $iWidth, $iHeight) ; скриншот окна
    Local $iH, $iW, $hDDC, $hCDC, $hBMP
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)
	_WinAPI_PrintWindow ($hWnd, $hCDC)
    ;_WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, 0, 0, 0x00330008)
    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
	Return $hBMP
EndFunc   ;==>_WinCapture


Поиск на экране (координаты получите относительно экрана):
Код:
#include "ImageSearch.au3"
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Array.au3>

_GDIPlus_Startup()

$image = _Load_img("image.bmp") ;вместо Image.bmp пишем название картинки, которую ищем
;_WinAPI_SaveHBITMAPToFile("1.bmp", $image);можно сохранить картинку и проверить все ли правильно загрузили

$img_coord = _Img_search(0, $image, 0);ищем картинку на экране, вместо 0 можно задать отклонение цветов
_ArrayDisplay($img_coord);смотрим координаты цетра найденой картинки

Func _Img_search($hBitmap, $image_for_search, $ShadeVariation) ;поиск картинки
	$x = 0
	$y = 0
	$image_for_search_clone = _WinAPI_CopyImage($image_for_search)
	$result = _ImageSearch($image_for_search_clone, 1, $x, $y, $ShadeVariation, $hBitmap) ;если вместо "1"
	;написать, то получим координаты не центра картинки, а левого верхнего угла
	_WinAPI_DeleteObject($image_for_search_clone)

	If $result == 1 Then
		Local $img_coord[2] = [$x, $y]
	Else
		Local $img_coord[2] = [-1, -1]
	EndIf
	Return $img_coord
EndFunc

Func _Load_img($img_name) ;загрузка картинки, которую ищем
	$hImage =_GDIPlus_ImageLoadFromFile(@ScriptDir & $img_name)
;ConsoleWrite($hImage)
	$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
	_GDIPlus_ImageDispose($hImage)
	Return $hBitmap
EndFunc


$image_for_search_clone = _WinAPI_CopyImage($image_for_search) - клонировать надо потому, что dll-ка затирает битмап с картикой, которую ищете, и чтоб найти ее второй раз- опять придется загрузить.
 

Вложения

  • ImageSearch.au3
    2.7 КБ · Просмотры: 109
Автор
I

Iniar

Новичок
Сообщения
9
Репутация
0
Yura [?]
Поиск в окне (координаты получите относительно левого верхнего угла окна):
Благодарю Вас. Подскажите только пожалуйста куда нужно вставить действие после находки картинки? К примеру картинка найдена и нужно туда по этим координатам переместить указатель мыши.


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

InnI [?]
А вы хоть попытались понять, что этот пример делает? Если нет, то он ищет на рабочем столе картинку из файла test.bmp, который находится в папке со скриптом.
Разобраться попробовал. Да, но я же положил файл test.bmp в папку со скриптом и запуская скрипт сворачивал папку открывая видимости рабочий стол. Но в таком случае поясните пожалуйста мне почему фрагмент не был найден на рабочем столе, хотя я его вырезал со своего раб. стола? И где в скрипте том указывается, что искать по всему рабочему столу?


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

Yura [?]
Поиск в окне (координаты получите относительно левого верхнего угла окна):
И что за окно выдаёт скрипт после запуска?
skrin.jpg
К тому же при сохранении скрина он вот так сохраняет:
2.jpg
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Iniar
Разобраться попробовал
Попробуйте ещё раз на этом примере (скрипт самостоятельно сделает картинку и найдет её)
Код:
#include <ScreenCapture.au3>
#include "BmpSearch.au3"

_GDIPlus_Startup()

; для проверки поиска сохраняем фрагмент экрана в виде картинки
; координаты: 100,100; размер: 50х50; формат: 24-разрядный bmp
_ScreenCapture_Capture(@ScriptDir & "\test.bmp", 100, 100, 150, 150, False)

; снимок экрана
$hSource = _ScreenCapture_Capture()
; загрузка картинки из файла
$hBmp = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\test.bmp")
; создание дескриптора
$hFind = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
; поиск картинки
$aCoords = _BmpSearch($hSource, $hFind, 1)

If @error Then
  ConsoleWrite("Не найдено" & @CRLF)
Else
  ConsoleWrite("X:" & $aCoords[1][2] & " Y:" & $aCoords[1][3] & @CRLF)
EndIf
 

Yura

Знающий
Сообщения
36
Репутация
7
Iniar сказал(а):
Благодарю Вас. Подскажите только пожалуйста куда нужно вставить действие после находки картинки? К примеру картинка найдена и нужно туда по этим координатам переместить указатель мыши.
См. функцию MouseMove в справке.

И что за окно выдаёт скрипт после запуска?
(-1, -1) это значит, что картинка не найдена.

К тому же при сохранении скрина он вот так сохраняет:

А не найдена, потому что ее на скриншоте нет, потому что скриншот сделан неправильно. Или вы не тот хэндл окна получаете (скорее всего), или окно свернуто было во время скрина. Скачайте Control Viewer и название окна ( пункт title) копируйте оттуда.

А перед тем как работать с окном- попробуйте второй вариант- поиск с экрана. Но тогда изображение, которое ищете, должно быть видимым и не перекрытым ничем.
 
Автор
I

Iniar

Новичок
Сообщения
9
Репутация
0
Yura [?]
А перед тем как работать с окном- попробуйте второй вариант- поиск с экрана. Но тогда изображение, которое ищете, должно быть видимым и не перекрытым ничем.
Изображение видимо, не перекрывается, ищется на экране вторым вариантом, но результат вновь -1, -1. Фрагмент без лишних белых областей расположен в папке скрипта с нужным форматом, библиотеки Ваши.


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

InnI [?]
Попробуйте ещё раз на этом примере (скрипт самостоятельно сделает картинку и найдет её)
По сути в этом примере даже менять ничего не нужно для его удачной работы, но результат его выполнения - Не найдено, хотя по логике он сам сканирует область, сохраняет и из неё же сравнивает, успех должен быть 100% если пользователь не передвинет окно во время работы в момент между скрином и сравниванием. По комментариям всё ясно, но почему отрицательный результат поиска?
 

Yura

Знающий
Сообщения
36
Репутация
7
Мистика прямо. У меня работает и мой метод, и тот, что дал InnI. Может дело в вашей винде, может картинка не так сохранена и еще 100 вариантов. Личные сообщение смотрите.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Iniar
отрицательный результат поиска
Если у вас Windows XP, то работать не будет.
Если нет - посмотрите картинку в test.bmp. Может у вас там каретка мигает или меню затухает или ещё что-то происходит.
 
Автор
I

Iniar

Новичок
Сообщения
9
Репутация
0
Yura [?]
Мистика прямо. У меня работает и мой метод, и тот, что дал InnI. Может дело в вашей винде, может картинка не так сохранена и еще 100 вариантов. Личные сообщение смотрите.
Написал Вам ответ. На самом деле мистика. Может стоит испробовать другую библиотеку?

InnI [?]
Если у вас Windows XP, то работать не будет.Если нет - посмотрите картинку в test.bmp. Может у вас там каретка мигает или меню затухает или ещё что-то происходит.
Нет, у меня Win7 Максимальная x64.
А про посмотреть, взглянул файл, визуально в нём всё хорошо. Я передвинул область поиска на место с маловероятными визуальными помехами.
 

Yura

Знающий
Сообщения
36
Репутация
7
Ответил в личку. Здесь продублирую тем, кто будет читать форум. либа, на которую я дал ссылку, для х86!
"Еще, если у вас х64, то не знаю будет работать или нет."- это я написал в первом сообщении.

Для вин х64 надо искать либу скомпилированную для х64. dll пишутся на компилируемых языках и работают в нативной среде- если ее собрали в х86, то на х64 работать не будет.

Здесь качайте для х64, .au3 тоже оттуда тогда берите:
https://www.autoitscript.com/forum/topic/148005-imagesearch-usage-explanation/

Может Inni подскажет, если добавить #AutoIt3Wrapper_UseX64=n, это поможет запустить либу для х86 на х64 или нет. Я где-то что-то такое видел, но толком не знаю.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Iniar
у меня Win7 Максимальная x64
Проверил на Win7pro x64. При запуске как х86 работает без проблем. Запуск как х64 - аварийно завершает AutoIt.

Yura
Может Inni подскажет
Не подскажет :smile: Win х64 есть, но я под ней не работаю - мне пока х86 достаточно.
 
Автор
I

Iniar

Новичок
Сообщения
9
Репутация
0
Yura [?]
Здесь качайте для х64, .au3 тоже оттуда тогда берите:
С теми библиотеками и Вашим скриптом ошибка:
Код:
"C:\ImageSearch.au3" (44) : ==> Subscript used on non-accessible variable.:
if $result[0]="0" then return 0
if $result^ ERROR
>Exit code: 1    Time: 0.4119
 

Yura

Знающий
Сообщения
36
Репутация
7
С теми библиотеками и Вашим скриптом ошибка:

Подозревал, что такое будет. Насколько помню, их ImageSearch.au3 надо еще править, там на последней версии AutoIt выбивает ошибки. Именно поэтому я сбросил свой вариант ImageSearch.au3, который я уже поправил. Но он не будет работать с теми dll, там разные параметры передаются и разные названия функций dll. Другими словами с нулевыми знаниями у вас не получится это запустить.
А я не могу, у меня нет вин х64.

http://autoit-script.ru/index.php/topic,175.0.html здесь еще может что найдете, там вроде еще один вариант лежит, но его я не пробовал.

Или Bmpsearch используйте, InnI его как-то запустил на х64.

И если вам не надо находить за несколько мс, а можно за секунду или две - без библиотек и dll можно вообще обойтись.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Iniar
при сохранении скрина он вот так сохраняет
А что это у вас за лишняя кнопка в заголовке? Какая-то программа установлена по замене тем Windows? Попробуйте отключить ВСЕ ненужные программы, включить тему Aero по умолчанию, установить масштаб в 100%. Короче, проверьте на Windows с настройками максимально близкими к "по-умолчанию".
Я вот у себя на Win7 отключил Aero (выбрал упрощённую тему) и скрипт из ответа #7 перестал находить картинку. Включил Aero снова - и всё заработало.
 
Автор
I

Iniar

Новичок
Сообщения
9
Репутация
0
InnI [?]
А что это у вас за лишняя кнопка в заголовке?
Если Вы о 4 кнопке в разделе кнопок управления окном, то она не от тем, разными изменениями визуальными я не увлекаюсь. Всё по умолчанию с момента первой установки ОС. А кнопка - это функция сворачивает в трей любое окно в виде значка. К тому же столько манипуляций снижают вероятность работы скрипта на любой другой машине. Хотелось бы альтернативный вариант который бы одинаково срабатывал на x86 и на x64 и разных системах. Пусть возможно на некоторых бы пришлось лишь заменить разрядность и библиотек для скрипта, но без лишних манипуляций.

Yura [?]
Подозревал, что такое будет. Насколько помню, их ImageSearch.au3 надо еще править, там на последней версии AutoIt выбивает ошибки.
Это я уже понял и в коде заметил разницу. Тема ещё актуальна.)
 

kopeheb

Новичок
Сообщения
17
Репутация
0
Iniar сказал(а):
Хорошо. Вот по Вашей ссылке нашёл пример, но к нему явно что-то не прикреплено до конца...
Код:
#include <ScreenCapture.au3>
#include "BmpSearch.au3"
 
_GDIPlus_Startup()

$hSource = _ScreenCapture_Capture()
$hBmp = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\test.bmp")
$hFind = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)

$aCoords = _BmpSearch($hSource, $hFind, 1)

If @error Then
  ConsoleWrite("Не найдено" & @CRLF)
Else
  ConsoleWrite("X:" & $aCoords[1][2] & " Y:" & $aCoords[1][3] & " time:" & @extended & @CRLF)
EndIf


Ошибка:
Код:
"C:\BmpSearch.au3" (46) : ==> Variable must be of type "Object".:
Local $iRowInc = ($tSizeSource.X - $tSizeFind.X) * 4
Local $iRowInc = ($tSizeSource.X - $tSizeFind^ ERROR
>Exit code: 1    Time: 0.4355
На том сайте так и не ответили по той же ошибке. Помогите пожалуйста разобраться.
Осмелился обратить внимание на найденные несовпадения...
после сравнения своего BmpSearch.au3 с ошибкой в вашем посте:
Код:
; ==> 46 строка:
	Local $iRowInc = (DllStructGetData($tSizeSource,'X') - DllStructGetData($tSizeFind,'X')) * 4


и еще риторический вопрос, у Вас скрипт в корне "C:/" находится?
 
Верх