画像処理100本ノックに最近取り組み始めたので実装例を一部。今回はQ1-10の中からいくつかピックアップしました。
Q6 減色処理
処理の式は以下
val = \left\{
\begin{array}{ll}
32 & (0 \leq x < 64) \\
96 & (64 \leq x < 128) \\
96 & (128 \leq x < 192) \\
96 & (192 \leq x < 256) \\
\end{array}
\right.
def reduce(pix):
if 0 <= pix < 64:
return 32
elif 64 <= pix < 128:
return 96
elif 128 <= pix <192:
return 160
else:
return 224
def reduce_color(img):
return np.vectorize(reduce)(img)
Q7 Average Pooling
def average_pool(img, f=8):
height, width, channel = img.shape
n = int(width/f)
out = np.empty(shape=(n, n, channel))
print(out.shape)
for h in range(n):
for w in range(n):
for c in range(channel):
vert_start = h * f
vert_end = vert_start + f
horiz_start = w * f
horiz_end = horiz_start + f
val = np.sum(img[vert_start:vert_end, horiz_start:horiz_end, c]) / f**2
out[h, w, c] = val
return out.astype(np.int32)
Q8: Max Pooling
def max_pool(img, f=8):
height, width, channel = img.shape
n = int(width/f)
out = np.empty(shape=(n, n, channel))
print(out.shape)
for h in range(n):
for w in range(n):
for c in range(channel):
vert_start = h * f
vert_end = vert_start + f
horiz_start = w * f
horiz_end = horiz_start + f
val = np.max(img[vert_start:vert_end, horiz_start:horiz_end, c])
out[h, w, c] = val
return out.astype(np.int32)
Q9 ガウシアンフィルタ
やることは単純と思っいたら意外に添字のミスでてこずってしまった。。。カーネルの実装は解答例を参考にしました。
def gaussian_filter(img, size=3, sigma=1.3):
height, width, channel = img.shape
# padding
pad = size//2
img_pad = img.copy()
img_pad = np.pad(img_pad, [(pad, pad), (pad, pad), (0, 0)], 'constant', constant_values=(0,0))
# PREPARE KERNEL
K = np.zeros(shape=(size, size), dtype=np.float32)
for x in range(-pad, -pad+size):
for y in range(-pad, -pad+size):
K[y+pad, x+pad] = (1/((2 * np.pi * sigma * sigma)) * np.exp(-(x**2+y**2) / (2*(sigma**2))))
K /= K.sum()
tmp = img_pad.copy()
for h in range(height):
for w in range(width):
for c in range(channel):
tmp[h+pad, w+pad, c] = np.sum(K*img_pad[h:h+size, w:w+size, c])
tmp = tmp[pad:pad+height, pad:pad+width, :].astype(np.int32)
return tmp
Q10 メディアンフィルタ
def median_filter(img, size=3):
height, width, channel = img.shape
out = img.copy()
# padding
pad = size//2
out = img.copy()
out = np.pad(out, [(pad, pad), (pad, pad), (0, 0)], 'constant', constant_values=(0,0))
assert out.shape == (img.shape[0]+2*pad, img.shape[1]+2*pad, img.shape[2])
# Apply filter
tmp = out.copy()
for h in range(height):
for w in range(width):
for c in range(channel):
out[h+pad, w+pad, c] = np.median(tmp[h:h+size, w:w+size, c])
out = out[pad:H, pad:W, :].astype(np.uint8)
return out