Numpyで画像に図形描画してみます。
まず、使用する画像を読み込んでおきます。
import numpy as np
import matplotlib.pyplot as plt
original_image = plt.imread(image_name)
if np.issubdtype(original_image.dtype, np.integer):
original_image = original_image / np.iinfo(original_image.dtype).max
plt.imshow(original_image)
円
塗りつぶしの円です。
def fill_circle(image, color, center, radius):
coord = np.fromfunction(lambda y, x: np.dstack((y + 0.5, x + 0.5)), image.shape[:2])
dist2 = (coord[:,:,1] - center[0]) ** 2 + (coord[:,:,0] - center[1]) ** 2
condition = dist2 <= radius ** 2
if image.ndim == 3:
condition = np.tile(condition.reshape(condition.shape + (1,)), (1, 1, image.shape[2]))
return np.where(condition, color, image)
fill_circle_image = fill_circle(original_image, np.array([1.0, 0.0, 1.0]), (80, 120), 40)
plt.imshow(fill_circle_image)
線の円です。
def stroke_circle(image, color, weight, center, radius):
coord = np.fromfunction(lambda y, x: np.dstack((y + 0.5, x + 0.5)), image.shape[:2])
dist2 = (coord[:,:,1] - center[0]) ** 2 + (coord[:,:,0] - center[1]) ** 2
condition = abs(np.sqrt(dist2) - radius) - weight * 0.5 <= 0
if image.ndim == 3:
condition = np.tile(condition.reshape(condition.shape + (1,)), (1, 1, image.shape[2]))
return np.where(condition, color, image)
stroke_circle_image = stroke_circle(original_image, np.array([1.0, 0.0, 1.0]), 3.0, (80, 120), 40)
plt.imshow(stroke_circle_image)
四角形
塗りつぶしの四角形です。
def fill_rectangle(image, color, center, size):
coord = np.fromfunction(lambda y, x: np.dstack((y + 0.5, x + 0.5)), image.shape[:2])
dist = np.dstack((abs(coord[:,:,1] - center[0]) - size[0] / 2, abs(coord[:,:,0] - center[1]) - size[1] / 2)).max(axis=2)
condition = dist <= 0
if image.ndim == 3:
condition = np.tile(condition.reshape(condition.shape + (1,)), (1, 1, image.shape[2]))
return np.where(condition, color, image)
fill_rectangle_image = fill_rectangle(original_image, np.array([1.0, 0.0, 1.0]), (80, 120), (120, 80))
plt.imshow(fill_rectangle_image)
線の四角形です。
def stroke_rectangle(image, color, weight, center, size):
coord = np.fromfunction(lambda y, x: np.dstack((y + 0.5, x + 0.5)), image.shape[:2])
dist = np.dstack((abs(coord[:,:,1] - center[0]) - size[0] / 2, abs(coord[:,:,0] - center[1]) - size[1] / 2)).max(axis=2)
condition = abs(dist) - weight * 0.5 <= 0
if image.ndim == 3:
condition = np.tile(condition.reshape(condition.shape + (1,)), (1, 1, image.shape[2]))
return np.where(condition, color, image)
stroke_rectangle_image = stroke_rectangle(original_image, np.array([1.0, 0.0, 1.0]), 3.0, (80, 120), (120, 80))
plt.imshow(stroke_rectangle_image)
直線
二点間を結ぶ直線です。
def line(image, color, weight, point1, point2):
coord = np.fromfunction(lambda y, x: np.dstack((y + 0.5, x + 0.5)), image.shape[:2])
p12 = np.array([point2[1] - point1[1], point2[0] - point1[0]])
p12_norm = np.linalg.norm(p12)
p12_dir = p12 / p12_norm
p1c = np.dstack(([coord[:,:,0] - point1[1], coord[:,:,1] - point1[0]]))
dot = np.einsum('ijk,k->ij', p1c, p12_dir)
dist = np.sqrt(p1c[:,:,0] ** 2 + p1c[:,:,1] ** 2 - dot ** 2)
condition = (dot >= 0) & (dot <= p12_norm) & (dist <= weight * 0.5)
if image.ndim == 3:
condition = np.tile(condition.reshape(condition.shape + (1,)), (1, 1, image.shape[2]))
return np.where(condition, color, image)
line_image = line(original_image, np.array([1.0, 0.0, 1.0]), 3.0, (30, 40), (200, 150))
plt.imshow(line_image)
実装したコードはGoogle Colaboratoryに置いてあります。