2013-07-10 10 views
6

Desidero trovare l'immagine secondaria da un'immagine grande utilizzando la libreria PIL. Voglio anche conoscere le coordinate in cui è stato trovato?Come trovare un'immagine secondaria usando la libreria PIL?

+0

Puoi essere più specifico? Ad ogni modo - se vuoi qualcosa come Face Detection e così via - dimentica PIL (non è progettato per questo tipo di lavoro) e cerca OpenCV. –

+0

Puoi essere un po 'più chiaro? fornisci alcune righe di codice di ciò che hai già fatto, quale formato di dati ha l'immagine ecc. – usethedeathstar

+0

Non ho ancora iniziato a scrivere il codice. Voglio l'immagine secondaria dalla grande immagine. per es. abbiamo screenshot di qualsiasi giocatore. abbiamo un'immagine della barra di ricerca. ora voglio trovare la posizione della barra di ricerca usando PIL. – Sagar

risposta

5
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) 

Questo funziona bene e in maniera efficiente per me.

0

Sembra che si desideri eseguire il rilevamento dell'oggetto , probabilmente tramite il modello corrispondente a. Non è un problema banale a meno che tu non stia cercando una corrispondenza esatta pixel per pixel, e PIL non è pensato per fare questo genere di cose.

Jan ha ragione che dovresti provare OpenCV. È una robusta libreria per la visione artificiale con buoni collegamenti Python.

Ecco un bel breve esempio in Python che disegna un rettangolo intorno alla regione trovati: https://github.com/jungilhan/Tutorial/blob/master/OpenCV/templateMatching.py

2

Sono riuscito a farlo solo utilizzando PIL.

Alcuni avvertimenti:

  1. Questo è un pixel di ricerca perfetto. Cerca semplicemente i pixel RGB corrispondenti.
  2. Per semplicità rimuovo il canale alfa/trasparenza. Sto solo cercando i pixel RGB.
  3. Questo codice carica l'intera matrice di pixel di dimensioni secondarie in memoria, mantenendo l'immagine grande fuori dalla memoria. Nel mio sistema, Python ha mantenuto un footprint di memoria di ~ 26 MiB per una minuscola sub-immagine 40x30 che ricerca attraverso uno screenshot 1920x1200.
  4. Questo semplice esempio non è molto efficiente, ma aumentare l'efficienza aggiungerà complessità. Qui sto mantenendo le cose semplici e facili da capire.
  5. Questo esempio funziona su Windows e OSX. Non testato su Linux. Serve solo uno screenshot del display principale (per configurazioni multi monitor).

Ecco il codice:

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) 

Velocità:

$ 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 

Durante l'esecuzione del comando precedente ho spostato la finestra che contiene l'immagine di dettaglio in diagonale come timeit era in esecuzione.

Problemi correlati