Spaces:
Running
Running
import math | |
import numpy as np | |
def downsample(img, factor): | |
""" | |
Downsample an image along both dimensions by some factor | |
""" | |
assert img.shape[0] % factor == 0 | |
assert img.shape[1] % factor == 0 | |
img = img.reshape([img.shape[0]//factor, factor, img.shape[1]//factor, factor, 3]) | |
img = img.mean(axis=3) | |
img = img.mean(axis=1) | |
return img | |
def fill_coords(img, fn, color): | |
""" | |
Fill pixels of an image with coordinates matching a filter function | |
""" | |
for y in range(img.shape[0]): | |
for x in range(img.shape[1]): | |
yf = (y + 0.5) / img.shape[0] | |
xf = (x + 0.5) / img.shape[1] | |
if fn(xf, yf): | |
img[y, x] = color | |
return img | |
def rotate_fn(fin, cx, cy, theta): | |
def fout(x, y): | |
x = x - cx | |
y = y - cy | |
x2 = cx + x * math.cos(-theta) - y * math.sin(-theta) | |
y2 = cy + y * math.cos(-theta) + x * math.sin(-theta) | |
return fin(x2, y2) | |
return fout | |
def point_in_line(x0, y0, x1, y1, r): | |
p0 = np.array([x0, y0]) | |
p1 = np.array([x1, y1]) | |
dir = p1 - p0 | |
dist = np.linalg.norm(dir) | |
dir = dir / dist | |
xmin = min(x0, x1) - r | |
xmax = max(x0, x1) + r | |
ymin = min(y0, y1) - r | |
ymax = max(y0, y1) + r | |
def fn(x, y): | |
# Fast, early escape test | |
if x < xmin or x > xmax or y < ymin or y > ymax: | |
return False | |
q = np.array([x, y]) | |
pq = q - p0 | |
# Closest point on line | |
a = np.dot(pq, dir) | |
a = np.clip(a, 0, dist) | |
p = p0 + a * dir | |
dist_to_line = np.linalg.norm(q - p) | |
return dist_to_line <= r | |
return fn | |
def point_in_circle(cx, cy, r): | |
def fn(x, y): | |
return (x-cx)*(x-cx) + (y-cy)*(y-cy) <= r * r | |
return fn | |
def point_in_circle_clip(cx, cy, r, theta_start=0, theta_end=-np.pi): | |
def fn(x, y): | |
if (x-cx)*(x-cx) + (y-cy)*(y-cy) <= r * r: | |
if theta_start < 0: | |
return theta_start > np.arctan2(y-cy, x-cx) > theta_end | |
else: | |
return theta_start < np.arctan2(y - cy, x - cx) < theta_end | |
return fn | |
def point_in_rect(xmin, xmax, ymin, ymax): | |
def fn(x, y): | |
return x >= xmin and x <= xmax and y >= ymin and y <= ymax | |
return fn | |
def point_in_triangle(a, b, c): | |
a = np.array(a) | |
b = np.array(b) | |
c = np.array(c) | |
def fn(x, y): | |
v0 = c - a | |
v1 = b - a | |
v2 = np.array((x, y)) - a | |
# Compute dot products | |
dot00 = np.dot(v0, v0) | |
dot01 = np.dot(v0, v1) | |
dot02 = np.dot(v0, v2) | |
dot11 = np.dot(v1, v1) | |
dot12 = np.dot(v1, v2) | |
# Compute barycentric coordinates | |
inv_denom = 1 / (dot00 * dot11 - dot01 * dot01) | |
u = (dot11 * dot02 - dot01 * dot12) * inv_denom | |
v = (dot00 * dot12 - dot01 * dot02) * inv_denom | |
# Check if point is in triangle | |
return (u >= 0) and (v >= 0) and (u + v) < 1 | |
return fn | |
def point_in_quadrangle(a, b, c, d): | |
fn1 = point_in_triangle(a, b, c) | |
fn2 = point_in_triangle(b, c, d) | |
fn = lambda x, y: fn1(x, y) or fn2(x, y) | |
return fn | |
def highlight_img(img, color=(255, 255, 255), alpha=0.30): | |
""" | |
Add highlighting to an image | |
""" | |
blend_img = img + alpha * (np.array(color, dtype=np.uint8) - img) | |
blend_img = blend_img.clip(0, 255).astype(np.uint8) | |
img[:, :, :] = blend_img | |