2013-07-10 20 views
6

Alt resmi PIL kitaplığını kullanarak büyük görüntüden bulmak istiyorum. Ayrıca bulunduğunuz koordinatları bilmek isterim? Eğer nesne algılama gerçekleştirmek istediğiniz gibiPIL kitaplığı kullanarak subimage nasıl bulunur?

+0

Daha spesifik olabilir misiniz? Neyse - eğer yüz algılama gibi bir şey istiyorsanız - PIL (bu tür bir iş için tasarlanmamıştır) hakkında unutun ve OpenCV'yi arayın. –

+0

Biraz daha açık olabilir misiniz? Yaptığınız şeyin birkaç satırını verin, görüntünüzün hangi formatta biçimlendirildiğini vs. – usethedeathstar

+0

henüz kodlamaya başlamadım. Alt görüntüyü büyük görüntüden istiyorum. örneğin Herhangi bir oyuncunun ekran görüntüsüne sahibiz. Seekbar görüntü var. şimdi PIL kullanarak arama çubuğunun yerini bulmak istiyorum. – Sagar

cevap

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) 

Bu iyi çalışır ve benim için verimli bir şekilde.

0

Muhtemelen şablon eşleşen yoluyla çalar. Tam olarak bir piksel-piksel eşleşmesi aradığınız sürece önemsiz bir sorun değildir ve PIL bu tür bir şey yapmak anlamına gelmez.

Jan, OpenCV'yi denemeniz gerektiği doğru. İyi Python bağlamaları olan sağlam bir bilgisayar görme kitaplığı.

İşte eşleşti bölgenin etrafında bir dikdörtgen çizer Python güzel bir kısa örnek: https://github.com/jungilhan/Tutorial/blob/master/OpenCV/templateMatching.py

2

Bunu yalnızca PIL kullanarak yapmayı başardım.

Bazı uyarılar:

  1. Bu piksel mükemmel aramasıdır. Sadece eşleşen RGB pikselleri arar.
  2. Basitlik için alfa/saydamlık kanalını kaldırırım. Ben sadece RGB pikselleri arıyorum.
  3. Bu kod, büyük resmi bellekte tutuyorken tüm alt piksel piksel dizisini belleğe yükler. Benim sistemimde Python, 1920x1200 ekran görüntüsü aracılığıyla yapılan 40x30 minik bir küçümseme için ~ 26 MiB bellek ayak izi tuttu.
  4. Bu basit örnek çok verimli değil, ancak verimliliği artırmak karmaşıklığı artıracaktır. Burada işleri düz ve ileride kolay anlıyorum.
  5. Bu örnek, Windows ve OSX'te çalışır. Linux'ta test edilmedi. Sadece birincil ekranın ekran görüntüsünü alır (çoklu monitör ayarları için).

İşte 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) 

Hız:

$ 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 

Ben timeit koşuyordu olarak çapraz alt imge içeren pencereyi taşındı yukarıdaki komutu çalışırken.