C# поиск по картинке с кликом и без, в выбранной области

Регистрация
19.10.2018
Сообщения
205
Благодарностей
65
Баллы
28
Всем добрейшего времени суток!
Первый раз участвую в конкурсе. Высвободилось немного времени и решил поделиться небольшой наработкой. На форуме не встречал данной информации.

Стандартный кубик поиск по картинке, не предполагает поиск изображения без клика (чтобы проверить имеется ли изображение на экране).
Поиск без клика может быть полезен для выстраивания логики, в тех случаях где клик перебросит вас на новую страницу, а вам нужно остаться на текущей.
Также это может быть полезно при работе с Canvas (сайты, которые полностью состоят из картинки), где нет возможности обращаться к элементам страницы.
Еще это решение ищет изображение не на всем экране, а в заданной области (что, как я думаю, снижает нагрузку, нежели при поиске по всему экрану).

Собственно решение универсальное и вы сможете его применить в множестве своих проектов, где вам это понадобится.

1. Сохраняем общее изображение сайта (допустим в 1.png)

138482


2. Открываем в редакторе Paint. В левом нижнем углу можно увидеть координаты по х и у, что очень удобно. Сразу записываем себе координаты элемента, который будем искать.
В моем случае это X от 225 до 325 и Y от 125 до 155.

3. Выделяем нужное изображение, обрезаем и сохраняем.
138483
138485


4. Теперь настраиваем сам кубик. Нам нужны первые 4 строчки.
В первой строке указываем имя картинки, которую будем искать.
Во второй координаты. С координатами есть ньюанс.
Первая координата начало поиска по оси X, вторая по оси Y, третья это конец поиска по оси X и четвертая по оси Y.
Исходя из моих координат мне нужно искать изображение по X от 225 до 325 т.е первую координату я ставлю 225, а третью 100 т.к 225+100=325.
Аналогично с осью Y. Вторую координату ставлю 125 и четвертую 30 т.к 125+30=155. Надеюсь пример понятен.
Координаты в тоге: 225, 125, 100, 30.
Третья строка это булевая переменная true или false. Устанавливаем true, если нужен клик и false если не нужен.
Четвертая строка процент совпадения изображения в %. Можно играться от 95 до 99%.

Если изображение будет не найдено, кубик выйдет по красной ветке.
В самом кубике еще есть комментарии. Если вам будет интересно прочтите и их, кубик совсем небольшой.

Код кубика:
C#:
string file = project.Directory + @"\capmonster.png"; // Путь к изображению в папке проекта
int[] coords = new int[] { 225, 125, 100, 30 }; // Область поиска (от x, y до x+, y+)
bool click = true; // Если нужен клик true, иначе false
int similarity = 99; // совпадение от 95 до 99%

Tab tab = instance.ActiveTab;
if (tab.IsBusy) tab.WaitDownloading();

string image = Convert.ToBase64String(System.IO.File.ReadAllBytes(file));

System.Drawing.Rectangle searchRect = new System.Drawing.Rectangle(coords[0], coords[1], coords[2], coords[3]);
System.Drawing.Rectangle[] searchAreas = new System.Drawing.Rectangle[] { searchRect };

string rectStr = tab.FindImage(image, searchAreas, similarity);

if (!string.IsNullOrEmpty(rectStr)){
    string[] parts = rectStr.Split(',');
    if (parts.Length == 4){
        int left   = Convert.ToInt32(parts[0].Trim());
        int top    = Convert.ToInt32(parts[1].Trim());
        int width  = Convert.ToInt32(parts[2].Trim());
        int height = Convert.ToInt32(parts[3].Trim());
      
        // тут можно добавить если нужно например кликнуть правее на 100px то добавляем к clickX + 100
        // по аналогии и с clickY
        int clickX = left + width / 2;
        int clickY = top + height / 2; //

        // если координаты невалидные — кидаем ошибку
        if (clickX == 0 && clickY == 0){ // в некоторых случаях можно попробовать вместо && поставить ||
            throw new Exception("Изображение не найдено.");
        }

        System.Drawing.Rectangle clickPoint = new System.Drawing.Rectangle(
            clickX,
            clickY,
            1, 1
        );
      
        if(click){
            tab.RiseEvent("click", clickPoint, "Left");
            project.SendInfoToLog("Клик по " + file + " Координаты: " + clickPoint, true);
        }
        else{
            project.SendInfoToLog("Найден " + file + " Координаты: " + clickPoint, true);
        }
      
        return 0; // Успех
    }
    else{
        throw new Exception("Некорректный формат координат: " + rectStr);
    }
}
else{
    throw new Exception("Изображение "+ file +" не найдено в указанной области.");
}
Вариант 2

Если вы не хотите каждый раз из кубика дергать изображение с диска и конвертировать его в base64, то можно сделать один раз в начале проекта кубик C# с кодом конвертации изображений. Сложить значения в переменные использовав массив и уже из переменных брать код base64.

C#:
string[] imageNames = { "back", "claim", "close_banner", "confirm"}; //название картинок, точно такие же переменные нужно создать в проекте

foreach (var name in imageNames)
{
    string file = project.Directory + @"\img\" + name + ".png"; // путь и расширение файла
    project.Variables[name].Value = Convert.ToBase64String(System.IO.File.ReadAllBytes(file));
}
Кубик поиска изображения изменится на такой в этом случае:
C#:
string img = "claim"; // вписываем название переменной из которой нужно взять base64
int[] coords = new int[] { 580, 510, 120, 50 }; // Область поиска (от x, y до x+, y+)
bool click = true; // Если нужен клик true, иначе false
int similarity = 99; // совпадение от 95 до 99%

Tab tab = instance.ActiveTab;
if (tab.IsBusy) tab.WaitDownloading();

string image = project.Variables[img].Value;
System.Drawing.Rectangle searchRect = new System.Drawing.Rectangle(coords[0], coords[1], coords[2], coords[3]);
System.Drawing.Rectangle[] searchAreas = new System.Drawing.Rectangle[] { searchRect };

string rectStr = tab.FindImage(image, searchAreas, similarity);

if (!string.IsNullOrEmpty(rectStr))
{
    string[] parts = rectStr.Split(',');
    if (parts.Length == 4)
    {
        int left   = Convert.ToInt32(parts[0].Trim());
        int top    = Convert.ToInt32(parts[1].Trim());
        int width  = Convert.ToInt32(parts[2].Trim());
        int height = Convert.ToInt32(parts[3].Trim());

        int clickX = left + width / 2;
        int clickY = top + height / 2;

        // если координаты невалидные — кидаем ошибку
        if (clickX == 0 && clickY == 0){
            throw new Exception("Изображение не найдено.");
        }

        System.Drawing.Rectangle clickPoint = new System.Drawing.Rectangle(
            clickX,
            clickY,
            1, 1
        );
       
        if(click){
            tab.RiseEvent("click", clickPoint, "Left");
            project.SendInfoToLog("Клик по " + img + "Координаты: " + clickPoint, true);
        }
        else{
            project.SendInfoToLog("Найден " + img + "Координаты: " + clickPoint, true);
        }
       
        return 0; // Успех
    }
    else
    {
        throw new Exception("Некорректный формат координат: " + rectStr);
    }
}
else
{
    throw new Exception("Изображение "+ img +" не найдено в указанной области.");
}

В архиве прикрепил шаблон с кубиком и скриншот с обрезанной картинкой.

Всем спасибо за прочтение! Желаю вам успехов в ваших проектах! Зенка крутится - лавешка мутится!
 

Вложения

Последнее редактирование:

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)