In [270]:
%matplotlib inline

import cv2
from cv2 import cv
import matplotlib.pyplot as plt
import numpy as np

from IPython.display import display, Image as PImage

from PIL import Image

from glob import glob
In [271]:
baseurl = "/Users/mga/Desktop/hack4fi/data/"
In [272]:
# taken from https://www.flickr.com/photos/slsarkiva/sets/72157644581542379
images = ["14150358928_e39ffe62d3_k.jpg",
    "14150359478_e9068c1bb0_k.jpg",
    "14150363748_15fc880fb5_k.jpg",
    "14150365358_0d4304a05c_k.jpg",
    "14150366448_ed7cd1d1a5_k.jpg",
    "14150368099_ca896719a3_k.jpg",
    "14150372658_62154f677c_k.jpg",
    "14150404490_8016758b1d_k.jpg",
    "14150405960_634206b2c9_k.jpg",
    "14150409510_a2d2513979_k.jpg",
    "14150410510_dd2bc28e30_k.jpg",
    "14150413850_501e87ab29_k.jpg",
    "14150414830_e7c2c6463e_k.jpg",
    "14150415010_4c9146f594_k.jpg",
    "14150415200_fd012b4bd3_k.jpg",
    "14150422810_8d1a564542_k.jpg",
    "14150533077_1ebed0b0d8_k.jpg",
    "14150534587_7fa21f1972_k.jpg",
    "14150534687_7fef87be81_k.jpg",
    "14150543547_f0c646a735_k.jpg",
    "14313883716_f7bdb887a1_k.jpg",
    "14313897186_df9708311a_k.jpg",
    "14333682191_cb8b168932_k.jpg",
    "14333684581_2f3ad497c5_k.jpg",
    "14333690961_6cab5abac9_k.jpg",
    "14335350162_02cd300895_k.jpg",
    "14335350662_418a4c9225_k.jpg",
    "14335351072_6f8cc1c1d0_k.jpg",
    "14335352842_735111fb12_k.jpg",
    "14336267914_f8833a689e_k.jpg",
    "14336270814_891ae0aa15_k.jpg",
    "14337016445_923bc0abf9_k.jpg",
    "14337022265_0e99ee4713_k.jpg",
    "14337026705_ab2ac044f5_k.jpg",
    "14337029665_e565809e94_k.jpg",
    "14357219413_dfc0310475_k.jpg",
    "14357220853_7576446bde_k.jpg",
    "14357228353_55c6bc0ff8_k.jpg"]
In [275]:
def find_image(from_file, to_file):
    waldo_img = cv2.imread(from_file)
    scene_img = cv2.imread(to_file)
    return best_match(waldo_img, scene_img, 60, 100)
In [276]:
# taken wholesale from http://nbviewer.ipython.org/gist/aschn/5861365
def best_match(template_img, scene_img, minsize, maxsize):
    """ Get the best match for a template image within a scene image,
        rescaling the template width between minsize and maxsize
        while maintaining the aspect ratio.
        Returns two 2-tuples of ints:
            corner is the (x,y) position of the upper-left corner of the template in the scene
            wh is (width, height)
    """
    # widths is all the widths to try
    widths = np.arange(minsize, maxsize, dtype=int)
    # aspect_ratio is height/width of the template image
    aspect_ratio = template_img.shape[0] / float(template_img.shape[1])
    # heights is all the heights to try
    heights = np.asarray(aspect_ratio*widths, dtype=int)
    
    # best_scores will store the best score for each width
    best_scores = np.zeros(len(widths))
    # best_positions will store the best (x,y) positions of the template for each width
    best_positions = np.zeros([len(widths), 2], dtype=int)
    
    # scan widths
    for isize in range(widths.size):
        # log
#         print "resizing to width = %d" % widths[isize]
        
        # resize
        resized_template_img = cv2.resize(template_img, (widths[isize], heights[isize]))
        
        # match
        scores = cv2.matchTemplate(scene_img, resized_template_img, method=cv2.TM_CCORR_NORMED)
        
        # get best score and position
        min_score, max_score, (min_x, min_y), (max_x, max_y) = cv2.minMaxLoc(scores)
        
        # store best score and position
        best_scores[isize] = max_score
        best_positions[isize] = [max_x, max_y]
        
    # choose best overall match
    best_isize = np.argmax(best_scores)
    best_width = widths[best_isize]
    best_position = best_positions[best_isize]
    
    # plot scores
    plt.plot(widths, best_scores)
    plt.arrow(widths[best_isize], 0, 0, 1, color='r')
    plt.xlabel('template width')
    plt.ylabel('score')
    
    # return
    return tuple(best_positions[best_isize]), (widths[best_isize], heights[best_isize])

def imshow_highlighted(img, corner, wh, rgb=(255,0,0), stroke=5):
    """ Show an image with a highlighted rectangle.
        corner is a (x_upperleft, y_upperleft) tuple of ints,
        wh is a (width, height) tuple of ints,
        rgb is an optional (r,g,b) tuple (default green),
        stroke is an optional number of pixels for rectangle stroke (default 5).
    """

    # copy the image so we don't modify the original
    img_highlighted = img[:,:,[2,1,0]].copy()
    
    # add a rectangle
    cv2.rectangle(img_highlighted, corner, (corner[0]+wh[0], corner[1]+wh[1]), rgb, stroke)
    
    # show
    plt.imshow(img_highlighted)
In [279]:
corners = []
whs = []
waldos = []
scenes = []
for i, image in enumerate(images):
    waldo = images[i]
    if (i+1 < len(images)):
        scene = images[i+1]
    else:
        scene = images[0]
    corner, wh = find_image(baseurl+waldo, baseurl+scene)
    corners.append(corner)
    whs.append(wh)
    waldos.append(waldo)
    scenes.append(scene)
In [280]:
scene_img = cv2.imread(baseurl + images[0])
plt.figure()
plt.imshow(scene_img)
for i,scene in enumerate(scenes):
    scene_img = cv2.imread(baseurl + scenes[i])
    plt.figure()
    imshow_highlighted(scene_img, corners[i], whs[i])
/Library/Python/2.7/site-packages/matplotlib-override/matplotlib/pyplot.py:412: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_num_figures`).
  max_open_warning, RuntimeWarning)