gokaygokay commited on
Commit
e9c5763
·
verified ·
1 Parent(s): 929c20c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -80
app.py CHANGED
@@ -31,38 +31,39 @@ def neighbours(i, j, max_i, max_j):
31
 
32
  def poisson_blend(img_s, mask, img_t):
33
  img_s_h, img_s_w = img_s.shape
 
 
 
 
 
 
 
 
 
34
 
35
- nnz = (mask>0).sum()
36
- im2var = -np.ones(mask.shape[0:2], dtype='int32')
37
- im2var[mask>0] = np.arange(nnz)
38
-
39
- ys, xs = np.where(mask==1)
40
-
41
- A = sp.sparse.lil_matrix((4*nnz, nnz))
42
- b = np.zeros(4*nnz)
43
-
44
- e = 0
45
- for n in range(nnz):
46
- y, x = ys[n], xs[n]
47
-
48
- for n_y, n_x in neighbours(y, x, img_s_h-1, img_s_w-1):
49
- A[e, im2var[y][x]] = 1
50
- b[e] = img_s[y][x] - img_s[n_y][n_x]
51
-
52
- if im2var[n_y][n_x] != -1:
53
- A[e, im2var[n_y][n_x]] = -1
54
- else:
55
- b[e] += img_t[n_y][n_x]
56
- e += 1
57
-
58
- A = sp.sparse.csr_matrix(A)
59
  v = sp.sparse.linalg.lsqr(A, b)[0]
60
 
 
61
  img_t_out = img_t.copy()
62
-
63
- for n in range(nnz):
64
- y, x = ys[n], xs[n]
65
- img_t_out[y][x] = v[im2var[y][x]]
66
 
67
  return np.clip(img_t_out, 0, 1)
68
 
@@ -108,62 +109,61 @@ def mixed_blend(img_s, mask, img_t):
108
 
109
  return np.clip(img_t_out, 0, 1)
110
 
111
- def _2d_gaussian(sigma):
112
- ksize = np.int(np.ceil(sigma)*6+1)
113
- gaussian_1d = cv2.getGaussianKernel(ksize, sigma)
114
- return gaussian_1d * np.transpose(gaussian_1d)
115
-
116
- def _low_pass_filter(img, sigma):
117
- return cv2.filter2D(img, -1, _2d_gaussian(sigma))
118
-
119
- def _high_pass_filter(img, sigma):
120
- return img - _low_pass_filter(img, sigma)
121
-
122
- def _gaus_pyramid(img, depth, sigma):
123
- _im = img.copy()
124
- pyramid = []
125
- for d in range(depth-1):
126
- _im = _low_pass_filter(_im.copy(), sigma)
127
- pyramid.append(_im)
128
- _im = cv2.pyrDown(_im)
129
- return pyramid
130
-
131
- def _lap_pyramid(img, depth, sigma):
132
- _im = img.copy()
133
- pyramid = []
134
- for d in range(depth-1):
135
- lap = _high_pass_filter(_im.copy(), sigma)
136
- pyramid.append(lap)
137
- _im = cv2.pyrDown(_im)
138
- return pyramid
139
-
140
- def _blend(img1, img2, mask):
141
- return img1 * mask + img2 * (1.0 - mask)
142
-
143
  def laplacian_blend(img1, img2, mask, depth=5, sigma=25):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  mask_gaus_pyramid = _gaus_pyramid(mask, depth, sigma)
145
- img1_lap_pyramid, img2_lap_pyramid = _lap_pyramid(img1, depth, sigma), _lap_pyramid(img2, depth, sigma)
146
 
147
- blended = [_blend(obj, bg, mask) for obj, bg, mask in zip(img1_lap_pyramid, img2_lap_pyramid, mask_gaus_pyramid)][::-1]
148
-
149
- h, w = blended[0].shape[:2]
150
-
151
- img1 = cv2.resize(img1, (w, h))
152
- img2 = cv2.resize(img2, (w, h))
153
- mask = cv2.resize(mask, (w, h))
154
 
155
- blanded_img = _blend(img1, img2, mask)
156
- blanded_img = cv2.resize(blanded_img, blended[0].shape[:2])
157
-
158
- imgs = []
159
- for d in range(0, depth-1):
160
- gaussian_img = _low_pass_filter(blanded_img.copy(), sigma)
161
- reconstructed_img = cv2.add(blended[d], gaussian_img)
162
-
163
- imgs.append(reconstructed_img)
164
- blanded_img = cv2.pyrUp(reconstructed_img)
165
-
166
- return np.clip(imgs[-1], 0, 1)
167
 
168
  def load_example_images(bg_path, obj_path, mask_path):
169
  bg_img = cv2.imread(bg_path)
 
31
 
32
  def poisson_blend(img_s, mask, img_t):
33
  img_s_h, img_s_w = img_s.shape
34
+ nnz = np.sum(mask > 0)
35
+ im2var = np.full(mask.shape, -1, dtype='int32')
36
+ im2var[mask > 0] = np.arange(nnz)
37
+
38
+ ys, xs = np.where(mask == 1)
39
+
40
+ # Precompute neighbor indices
41
+ y_n = np.clip(np.stack([ys-1, ys+1, ys, ys]), 0, img_s_h-1)
42
+ x_n = np.clip(np.stack([xs, xs, xs-1, xs+1]), 0, img_s_w-1)
43
 
44
+ # Compute differences
45
+ d = img_s[ys, xs][:, np.newaxis] - img_s[y_n, x_n]
46
+
47
+ # Construct sparse matrix A and vector b
48
+ rows = np.repeat(np.arange(4*nnz), 2)
49
+ cols = np.column_stack([np.repeat(im2var[ys, xs], 4), im2var[y_n, x_n].ravel()])
50
+ data = np.column_stack([np.ones(4*nnz), -np.ones(4*nnz)]).ravel()
51
+
52
+ mask_n = (im2var[y_n, x_n] != -1).ravel()
53
+ rows = rows[mask_n]
54
+ cols = cols[mask_n]
55
+ data = data[mask_n]
56
+
57
+ A = sp.sparse.csr_matrix((data, (rows, cols)), shape=(4*nnz, nnz))
58
+ b = d.ravel()
59
+ b[~mask_n] += img_t[y_n, x_n].ravel()[~mask_n]
60
+
61
+ # Solve the system
 
 
 
 
 
 
62
  v = sp.sparse.linalg.lsqr(A, b)[0]
63
 
64
+ # Update the target image
65
  img_t_out = img_t.copy()
66
+ img_t_out[ys, xs] = v
 
 
 
67
 
68
  return np.clip(img_t_out, 0, 1)
69
 
 
109
 
110
  return np.clip(img_t_out, 0, 1)
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  def laplacian_blend(img1, img2, mask, depth=5, sigma=25):
113
+ def _2d_gaussian(sigma):
114
+ ksize = int(np.ceil(sigma) * 6 + 1)
115
+ gaussian_1d = cv2.getGaussianKernel(ksize, sigma)
116
+ return gaussian_1d @ gaussian_1d.T
117
+
118
+ def _low_pass_filter(img, sigma):
119
+ return cv2.filter2D(img, -1, _2d_gaussian(sigma))
120
+
121
+ def _high_pass_filter(img, sigma):
122
+ return img - _low_pass_filter(img, sigma)
123
+
124
+ def _gaus_pyramid(img, depth, sigma):
125
+ pyramid = [img]
126
+ for _ in range(depth - 1):
127
+ img = _low_pass_filter(cv2.pyrDown(img), sigma)
128
+ pyramid.append(img)
129
+ return pyramid
130
+
131
+ def _lap_pyramid(img, depth, sigma):
132
+ pyramid = []
133
+ for d in range(depth - 1):
134
+ next_img = cv2.pyrDown(img)
135
+ lap = img - cv2.pyrUp(next_img, dstsize=img.shape[:2])
136
+ pyramid.append(lap)
137
+ img = next_img
138
+ pyramid.append(img)
139
+ return pyramid
140
+
141
+ def _blend(img1, img2, mask):
142
+ return img1 * mask + img2 * (1.0 - mask)
143
+
144
+ # Ensure mask is 3D
145
+ if mask.ndim == 2:
146
+ mask = np.repeat(mask[:, :, np.newaxis], 3, axis=2)
147
+
148
+ # Create Gaussian pyramid for mask
149
  mask_gaus_pyramid = _gaus_pyramid(mask, depth, sigma)
 
150
 
151
+ # Create Laplacian pyramids for images
152
+ img1_lap_pyramid = _lap_pyramid(img1, depth, sigma)
153
+ img2_lap_pyramid = _lap_pyramid(img2, depth, sigma)
 
 
 
 
154
 
155
+ # Blend pyramids
156
+ blended_pyramid = [_blend(img1_lap, img2_lap, mask_gaus)
157
+ for img1_lap, img2_lap, mask_gaus
158
+ in zip(img1_lap_pyramid, img2_lap_pyramid, mask_gaus_pyramid)]
159
+
160
+ # Reconstruct image
161
+ blended_img = blended_pyramid[-1]
162
+ for lap in reversed(blended_pyramid[:-1]):
163
+ blended_img = cv2.pyrUp(blended_img, dstsize=lap.shape[:2])
164
+ blended_img += lap
165
+
166
+ return np.clip(blended_img, 0, 1)
167
 
168
  def load_example_images(bg_path, obj_path, mask_path):
169
  bg_img = cv2.imread(bg_path)