Майним крипто-коины с помощью Python и компьютерного зрения

от автора

После внезапного обогащения энтузиастов, которые поиграли в начале года в приложение Notcoin в телеграм, подобные проекты стали расти как грибы. Да и грибников заметно поприбавилось. Но в данной статье мы не будем касаться тем блокчейна или финансов, а рассмотрим простой пример применения компьютерного зрения для фарма поинтов в самом популярном, после Notcoin, проекте — хомяке комбате. Название явно на что-то намекает, но да ладно.

Это не первый проект, который я автоматизирую, и не самый нуждающийся в этом. Да и без компьютерного зрения с автоматизацией хомяка можно спокойно обойтись. Но с ним, во-первых, интереснее, а во-вторых — это просто хороший пример с минимумом строк кода для демонстрации возможностей библиотеки cv2. Статья, соответственно, предназначена для энтузиастов и начинающих специалистов.

Начнем с того, что мы установим все необходимые зависимости и импортируем их в свой проект. Вот они, слева направо.

import pyautogui import keyboard import cv2 import numpy as np import time

С помощью pyautogui наш бот будет управлять мышью. Keyboard пригодится для назначения горячих клавиш, чтобы управлять работой бота. cv2 наградит бота зрением, пусть и компьютерным, с помощью которого тот будет находить совпадения с искомым изображением. А numpy пригодится для работы с большими массивами, но тут он почти для галочки, не бойтесь. Модуль time тоже понадобится, чтобы ставить таймауты в работе программы.

Далее напишем небольшую конструкцию- переключатель.

def change():     global work     work = not work  work = False

Функция change при вызове всего лишь меняет значение переменной work, которая будет использована в бесконечном цикле. И если work будет False, работа нашего кода будет останавливаться. И наоборот запускаться, в противоположном случае.

Кстати, забыл упомянуть, что разработчики проекта, над которым мы сейчас проводим эксперимент, большие молодцы, и убрали возможность пользоваться приложением на десктопных устройствах. Поэтому для его запуска понадобится эмулятор Android.

Теперь определим основную логику работы бота:

  1. Он ищет совпадение с изображением полностью заполненной энергии.

  2. Если находит совпадение, ищет изображение монеты и кликает на неё энное количество раз.

  3. И всё это работает в бесконечном цикле.

Значит со скриншота приложения необходимо вырезать две области, которые помечены красным, и разместить их в отдельные файлы, конечно же.

Теперь напишем функцию для кликов по монетке. Она будет принимать путь к исходному изображению, а так же порог чувствительности для компьютерного зрения и интервал (таймаут) в секундах.

def click(template_path, threshold=0.8, interval=0.0001):      template = cv2.imread(template_path, 0)     w, h = template.shape[::-1]      screenshot = pyautogui.screenshot()     screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)      # Переводим скриншот в оттенки серого.     gray_screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)      # Находим изображение на экране.     result = cv2.matchTemplate(gray_screenshot, template, cv2.TM_CCOEFF_NORMED)     loc = np.where(result >= threshold)      # Кликаем по найденным координатам.     for pt in zip(*loc[::-1]):         center_x = pt[0] + w // 2         center_y = pt[1] + h // 2         for _ in range(260):             pyautogui.doubleClick(center_x, center_y)         break

Переменной template будет присвоено исходное изображение монетки, но в оттенках серого, так как мы указали в параметрах 0. Это необходимость, так как в оттенках серого компьютер зрит лучше. Сразу вычисляем высоту и ширину исходника, и присваиваем переменным. А далее по ходу исполнения кода он делает скриншот, сравнивает с исходником, получает координаты области с совпадением, и делает 260 даблкликов по ней. Координаты я ищу немного кривовато и в итоге loc содержит большой массив, из которого я использую лишь самые первые координаты, после чего цикл прерываю. Но лучше сделать не смог, извините.

А теперь напишем аналогичную функцию, но с задачей искать совпадение с картинкой полной энергии, после чего вызывать функцию click.

def find(template_path, threshold=0.9, interval=1):     keyboard.add_hotkey('`', change)      # Загружаем изображение, которое мы хотим найти на экране. 0- в градациях серого.     template = cv2.imread(template_path, 0)     w, h = template.shape[::-1]      try:         while True:             if work:                  # Получаем скриншот экрана.                 screenshot = pyautogui.screenshot()                 screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)                  # Переводим скриншот в оттенки серого.                 gray_screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)                  # Находим изображение на экране.                 result = cv2.matchTemplate(gray_screenshot, template, cv2.TM_CCOEFF_NORMED)                 loc = np.where(result >= threshold)                  for _ in zip(*loc[::-1]):                     click('coin.bmp')                     break                 time.sleep(interval)          except KeyboardInterrupt:         print('\nВыход из программы')

В целом всё аналогично. Добавил лишь ожидание горячей клавиши, чтобы можно было остановить программу в любое время нажатием на тильду (Ё). Ну и для красоты заключил в try-except.

И это всё. Пишем последние строки и запускаем скрипт (не забыв нажать на Ё для запуска логики в цикле).

if __name__ == "__main__":     find('energy.bmp')

По сути, этот код многофункционален, и его без труда, с минимальными изменениями, можно переделать под любые другие задачи. На всякий случай оставлю и полную версию кода:

import pyautogui import keyboard import cv2 import numpy as np import time   def change():     global work     work = not work  work = False  def find(template_path, threshold=0.9, interval=1):     keyboard.add_hotkey('`', change)      # Загружаем изображение, которое мы хотим найти на экране. 0- в градациях серого.     template = cv2.imread(template_path, 0)     w, h = template.shape[::-1]      try:         while True:             if work:                  # Получаем скриншот экрана.                 screenshot = pyautogui.screenshot()                 screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)                  # Переводим скриншот в оттенки серого.                 gray_screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)                  # Находим изображение на экране.                 result = cv2.matchTemplate(gray_screenshot, template, cv2.TM_CCOEFF_NORMED)                 loc = np.where(result >= threshold)                  for _ in zip(*loc[::-1]):                     click('coin.bmp')                     break                 time.sleep(interval)          except KeyboardInterrupt:         print('\nВыход из программы')   def click(template_path, threshold=0.8, interval=0.0001):      template = cv2.imread(template_path, 0)     w, h = template.shape[::-1]      screenshot = pyautogui.screenshot()     screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)      # Переводим скриншот в оттенки серого.     gray_screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)      # Находим изображение на экране.     result = cv2.matchTemplate(gray_screenshot, template, cv2.TM_CCOEFF_NORMED)     loc = np.where(result >= threshold)      # Кликаем по найденным координатам.     for pt in zip(*loc[::-1]):         center_x = pt[0] + w // 2         center_y = pt[1] + h // 2         for _ in range(260):             pyautogui.doubleClick(center_x, center_y)         break   if __name__ == "__main__":     find('energy.bmp')

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


ссылка на оригинал статьи https://habr.com/ru/articles/819087/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *