Template Matching and Tracking
import os, sys
import cv2
import numpy as np
import matplotlib.pyplot as plt
Linear Regression
slope, offset = 3, 1.5
x = np.random.rand(200)*2
y = slope*x + offset + np.random.randn(200)*0.2
X = np.stack([x, np.ones_like(x)]).T
w_est, residuals, rank, singular_values = np.linalg.lstsq(X, y)
print(w_est)
# Equivalently
# w_est = np.linalg.solve(X.T @ X, X.T @ y)
slope_est, offset_est = w_est
plt.figure(figsize=(6, 10))
plt.scatter(x, y, color='k', alpha=0.2)
plt.plot(x, slope*x + offset, 'g--')
plt.plot(x, slope_est*x + offset_est, 'b-.', alpha=0.5)
Template Matching
full_image = cv2.cvtColor(cv2.imread("/work/images/Wheres_Waldo_Full.png"), cv2.COLOR_BGR2RGB)
waldo_image = cv2.cvtColor(cv2.imread("/work/images/Wheres_Waldo_Waldo.png"), cv2.COLOR_BGR2RGB)
image = full_image.astype(np.float32)/255
kernel = waldo_image.astype(np.float32)/255
fig, ax = plt.subplots(1,2,figsize=(12, 6))
ax[0].imshow(image)
ax[1].imshow(kernel)
# waldo_filter = cv2.filter2D(image, -1, kernel, borderType=cv2.BORDER_CONSTANT)
# See here: https://docs.opencv.org/3.4/de/da9/tutorial_template_matching.html
waldo_template_match = cv2.matchTemplate(image, kernel, cv2.TM_CCOEFF_NORMED)
waldo_position = np.abs(waldo_template_match)
print(f"Mean: {np.mean(waldo_position)}, Std: {np.std(waldo_position)}, [Min, Max]: [{np.min(waldo_position)}, {np.max(waldo_position)}]")
plt.figure(figsize=(20,10))
print(waldo_position.shape)
viz = np.tile(np.pad(waldo_position / np.max(waldo_position), [[20, 19], [20, 19]])[:,:,None], (1, 1, 3))
plt.imshow(0.9*viz + 0.1 * image)
y, x = np.unravel_index(waldo_position.argmax(), waldo_position.shape)
print(x, y)
plt.scatter(x+20, y+20, s=400, color='r', marker='o', facecolors='none')
Template Tracking
# From the Project 1 code
def get_num_frames(input_filename):
cap = cv2.VideoCapture(input_filename)
# try the fast way
nframes = cap.get(cv2.CAP_PROP_FRAME_COUNT)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
if not fps > 1:
# fps buggy sometimes
fps = 30.0
if nframes > 1 and width > 1 and height > 1:
# it worked
return int(nframes), int(width), int(height), fps
# the slow way
cnt = 0
while True:
ok, frame = cap.read()
if not ok or frame is None:
break
height, width = frame.shape[:2]
cnt += 1
return cnt, width, height, fps
### Code to read and write videos
input_filename = '/work/images/Rubiks_Tracking.MOV'
if not os.path.exists(input_filename):
print('error:', input_filename, 'does not exist')
sys.exit(1)
# Create the output video
path_prefix, basename = os.path.split(input_filename)
basename, _ = os.path.splitext(basename)
# Get video properties
nframes, width, height, fps = get_num_frames(input_filename)
# Create output writer
# fourcc, ext = (cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), 'mp4')
# output_filename = os.path.join(path_prefix, basename + '_captured.' + ext)
# writer = cv2.VideoWriter(output_filename, fourcc, fps, (width, height))
# Write out frames
cap = cv2.VideoCapture(input_filename)
fig, ax = plt.subplots(2, 5, figsize=(5*4, 2*6))
myframes = []
for frame_idx in range(nframes): # Get 10 frames
ok, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
if frame_idx > 85 and len(myframes) < 10:
myframes.append(frame)
if not ok or frame is None or len(myframes) >= 10:
break
for i in range(len(myframes)):
if i < 5:
ax[0, i % 5].imshow(myframes[i])
else:
ax[1, i % 5].imshow(myframes[i])
print(f"Total number of frames: {frame_idx}")
cap.release()
# Select frames
cur_frame = np.mean(myframes[0]/255.0, -1)
next_frame = np.mean(myframes[1]/255.0, -1)
# Make template
y0, x0, h, w = 750, 430, 220, 350
template = cur_frame[y0:y0+h, x0:x0+w].copy()
plt.figure(figsize=(3, 4))
plt.imshow(template)
# Draw bounding box
bbox_img = cv2.rectangle(cur_frame.copy(), (x0, y0), (x0+w, y0+h), 1, 10)
fig, ax = plt.subplots(1, 2, figsize=(2*3, 4))
ax[0].imshow(bbox_img)
ax[1].imshow(next_frame)
fig, ax = plt.subplots(1,3,figsize=(3*4,6))
ErrorI = (cur_frame[y0:y0+h, x0:x0+w] -next_frame[y0:y0+h, x0:x0+w])
Ix, Iy = cv2.Sobel(cur_frame[y0:y0+h, x0:x0+w], -1, 1, 0), cv2.Sobel(cur_frame[y0:y0+h, x0:x0+w], -1, 0, 1)
ax[0].imshow(np.abs(ErrorI))
ax[1].imshow(np.abs(Ix))
ax[2].imshow(np.abs(Iy))