как я могу получить координаты изображения, показанного в opencv - PullRequest
0 голосов
/ 08 января 2019

Извините, но название не имеет смысла

Я пытаюсь сделать ai, который нажимает на шар, чтобы он подпрыгнул. для контекста вот картина приложения enter image description here

в игре, когда вы нажимаете на шар, он поднимается, а затем возвращается назад, и цель игры состоит в том, чтобы поддерживать его.

я написал некоторый код, который превращает изображение в маску с помощью opencv, вот картинка с результатом

enter image description here

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

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

вот копия моего кода:

import numpy as np
from PIL import ImageGrab
import cv2
import time
import pyautogui


def draw_lines(img,lines):
    for line in lines:
        coords = line[0]
        cv2.line(img, (coords[0], coords[1]), (coords[2], coords[3]), [255,255,255], 3)

def process_img(original_image):
    processed_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
    processed_img = cv2.Canny(processed_img, threshold1=200, threshold2=300)
    vertices = np.array([[0,0],[0,800],[850,800],[850,0]
                         ], np.int32)
    processed_img = roi(processed_img, [vertices])

    # more info: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html
    #                          edges       rho   theta   thresh         # min length, max gap:        
    lines = cv2.HoughLinesP(processed_img, 1, np.pi/180, 180,      20,         15)
    draw_lines(processed_img,lines)
    return processed_img

def roi(img, vertices):
    #blank mask:
    mask = np.zeros_like(img)
    # fill the mask
    cv2.fillPoly(mask, vertices, 255)
    # now only show the area that is the mask
    masked = cv2.bitwise_and(img, mask)
    return masked
def main():
    last_time = time.time()
    while(True):
        screen =  np.array(ImageGrab.grab(bbox=(0,40, 800, 850)))
        new_screen = process_img(screen)
        print('Loop took {} seconds'.format(time.time()-last_time))
        last_time = time.time()
        cv2.imshow('window', new_screen)
        #cv2.imshow('window2', cv2.cvtColor(screen, cv2.COLOR_BGR2RGB))
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

def mouse_movement():
    ##Set to move relative to where ball is
    pyautogui.moveTo(300,400)
    pyautogui.click();
main()

Извините, если это сбивает с толку, но brain.exe перестал работать :( Спасибо

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Я работал над другим, связанным с вами вопросом, когда вы удалили его и увидели, что у вас проблемы с производительностью при поиске шара. Поскольку ваш шарик выглядит на приятном простом белом фоне (кроме партитуры и кнопки close в правом верхнем углу), существуют более простые / быстрые способы поиска мяча.

Во-первых, работайте в оттенках серого, чтобы у вас был только 1 канал вместо 3 каналов RGB для обработки - это обычно быстрее.

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

Теперь найдите самую низкую и самую высокую координату в направлении y и усредните их для центра шара, аналогично в направлении x для другого пути.

#!/usr/bin/env python3

# Load image - work in greyscale as 1/3 as many pixels
im = cv2.imread('ball.png',cv2.IMREAD_GRAYSCALE)

# Overwrite "Current Best" with white - these numbers will vary depending on what you capture
im[134:400,447:714] = 255

# Overwrite menu and "Close" button at top-right with white - these numbers will vary depending on what you capture
im[3:107,1494:1726] = 255

# Negate image so whites become black
im=255-im

# Find anything not black, i.e. the ball
nz = cv2.findNonZero(im)

# Find top, bottom, left and right edge of ball
a = nz[:,0,0].min()
b = nz[:,0,0].max()
c = nz[:,0,1].min()
d = nz[:,0,1].max()
print('a:{}, b:{}, c:{}, d:{}'.format(a,b,c,d))

# Average top and bottom edges, left and right edges, to give centre
c0 = (a+b)/2
c1 = (c+d)/2
print('Ball centre: {},{}'.format(c0,c1))

Это дает:

a:442, b:688, c:1063, d:1304
Ball centre: 565.0,1183.5

что, если я нарисую красную рамку на шоу:

enter image description here

Обработка занимает 845 микросекунд на моем Mac или меньше миллисекунды, что соответствует 1183 кадрам в секунду. Очевидно, у вас есть время, чтобы схватить экран, но я не могу это контролировать.

Обратите внимание, что вы также можете изменить размер изображения, скажем, в 4 раза (или, может быть, 8 или 16) в каждом направлении и при этом быть уверенным в нахождении шара, что может сделать его еще быстрее.

Ключевые слова : мяч, трек, трекинг, локация, поиск, положение, изображение, обработка изображений, python, OpenCV, numpy, ограничивающий прямоугольник, bbox.

0 голосов
/ 08 января 2019

Вы можете сделать это так:

1. обрезать изображение шара из скриншота или около того, что-н. как

img = cv2.imread("screenshot.jpg")
crop_img = img[y:y+h, x:x+w] # you will have to look for the parameters by trial and error

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

3. получить точку в середине получившегося прямоугольника и навести на нее мышку

Надеюсь, это поможет, если вам нужна дополнительная помощь по поводу того, как этого добиться, не стесняйтесь спрашивать

...