前回のStanford University/CS131/宿題4-3 画像拡大の続きをやる。今回の宿題は、Other experiments on the image(同じ画像によるさまざまな実験的試み)、Reducing and enlarging on another image(別の画像を使用した画像の縮小・拡大)をカバーする。
Other experiments on the image¶
Feel free to experiment more on this image, try different sizes to enlarge or reduce, or check what seams are chosen…
この画像を使って、さまざまなサイズに画像を拡大・縮小したり、あるいは、どのシームが選択されたかをチェックしてみたりと、色々と自由に実験してみよう。
Reducing by a 2x factor often leads to weird patterns.
Enlarging by more than 2x is impossible since we only duplicate seams. One solution is to enlarge in mutliple steps (enlarge x1.4, enlarge again x1.4…)
2倍率での画像縮小は変なパターンを生成しやすい。2倍以上の画像の拡大については、ただ単にシームを複製しているだけなので不可能だ。1つの解決方法が、複数ステップ(x1.4拡大した後で再びx1.4拡大する)を使って画像を拡大することだ。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
from skimage import color,io, util
from time import time
from IPython.display import HTML
from __future__ import print_function
from seam_carving import compute_cost,energy_function,enlarge
from seam_carving import backtrack_seam,reduce,remove_seam
%matplotlib inline
plt.rcParams['figure.figsize'] = (15.0, 12.0) # set default size of plots
plt.rcParams["font.size"] = "17"
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
img = io.imread('imgs/broadway_tower.jpg')
img = util.img_as_float(img)
# Reduce image width
H, W, _ = img.shape
W_new = 200
start = time()
out = reduce(img, W_new)
end = time()
print("Reducing width from %d to %d: %f seconds." % (W, W_new, end - start))
plt.subplot(2, 1, 1)
plt.title('Original')
plt.imshow(img)
plt.subplot(2, 1, 2)
plt.title('Resized')
plt.imshow(out)
plt.show()
Faster reduce¶
Implement a faster version of reduce called reduce_fast in the file seam_carving.py.
seam_carving.pyにreduce高速版reduce_fastを実装する。
def reduce_fast(image, size, axis=1, efunc=energy_function, cfunc=compute_cost):
"""Reduces the size of the image using the seam carving process. Faster than `reduce`.
Use your own implementation (you can use auxiliary functions if it helps like `energy_fast`)
to implement a faster version of `reduce`.
Hint: do we really need to compute the whole cost map again at each iteration?
Args:
image: numpy array of shape (H, W, C)
size: size to reduce height or width to (depending on axis)
axis: reduce in width (axis=1) or height (axis=0)
efunc: energy function to use
cfunc: cost function to use
Returns:
out: numpy array of shape (size, W, C) if axis=0, or (H, size, C) if axis=1
"""
out = np.copy(image)
if axis == 0:
out = np.transpose(out, (1, 0, 2))
H = out.shape[0]
W = out.shape[1]
assert W > size, "Size must be smaller than %d" % W
assert size > 0, "Size must be greater than zero"
### YOUR CODE HERE
energy = efunc(out)
for i in range(W-size):
cost,path = cfunc(out,energy)
seam = backtrack_seam(path,np.argmin(cost[-1]))
out = remove_seam(out,seam)
i = np.min(seam)
j = np.max(seam)
if i <= 3:
energy = np.c_[efunc(out[:,0:j+2])[:,:-1],\
energy[:,j+2:]]
elif j >= i-3:
energy = np.c_[energy[:,0:i-1],\
efunc(out[:,i-3:])[:,2:]]
else:
energy = np.c_[energy[:,0:i-1], \
efunc(out[:,i-3:j+2])[:,2:-1],energy[:,j+2:]]
### END YOUR CODE
assert out.shape[1] == size, "Output doesn't have the right shape"
if axis == 0:
out = np.transpose(out, (1, 0, 2))
return out
# Reduce image width
H, W, _ = img.shape
W_new = 400
start = time()
out = reduce(img, W_new)
end = time()
print("Normal reduce width from %d to %d: %f seconds." % (W, W_new, end - start))
start = time()
out_fast = reduce_fast(img, W_new)
end = time()
print("Faster reduce width from %d to %d: %f seconds." % (W, W_new, end - start))
assert np.allclose(out, out_fast), "Outputs don't match."
plt.subplot(3, 3, 1)
plt.title('Original')
plt.imshow(img)
plt.subplot(3, 3, 2)
plt.title('Resized')
plt.imshow(out)
plt.subplot(3, 3, 3)
plt.title('Faster resized')
plt.imshow(out)
plt.show()
Reducing and enlarging on another image¶
Also check these outputs with another image.
別の画像を使ってこれらの出力のチェックもしておく。
# Load image
img2 = io.imread('imgs/wave.jpg')
img2 = util.img_as_float(img2)
plt.title('Original Image')
plt.imshow(img2)
plt.show()
out = reduce(img2, 300)
plt.imshow(out)
plt.show()
out = enlarge(img2, 800)
plt.imshow(out)
plt.show()