Chcę znaleźć obraz podrzędny z dużego obrazu przy użyciu biblioteki PIL. Chciałbym również znać współrzędne, w których się znajduje?Jak znaleźć subimage przy użyciu biblioteki PIL?
Odpowiedz
import cv2
import numpy as np
image = cv2.imread("Large.png")
template = cv2.imread("small.png")
result = cv2.matchTemplate(image,template,cv2.TM_CCOEFF_NORMED)
print np.unravel_index(result.argmax(),result.shape)
To działa prawidłowo i w sposób efektywny dla mnie.
Wygląda na to, że chcesz wykonać wykrywanie obiektów , prawdopodobnie za pomocą szablonu pasującego do. To nie jest banalny problem, chyba że szukasz dokładnego piksela po pikselu, a PIL nie jest przeznaczony do tego typu rzeczy.
Jan ma rację, że powinieneś wypróbować OpenCV. Jest to solidna biblioteka wizji komputerowej z dobrymi powiązaniami Pythona.
Oto miły krótki przykład w Pythonie, który rysuje prostokąt wokół dopasowane regionu: https://github.com/jungilhan/Tutorial/blob/master/OpenCV/templateMatching.py
Udało mi się to zrobić tylko za pomocą PIL.
Niektóre Ostrzeżenia:
- To piksel doskonały wyszukiwania. Po prostu szuka pasujących pikseli RGB.
- Dla uproszczenia usuwam kanał alfa/przezroczystość. Szukam tylko pikseli RGB.
- Ten kod ładuje całą macierz pikseli subimage do pamięci, zachowując duży rozmiar wolnego miejsca w pamięci. W moim systemie Python utrzymywał pamięć o wielkości ~ 26 MiB dla małego podobrazia 40x30, przeszukując zrzuty ekranu 1920x1200.
- Ten prosty przykład nie jest zbyt wydajny, ale zwiększenie wydajności zwiększy złożoność. Tutaj utrzymuję rzeczy proste i łatwe do zrozumienia.
- Ten przykład działa w systemach Windows i OSX. Nie testowane na Linuksie. Wykonuje zrzut ekranu głównego ekranu (w przypadku konfiguracji z wieloma monitorami).
Oto kod:
import os
from itertools import izip
from PIL import Image, ImageGrab
def iter_rows(pil_image):
"""Yield tuple of pixels for each row in the image.
From:
http://stackoverflow.com/a/1625023/1198943
:param PIL.Image.Image pil_image: Image to read from.
:return: Yields rows.
:rtype: tuple
"""
iterator = izip(*(iter(pil_image.getdata()),) * pil_image.width)
for row in iterator:
yield row
def find_subimage(large_image, subimg_path):
"""Find subimg coords in large_image. Strip transparency for simplicity.
:param PIL.Image.Image large_image: Screen shot to search through.
:param str subimg_path: Path to subimage file.
:return: X and Y coordinates of top-left corner of subimage.
:rtype: tuple
"""
# Load subimage into memory.
with Image.open(subimg_path) as rgba, rgba.convert(mode='RGB') as subimg:
si_pixels = list(subimg.getdata())
si_width = subimg.width
si_height = subimg.height
si_first_row = tuple(si_pixels[:si_width])
si_first_row_set = set(si_first_row) # To speed up the search.
si_first_pixel = si_first_row[0]
# Look for first row in large_image, then crop and compare pixel arrays.
for y_pos, row in enumerate(iter_rows(large_image)):
if si_first_row_set - set(row):
continue # Some pixels not found.
for x_pos in range(large_image.width - si_width + 1):
if row[x_pos] != si_first_pixel:
continue # Pixel does not match.
if row[x_pos:x_pos + si_width] != si_first_row:
continue # First row does not match.
box = x_pos, y_pos, x_pos + si_width, y_pos + si_height
with large_image.crop(box) as cropped:
if list(cropped.getdata()) == si_pixels:
# We found our match!
return x_pos, y_pos
def find(subimg_path):
"""Take a screenshot and find the subimage within it.
:param str subimg_path: Path to subimage file.
"""
assert os.path.isfile(subimg_path)
# Take screenshot.
with ImageGrab.grab() as rgba, rgba.convert(mode='RGB') as screenshot:
print find_subimage(screenshot, subimg_path)
Speed:
$ python -m timeit -n1 -s "from tests.screenshot import find" "find('subimg.png')"
(429, 361)
(465, 388)
(536, 426)
1 loops, best of 3: 316 msec per loop
Podczas pracy powyższego polecenia przeniosłem okno zawierające subimage przekątnej jako timeit
został uruchomiony.
Czy możesz być bardziej konkretny? W każdym razie - jeśli chcesz coś takiego jak wykrywanie twarzy i tak dalej - zapomnij o PIL (nie jest to zaprojektowane do tego rodzaju pracy) i poszukaj OpenCV. –
Czy możesz być trochę bardziej zrozumiały? podaj kilka linii kodu z tego, co już zrobiłeś, jaki format danych ma twój obraz itp. – usethedeathstar
Jeszcze nie zacząłem kodowania. Chcę subimage z dużego obrazu. na przykład mamy zrzut ekranu dowolnego gracza. mamy obraz paska wyszukiwania. teraz chcę znaleźć lokalizację seekbar przy użyciu PIL. – Sagar