123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- 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_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 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
|