## Читаем изображения и делаем простое наложение:¶

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):
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()

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.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_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);