In [1]:
import scipy
import scipy.misc
def split_rgb(aos):
return array(split(aos, 3, axis=2)).squeeze()
def join_rgb(soa):
return concatenate(expand_dims(soa, 3), axis=2)
class PoissonSolver:
pass
def step1(self, ref_file, target_file, ofs, target_scale, common_scale):
ref = scipy.misc.imresize(scipy.misc.imread(ref_file), common_scale, interp="bicubic")
target_scaled = scipy.misc.imresize(scipy.misc.imread(target_file), common_scale * target_scale, interp="bicubic")
rn = ref.shape[:2]
tn = target_scaled.shape[:2]
Xg, Yg = ogrid[:rn[0], :rn[1]]
mask = (Xg >= ofs[0]) & (Xg < ofs[0]+tn[0]) & (Yg >= ofs[1]) & (Yg < ofs[1]+tn[1])
rgb_view_mode = [("r", uint8), ("g", uint8), ("b", uint8)]
target = zeros_like(ref).view(dtype=rgb_view_mode).squeeze().copy()
target[ofs[0]:ofs[0]+tn[0], ofs[1]:ofs[1]+tn[1]] = target_scaled.view(dtype=rgb_view_mode).squeeze()
target = reshape(target.view(dtype=uint8), ref.shape)
naive_clone = ref.copy()
naive_clone[mask == 1] = target[mask == 1]
figsize(20, 15)
for i, image in enumerate(["ref", "target", "mask", "naive_clone"]):
matplotlib.pyplot.subplot(3, 4, 1 + i)
matplotlib.pyplot.imshow(eval(image))
matplotlib.pyplot.title(image)
ref_soa = split_rgb(ref)
target_soa = split_rgb(target)
color_mode = 'RGB'
for i in range(3):
matplotlib.pyplot.subplot(3, 4, 5 + i)
matplotlib.pyplot.imshow(eval("ref_soa[%d]" % i))
matplotlib.pyplot.title("ref %s" % color_mode[i])
matplotlib.pyplot.subplot(3, 4, 9 + i)
matplotlib.pyplot.imshow(eval("target_soa[%d]" % i))
matplotlib.pyplot.title("target %s" % color_mode[i])
self.ref_soa = ref_soa
self.target_soa = target_soa
self.mask = mask
self.naive_clone = naive_clone
self.rn = rn
self.tn = tn
In [2]:
s = PoissonSolver()
step1(s, "sky.png", "bird.png", [10, 50], 0.5, 0.25)
In [3]:
import skimage
import skimage.morphology
def step2(self):
self.strict_interior = skimage.morphology.erosion(self.mask, ones((3,3), dtype=bool))
self.border = self.mask & ~self.strict_interior
self.strict_interior_indices = self.strict_interior.nonzero()
self.num_strict_interior_pixels = self.strict_interior_indices[0].shape[0]
self.variable_index_map = -1 * ones_like(self.mask, dtype=int32)
self.variable_index_map[self.strict_interior_indices] = arange(self.num_strict_interior_pixels)
figsize(13, 4)
for i, image in enumerate(["strict_interior", "border", "variable_index_map"]):
matplotlib.pyplot.subplot(1, 3, 1 + i)
matplotlib.pyplot.imshow(eval("self.%s" % image), interpolation="nearest")
matplotlib.pyplot.title(image)
step2(s)
In [4]:
import scipy.sparse
import scipy.sparse.linalg
def gen_poisson_coeffs(self, ref, target):
A = scipy.sparse.dok_matrix((self.num_strict_interior_pixels, ) * 2, dtype=float32)
B = zeros(self.num_strict_interior_pixels, dtype=float32)
for i in range(self.num_strict_interior_pixels):
y = self.strict_interior_indices[0][i]
x = self.strict_interior_indices[1][i]
x_left, x_right = x-1, x+1
y_up, y_down = y-1, y+1
assert(i == self.variable_index_map[y,x])
x_neighbors = []
y_neighbors = []
neighbors = []
if x_right < self.rn[1]:
y_neighbors.append(y)
x_neighbors.append(x_right)
neighbors.append(self.variable_index_map[y, x_right])
if y_up >= 0:
y_neighbors.append(y_up)
x_neighbors.append(x)
neighbors.append(self.variable_index_map[y_up, x])
if x_left >= 0:
y_neighbors.append(y)
x_neighbors.append(x_left)
neighbors.append(self.variable_index_map[y, x_left])
if y_down < self.rn[0]:
y_neighbors.append(y_down)
x_neighbors.append(x)
neighbors.append(self.variable_index_map[y_down, x])
y_neighbors = array(y_neighbors)
x_neighbors = array(x_neighbors)
neighbors = array(neighbors)
neighbors_strict_interior = (neighbors != -1).nonzero()
neighbors_border = (neighbors == -1).nonzero()
num_neighbors = y_neighbors.shape[0]
sum_vq = (num_neighbors * target[y, x]) - sum(target[(y_neighbors, x_neighbors)])
sum_border_f = sum(ref[(y_neighbors[neighbors_border],x_neighbors[neighbors_border])])
A[i,i] = num_neighbors
A[i, neighbors[neighbors_strict_interior[0]]] = -1
B[i] = sum_vq + sum_border_f
return A, B
coeffs = [gen_poisson_coeffs(s, s.ref_soa[i], s.target_soa[i]) for i in range(3)]
In [5]:
X_rgb = [scipy.sparse.linalg.spsolve(A.tocsr(), B) for A, B in coeffs]
seamless_clone_soa = s.ref_soa.copy()
for i in range(3):
seamless_clone_soa[i][s.strict_interior_indices] = clip(X_rgb[i], 0, 255)
ref = join_rgb(s.ref_soa)
target = join_rgb(s.target_soa)
seamless_clone = join_rgb(seamless_clone_soa)
naive_clone = s.naive_clone
figsize(18, 4)
for i, image in enumerate(["ref", "target", "naive_clone", "seamless_clone"]):
matplotlib.pyplot.subplot(1, 4, 1 + i)
matplotlib.pyplot.imshow(locals()[image])
matplotlib.pyplot.title(image)
In [6]:
arranged_coeffs = array(split(array(coeffs), 2, axis=1)).squeeze()
A = scipy.sparse.block_diag(arranged_coeffs[0]).tocsr()
B = concatenate(arranged_coeffs[1])
X_rgb = reshape(scipy.sparse.linalg.spsolve(A, B), (3, s.num_strict_interior_pixels))
seamless_clone_soa = s.ref_soa.copy()
for i in range(3):
seamless_clone_soa[i][s.strict_interior_indices] = clip(X_rgb[i], 0, 255)
ref = join_rgb(s.ref_soa)
target = join_rgb(s.target_soa)
naive_clone = s.naive_clone
seamless_clone_full = join_rgb(seamless_clone_soa)
figsize(18, 4)
for i, image in enumerate(["ref", "target", "naive_clone", "seamless_clone_full"]):
matplotlib.pyplot.subplot(1, 4, 1 + i)
matplotlib.pyplot.imshow(locals()[image]);
matplotlib.pyplot.title(image);
In [7]:
s = PoissonSolver()
step1(s, "sky.png", "rings.png", [10, 50], 1.0, 0.25)
step2(s)
coeffs = [gen_poisson_coeffs(s, s.ref_soa[i], s.target_soa[i]) for i in range(3)]
X_rgb = [scipy.sparse.linalg.spsolve(A.tocsr(), B) for A, B in coeffs]
seamless_clone_soa = s.ref_soa.copy()
for i in range(3):
seamless_clone_soa[i][s.strict_interior_indices] = clip(X_rgb[i], 0, 255)
ref = join_rgb(s.ref_soa)
target = join_rgb(s.target_soa)
seamless_clone = join_rgb(seamless_clone_soa)
naive_clone = s.naive_clone
figsize(18, 4)
for i, image in enumerate(["ref", "target", "naive_clone", "seamless_clone"]):
matplotlib.pyplot.subplot(1, 4, 1 + i)
matplotlib.pyplot.imshow(locals()[image]);
matplotlib.pyplot.title(image);
In [8]:
arranged_coeffs = array(split(array(coeffs), 2, axis=1)).squeeze()
A = scipy.sparse.block_diag(arranged_coeffs[0]).tocsr()
B = concatenate(arranged_coeffs[1])
X_rgb = reshape(scipy.sparse.linalg.spsolve(A, B), (3, s.num_strict_interior_pixels))
seamless_clone_soa = s.ref_soa.copy()
for i in range(3):
seamless_clone_soa[i][s.strict_interior_indices] = clip(X_rgb[i], 0, 255)
ref = join_rgb(s.ref_soa)
target = join_rgb(s.target_soa)
naive_clone = s.naive_clone
seamless_clone_full = join_rgb(seamless_clone_soa)
figsize(18, 4)
for i, image in enumerate(["ref", "target", "naive_clone", "seamless_clone_full"]):
matplotlib.pyplot.subplot(1, 4, 1 + i)
matplotlib.pyplot.imshow(locals()[image])
matplotlib.pyplot.title(image)