Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
e29bf957cf | 4 months ago |
![]() |
dfeb21d5a4 | 4 months ago |
![]() |
47e1fe1f1e | 4 months ago |
![]() |
3b26c00564 | 4 months ago |
![]() |
b644c96c1a | 4 months ago |
![]() |
2ebd56523f | 5 months ago |
![]() |
d83e36d227 | 5 months ago |
![]() |
abdfaf7304 | 5 months ago |
@ -1,2 +1,6 @@
|
||||
# patchMatch
|
||||
|
||||
Cette branche a pour seul but de versioner et sauvgarder des experimentations.
|
||||
Elle ne rejoindra jamais la branche ```master```.
|
||||
|
||||
C'est pour ça que contrairement aux autres branche, elle n'est pas supprimé.
|
@ -0,0 +1,210 @@
|
||||
from matplotlib.widgets import RectangleSelector
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
def doPatchMatch(img,x1,y1,x2,y2,patchSize=17,nbRadomPatch=10):
|
||||
|
||||
def getPatchFromCoord(x,y):
|
||||
patch = np.array([[i, j] for i in range(patchSize) for j in range(patchSize)])
|
||||
patch[:,0] = patch[:,0] + x
|
||||
patch[:,1] = patch[:,1] + y
|
||||
return patch
|
||||
|
||||
def distance(patchValue1,patchValue2):
|
||||
mask = np.all(patchValue1 == [-1, -1, -1, -1], axis=-1)
|
||||
return np.sum((patchValue1[~mask] - patchValue2[~mask]) ** 2)
|
||||
|
||||
def getBestNeigbourPatch(xy,ogValue,ogDist,step):
|
||||
x, y = xy
|
||||
|
||||
dist = -1
|
||||
|
||||
xt, yt = x+step, y
|
||||
if (0 <= xt <= width - patchSize and 0 <= yt <= height - patchSize):
|
||||
patch = getPatchFromCoord(xt,yt)
|
||||
patchValue = patchToValue(patch)
|
||||
dist = distance(ogValue,patchValue)
|
||||
|
||||
xt, yt = x-step, y
|
||||
if (0 <= xt <= width - patchSize and 0 <= yt <= height - patchSize):
|
||||
tpatch = getPatchFromCoord(xt,yt)
|
||||
tpatchValue = patchToValue(tpatch)
|
||||
tdist = distance(ogValue,tpatchValue)
|
||||
if tdist < dist or dist == -1:
|
||||
dist = tdist
|
||||
patch = tpatch
|
||||
patchValue = tpatchValue
|
||||
|
||||
xt, yt = x, y+step
|
||||
if (0 <= xt <= width - patchSize and 0 <= yt <= height - patchSize):
|
||||
tpatch = getPatchFromCoord(xt,yt)
|
||||
tpatchValue = patchToValue(tpatch)
|
||||
tdist = distance(ogValue,tpatchValue)
|
||||
if tdist < dist or dist == -1:
|
||||
dist = tdist
|
||||
patch = tpatch
|
||||
patchValue = tpatchValue
|
||||
|
||||
xt, yt = x, y-step
|
||||
if (0 <= xt <= width - patchSize and 0 <= yt <= height - patchSize):
|
||||
tpatch = getPatchFromCoord(xt,yt)
|
||||
tpatchValue = patchToValue(tpatch)
|
||||
tdist = distance(ogValue,tpatchValue)
|
||||
if tdist < dist or dist == -1:
|
||||
dist = tdist
|
||||
patch = tpatch
|
||||
patchValue = tpatchValue
|
||||
if dist == -1:
|
||||
return False, None, None, None
|
||||
return dist < ogDist, patch, patchValue, dist
|
||||
|
||||
def getTheBestPatch(addr,ogValue):
|
||||
patchs = []
|
||||
patchsValue = []
|
||||
dists = []
|
||||
for i in range(nbRadomPatch):
|
||||
x,y = getRandomPatch()
|
||||
patch = getPatchFromCoord(x,y)
|
||||
patchValue = patchToValue(patch)
|
||||
dist = distance(ogValue,patchValue)
|
||||
patchs.append(patch)
|
||||
patchsValue.append(patchValue)
|
||||
dists.append(dist)
|
||||
|
||||
minIdx = np.argmin(np.array(dist))
|
||||
patch = patchs[minIdx]
|
||||
patchValue = patchsValue[minIdx]
|
||||
|
||||
ogDist = dists[minIdx]
|
||||
foundNew = True
|
||||
step = 5
|
||||
addr = addr[0]
|
||||
while foundNew:
|
||||
foundNew, tpatch, tpatchValue, tdist = getBestNeigbourPatch(addr,ogValue,ogDist,step)
|
||||
if (foundNew):
|
||||
addr = tpatch[patchSize//2]
|
||||
patch = tpatch
|
||||
patchValue = tpatchValue
|
||||
ogDist = tdist
|
||||
step = 5
|
||||
else:
|
||||
step = step*1.25
|
||||
foundNew = step < min(width, height)/2
|
||||
return patch, patchValue
|
||||
|
||||
|
||||
def patchToValue(patch):
|
||||
return img[patch[0][1]:patch[len(patch)-1][1], patch[0][0]:patch[len(patch)-1][0]]
|
||||
|
||||
def getRandomPatch():
|
||||
rx = np.random.randint(0, width - patchSize)
|
||||
ry = np.random.randint(0, height - patchSize)
|
||||
return rx, ry
|
||||
|
||||
def initializePermimiter():
|
||||
perimeter = []
|
||||
for x in range(x1, x2 + 1):
|
||||
perimeter.append((x, y1))
|
||||
perimeter.append((x, y2))
|
||||
|
||||
for y in range(y1 + 1, y2):
|
||||
perimeter.append((x1, y))
|
||||
perimeter.append((x2, y))
|
||||
img[y1:y2+1, x1:x2+1] = -1
|
||||
return np.array(perimeter)
|
||||
|
||||
def removeAndAddFromPerimiter(perimiter, addr):
|
||||
p= []
|
||||
npAddr = np.array(addr)
|
||||
for coord in perimiter:
|
||||
if not np.any(np.all(npAddr == np.array(coord), axis=1)):
|
||||
p.append(coord)
|
||||
|
||||
perimiter = p
|
||||
p1 = patchSize+2
|
||||
for dx in range(-1, p1):
|
||||
for dy in range(-1, p1):
|
||||
if (dx!=-1 and dx!=p1-1 and dy != -1 and dy != p1-1):
|
||||
continue
|
||||
nx, ny = addr[0,0] + dx, addr[0,1] + dy
|
||||
if 0 <= nx < width and 0 <= ny < height and img[ny, nx][0] == -1:
|
||||
if len(perimiter) == 0:
|
||||
perimiter.append([nx, ny])
|
||||
continue
|
||||
if not np.any(np.all(perimiter == np.array([int(nx), int(ny)]), axis=1)):
|
||||
perimiter.append([nx, ny])
|
||||
return perimiter
|
||||
|
||||
def applyPatch(patch,addr):
|
||||
for i in range(len(addr)):
|
||||
if img[addr[i, 1], addr[i, 0]][0] == -1:
|
||||
img[addr[i, 1], addr[i, 0]] = img[patch[i, 1],patch[i, 0]]
|
||||
|
||||
def getRandomFromPerimiter(perimiter):
|
||||
return perimiter[np.random.randint(len(perimiter))]
|
||||
|
||||
def loop(perimiter):
|
||||
x,y = getRandomFromPerimiter(perimiter)
|
||||
addr = getPatchFromCoord(x,y)
|
||||
ogValue = patchToValue(addr)
|
||||
patch,patchValue = getTheBestPatch(addr,ogValue)
|
||||
applyPatch(patch,addr)
|
||||
perimiter = removeAndAddFromPerimiter(perimiter,addr)
|
||||
return perimiter
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
semiPatch = int(patchSize/2)
|
||||
height, width, _ = img.shape
|
||||
|
||||
|
||||
|
||||
perimiter = initializePermimiter()
|
||||
it = 0
|
||||
|
||||
# perimiter = loop(perimiter)
|
||||
# perimiter = loop(perimiter)
|
||||
# perimiter = loop(perimiter)
|
||||
# for coord in perimiter:
|
||||
# img[coord[1], coord[0]] = [1,1,1,1]
|
||||
# img[img == -1] = 0
|
||||
|
||||
while len(perimiter)> 0:
|
||||
it += 1
|
||||
perimiter = loop(perimiter)
|
||||
if (it == 1000):
|
||||
it = 0
|
||||
print(len(perimiter))
|
||||
|
||||
return img
|
||||
|
||||
|
||||
|
||||
|
||||
img = plt.imread('boat.png')
|
||||
|
||||
if len(img.shape) == 2:
|
||||
img = np.stack((img,)*3, axis=-1)
|
||||
|
||||
def onselect(eclick, erelease):
|
||||
x1, y1 = eclick.xdata, eclick.ydata
|
||||
x2, y2 = erelease.xdata, erelease.ydata
|
||||
|
||||
print("drawing")
|
||||
img_copy = np.copy(img)
|
||||
res = doPatchMatch(img_copy,int(x1),int(y1),int(x2),int(y2),33)
|
||||
ax.imshow(res)
|
||||
plt.draw()
|
||||
print("drawed")
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(img)
|
||||
toggle_selector = RectangleSelector(ax, onselect, useblit=True,
|
||||
button=[1], minspanx=5, minspany=5, spancoords='pixels',
|
||||
interactive=True)
|
||||
plt.axis('off')
|
||||
plt.show()
|
@ -0,0 +1,133 @@
|
||||
# j'ai trouvé ce code sur la page github:
|
||||
# https://github.com/MingtaoGuo/PatchMatch/blob/master/PatchMatch.py
|
||||
# pour experimenter et comprendre comment l'algoritme marche
|
||||
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
import time
|
||||
|
||||
def cal_distance(a, b, A_padding, B, p_size):
|
||||
p = p_size // 2
|
||||
patch_a = A_padding[a[0]:a[0]+p_size, a[1]:a[1]+p_size, :]
|
||||
patch_b = B[b[0]-p:b[0]+p+1, b[1]-p:b[1]+p+1, :]
|
||||
temp = patch_b - patch_a
|
||||
num = np.sum(1 - np.int32(np.isnan(temp)))
|
||||
dist = np.sum(np.square(np.nan_to_num(temp))) / num
|
||||
return dist
|
||||
|
||||
def reconstruction(f, A, B):
|
||||
A_h = np.size(A, 0)
|
||||
A_w = np.size(A, 1)
|
||||
temp = np.zeros_like(A)
|
||||
for i in range(A_h):
|
||||
for j in range(A_w):
|
||||
temp[i, j, :] = B[f[i, j][0], f[i, j][1], :]
|
||||
Image.fromarray(temp).show()
|
||||
|
||||
|
||||
def initialization(A, B, p_size):
|
||||
A_h = np.size(A, 0)
|
||||
A_w = np.size(A, 1)
|
||||
B_h = np.size(B, 0)
|
||||
B_w = np.size(B, 1)
|
||||
p = p_size // 2
|
||||
random_B_r = np.random.randint(p, B_h-p, [A_h, A_w])
|
||||
random_B_c = np.random.randint(p, B_w-p, [A_h, A_w])
|
||||
A_padding = np.ones([A_h+p*2, A_w+p*2, 3]) * np.nan
|
||||
A_padding[p:A_h+p, p:A_w+p, :] = A
|
||||
f = np.zeros([A_h, A_w], dtype=object)
|
||||
dist = np.zeros([A_h, A_w])
|
||||
for i in range(A_h):
|
||||
for j in range(A_w):
|
||||
a = np.array([i, j])
|
||||
b = np.array([random_B_r[i, j], random_B_c[i, j]], dtype=np.int32)
|
||||
f[i, j] = b
|
||||
dist[i, j] = cal_distance(a, b, A_padding, B, p_size)
|
||||
return f, dist, A_padding
|
||||
|
||||
def propagation(f, a, dist, A_padding, B, p_size, is_odd):
|
||||
A_h = np.size(A_padding, 0) - p_size + 1
|
||||
A_w = np.size(A_padding, 1) - p_size + 1
|
||||
x = a[0]
|
||||
y = a[1]
|
||||
if is_odd:
|
||||
d_left = dist[max(x-1, 0), y]
|
||||
d_up = dist[x, max(y-1, 0)]
|
||||
d_current = dist[x, y]
|
||||
idx = np.argmin(np.array([d_current, d_left, d_up]))
|
||||
if idx == 1:
|
||||
f[x, y] = f[max(x - 1, 0), y]
|
||||
dist[x, y] = cal_distance(a, f[x, y], A_padding, B, p_size)
|
||||
if idx == 2:
|
||||
f[x, y] = f[x, max(y - 1, 0)]
|
||||
dist[x, y] = cal_distance(a, f[x, y], A_padding, B, p_size)
|
||||
else:
|
||||
d_right = dist[min(x + 1, A_h-1), y]
|
||||
d_down = dist[x, min(y + 1, A_w-1)]
|
||||
d_current = dist[x, y]
|
||||
idx = np.argmin(np.array([d_current, d_right, d_down]))
|
||||
if idx == 1:
|
||||
f[x, y] = f[min(x + 1, A_h-1), y]
|
||||
dist[x, y] = cal_distance(a, f[x, y], A_padding, B, p_size)
|
||||
if idx == 2:
|
||||
f[x, y] = f[x, min(y + 1, A_w-1)]
|
||||
dist[x, y] = cal_distance(a, f[x, y], A_padding, B, p_size)
|
||||
|
||||
def random_search(f, a, dist, A_padding, B, p_size, alpha=0.5):
|
||||
x = a[0]
|
||||
y = a[1]
|
||||
B_h = np.size(B, 0)
|
||||
B_w = np.size(B, 1)
|
||||
p = p_size // 2
|
||||
i = 4
|
||||
search_h = B_h * alpha ** i
|
||||
search_w = B_w * alpha ** i
|
||||
b_x = f[x, y][0]
|
||||
b_y = f[x, y][1]
|
||||
while search_h > 1 and search_w > 1:
|
||||
search_min_r = max(b_x - search_h, p)
|
||||
search_max_r = min(b_x + search_h, B_h-p)
|
||||
random_b_x = np.random.randint(search_min_r, search_max_r)
|
||||
search_min_c = max(b_y - search_w, p)
|
||||
search_max_c = min(b_y + search_w, B_w - p)
|
||||
random_b_y = np.random.randint(search_min_c, search_max_c)
|
||||
search_h = B_h * alpha ** i
|
||||
search_w = B_w * alpha ** i
|
||||
b = np.array([random_b_x, random_b_y])
|
||||
d = cal_distance(a, b, A_padding, B, p_size)
|
||||
if d < dist[x, y]:
|
||||
dist[x, y] = d
|
||||
f[x, y] = b
|
||||
i += 1
|
||||
|
||||
def NNS(img, ref, p_size, itr):
|
||||
A_h = np.size(img, 0)
|
||||
A_w = np.size(img, 1)
|
||||
f, dist, img_padding = initialization(img, ref, p_size)
|
||||
for itr in range(1, itr+1):
|
||||
if itr % 2 == 0:
|
||||
for i in range(A_h - 1, -1, -1):
|
||||
for j in range(A_w - 1, -1, -1):
|
||||
a = np.array([i, j])
|
||||
propagation(f, a, dist, img_padding, ref, p_size, False)
|
||||
random_search(f, a, dist, img_padding, ref, p_size)
|
||||
else:
|
||||
for i in range(A_h):
|
||||
for j in range(A_w):
|
||||
a = np.array([i, j])
|
||||
propagation(f, a, dist, img_padding, ref, p_size, True)
|
||||
random_search(f, a, dist, img_padding, ref, p_size)
|
||||
print("iteration: %d"%(itr))
|
||||
return f
|
||||
|
||||
if __name__ == "__main__":
|
||||
img = np.array(Image.open("./cup_a.jpg"))
|
||||
ref = np.array(Image.open("./cup_b.jpg"))
|
||||
p_size = 3
|
||||
itr = 5
|
||||
start = time.time()
|
||||
f = NNS(img, ref, p_size, itr)
|
||||
end = time.time()
|
||||
print(end - start)
|
||||
reconstruction(f, img, ref)
|
@ -0,0 +1,89 @@
|
||||
from matplotlib.widgets import RectangleSelector
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
def doKnn(img,x1,y1,x2,y2):
|
||||
|
||||
def getNotInBoundNeighbour(neighbour, x1,y1,x2,y2):
|
||||
mask = np.logical_or(
|
||||
np.logical_or(neighbour[:, 0] < y1, neighbour[:, 0] > y2),
|
||||
np.logical_or(neighbour[:, 1] < x1, neighbour[:, 1] > x2)
|
||||
)
|
||||
return neighbour[mask]
|
||||
|
||||
def neighbourReelPixel(x,y):
|
||||
tNeighbour = np.copy(neighbour)
|
||||
tNeighbour = tNeighbour + np.array([y,x])
|
||||
return tNeighbour
|
||||
|
||||
def getAvgPixelFromNeighbour(neighbour):
|
||||
return np.mean(img[neighbour[:,0],neighbour[:,1]], axis=0)
|
||||
|
||||
|
||||
neighbour = np.array([[-1,-1],[-1,0],[0,-1],[-1,1],[1,-1],[0,1],[1,0],[1,1]])
|
||||
x1c = x1
|
||||
y1c = y1
|
||||
x2c = x2
|
||||
y2c = y2
|
||||
while x1 != x2 and y1 != y2:
|
||||
for x in range(x1,x2):
|
||||
currentNeighbour1 = neighbourReelPixel(x,y1)
|
||||
currentNeighbour2 = neighbourReelPixel(x,y2)
|
||||
currentNeighbour1 = getNotInBoundNeighbour(currentNeighbour1,x1,y1,x2,y2)
|
||||
currentNeighbour2 = getNotInBoundNeighbour(currentNeighbour2,x1,y1,x2,y2)
|
||||
currentColor1 = getAvgPixelFromNeighbour(currentNeighbour1)
|
||||
currentColor2 = getAvgPixelFromNeighbour(currentNeighbour2)
|
||||
img[y1,x] = currentColor1
|
||||
img[y2,x] = currentColor2
|
||||
for y in range(y1,y2):
|
||||
currentNeighbour1 = neighbourReelPixel(x1,y)
|
||||
currentNeighbour2 = neighbourReelPixel(x2,y)
|
||||
currentNeighbour1 = getNotInBoundNeighbour(currentNeighbour1,x1,y1,x2,y2)
|
||||
currentNeighbour2 = getNotInBoundNeighbour(currentNeighbour2,x1,y1,x2,y2)
|
||||
currentColor1 = getAvgPixelFromNeighbour(currentNeighbour1)
|
||||
currentColor2 = getAvgPixelFromNeighbour(currentNeighbour2)
|
||||
img[y,x1] = currentColor1
|
||||
img[y,x2] = currentColor2
|
||||
x1 += 1
|
||||
x2 -= 1
|
||||
y1 += 1
|
||||
y2 -= 1
|
||||
|
||||
for x in range(x1c, x2c):
|
||||
for y in range(y1c, y2c):
|
||||
currentNeighbour = neighbourReelPixel(x, y)
|
||||
currentNeighbour = getNotInBoundNeighbour(currentNeighbour,0,0,0,0)
|
||||
currentColor = getAvgPixelFromNeighbour(currentNeighbour)
|
||||
img[y, x] = currentColor
|
||||
img[y1:y2,x1:x2]
|
||||
return img
|
||||
|
||||
|
||||
|
||||
img = plt.imread('boat.png')
|
||||
|
||||
|
||||
if len(img.shape) == 2:
|
||||
img = np.stack((img,)*3, axis=-1)
|
||||
|
||||
|
||||
|
||||
def onselect(eclick, erelease):
|
||||
x1, y1 = eclick.xdata, eclick.ydata
|
||||
x2, y2 = erelease.xdata, erelease.ydata
|
||||
|
||||
img_copy = np.copy(img)
|
||||
res = doKnn(img_copy,int(x1),int(y1),int(x2),int(y2))
|
||||
ax.imshow(res)
|
||||
plt.draw()
|
||||
print("drawed")
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(img)
|
||||
toggle_selector = RectangleSelector(ax, onselect, useblit=True,
|
||||
button=[1], minspanx=5, minspany=5, spancoords='pixels',
|
||||
interactive=True)
|
||||
plt.axis('off')
|
||||
plt.show()
|
@ -0,0 +1,78 @@
|
||||
from matplotlib.widgets import RectangleSelector
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
|
||||
def patch_match(img, patch_size=3, iterations=1):
|
||||
height, width, _ = img.shape
|
||||
offsets = np.zeros((height, width, 2), dtype=np.int32)
|
||||
|
||||
def random_offsets():
|
||||
return np.random.randint(-patch_size, patch_size + 1, size=(height, width, 2))
|
||||
|
||||
def distance(patch1, patch2):
|
||||
return np.sum((patch1 - patch2) ** 2)
|
||||
|
||||
def get_patch(x, y):
|
||||
return img[max(0, y):min(height, max(0, y) + patch_size), max(0, x):min(width, max(0, x) + patch_size)]
|
||||
|
||||
offsets = random_offsets()
|
||||
|
||||
for _ in range(iterations):
|
||||
for y in range(patch_size,height-patch_size*2):
|
||||
for x in range(patch_size,width-patch_size*2):
|
||||
best_offset = offsets[y, x]
|
||||
best_distance = distance(get_patch(x, y), get_patch(x + best_offset[0], y + best_offset[1]))
|
||||
for dy in range(-1, 2):
|
||||
for dx in range(-1, 2):
|
||||
if dx == 0 and dy == 0:
|
||||
continue
|
||||
new_offset = best_offset + [dx, dy]
|
||||
if (new_offset[0]+x>width-patch_size or new_offset[1]+y>height-patch_size):
|
||||
continue
|
||||
new_distance = distance(get_patch(x, y), get_patch(x + new_offset[0], y + new_offset[1]))
|
||||
if new_distance < best_distance:
|
||||
best_distance = new_distance
|
||||
best_offset = new_offset
|
||||
offsets[y, x] = best_offset
|
||||
|
||||
result = np.zeros_like(img)
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
offset = offsets[y, x]
|
||||
result[y, x] = img[(y + offset[1]) % height, (x + offset[0]) % width]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Load the image using matplotlib
|
||||
img = plt.imread('boat.png')
|
||||
|
||||
|
||||
def onselect(eclick, erelease):
|
||||
x1, y1 = eclick.xdata, eclick.ydata
|
||||
x2 = x1 + 150
|
||||
x2, y2 = erelease.xdata, erelease.ydata
|
||||
|
||||
avg_color = np.mean(img, axis=(0, 1))
|
||||
img_copy = np.copy(img)
|
||||
img_copy[int(y1):int(y2), int(x1):int(x2)] = avg_color
|
||||
res = patch_match(img_copy)
|
||||
ax.imshow(res)
|
||||
plt.draw()
|
||||
print("drawed")
|
||||
#ax.imshow(img_copy)
|
||||
#plt.draw()
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(img)
|
||||
toggle_selector = RectangleSelector(ax, onselect, useblit=True,
|
||||
button=[1], minspanx=5, minspany=5, spancoords='pixels',
|
||||
interactive=True)
|
||||
plt.axis('off')
|
||||
plt.show()
|
@ -0,0 +1,101 @@
|
||||
from matplotlib.widgets import RectangleSelector
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
def patchMatch(img,x1,y1,x2,y2,patchSize=20, iterations=1000):
|
||||
height, width, _ = img.shape
|
||||
xx1 = max(0, x1-patchSize)
|
||||
yy1 = max(0, y1-patchSize)
|
||||
xx2 = min(width, x2+patchSize)
|
||||
yy2 = min(height, y2+patchSize)
|
||||
|
||||
mask = np.ones((height, width), dtype=bool)
|
||||
mask[yy1:yy2, xx1:xx2] = False
|
||||
mask[y1:y2, x1:x2] = True
|
||||
img[int(y1):int(y2), int(x1):int(x2)] = np.mean(img[~mask], axis=(0, 1))
|
||||
img_copy = np.copy(img)
|
||||
|
||||
div = 10
|
||||
|
||||
if (xx2-xx1 < patchSize or yy2-yy1 < patchSize):
|
||||
return img
|
||||
|
||||
def getRandomPatch():
|
||||
rx = np.random.randint(0, width - patchSize)
|
||||
ry = np.random.randint(0, height - patchSize)
|
||||
return rx, ry
|
||||
|
||||
def fusion(patch1, patch2):
|
||||
return (patch1*2+patch2) / 3
|
||||
|
||||
def distance(patch1, patch2):
|
||||
return np.sum((patch1 - patch2) ** 2)
|
||||
|
||||
def gradientDescent(x, y, bestPatch, bestDistance):
|
||||
neighbors = [(-div,0), (div,0), (0,-div), (0,div), (-div,-div), (-div,div), (div,-div), (div,div)]
|
||||
patch = img[y:y + patchSize, x:x + patchSize]
|
||||
hasChanged = True
|
||||
while hasChanged:
|
||||
hasChanged = False
|
||||
for nx, ny in neighbors:
|
||||
cx = bestPatch[0] + nx
|
||||
cy = bestPatch[1] + ny
|
||||
if cx < 0 or cy < 0 or cx >= width - patchSize or cy >= height - patchSize:
|
||||
continue
|
||||
|
||||
neighborPatch = img[cy:cy + patchSize, cx:cx + patchSize]
|
||||
neighborDist = distance(patch, neighborPatch)
|
||||
if neighborDist < bestDistance:
|
||||
hasChanged = True
|
||||
bestPatch = [cx, cy]
|
||||
bestDistance = neighborDist
|
||||
return bestPatch, bestDistance
|
||||
|
||||
|
||||
for x in range(xx1,xx2-patchSize,int(patchSize/div)):
|
||||
for y in range(yy1,yy2-patchSize,int(patchSize/div)):
|
||||
px, py = getRandomPatch()
|
||||
bestPatch = [px, py]
|
||||
bestDistance = distance(img[y:y+patchSize,x:x+patchSize], img[py:py+patchSize,px:px+patchSize])
|
||||
firstDistance = np.copy(bestDistance)
|
||||
for _ in range(iterations):
|
||||
px, py = getRandomPatch()
|
||||
currentDistance = distance(img[y:y+patchSize,x:x+patchSize], img[py:py+patchSize,px:px+patchSize])
|
||||
if currentDistance > firstDistance:
|
||||
continue
|
||||
currentFirstDistance = np.copy(currentDistance)
|
||||
currentPatch, bestDistance = gradientDescent(x, y, bestPatch, bestDistance)
|
||||
if currentDistance < bestDistance:
|
||||
firstDistance = currentFirstDistance
|
||||
bestPatch = currentPatch
|
||||
bestDistance = currentDistance
|
||||
img_copy[y:y+patchSize, x:x+patchSize] = fusion(img_copy[y:y+patchSize, x:x+patchSize],img[bestPatch[1]:bestPatch[1]+patchSize, bestPatch[0]:bestPatch[0]+patchSize])
|
||||
img[y1:y2,x1:x2] = img_copy[y1:y2,x1:x2]
|
||||
return img
|
||||
|
||||
|
||||
# Load the image using matplotlib
|
||||
img = plt.imread('simson.png')
|
||||
|
||||
if len(img.shape) == 2:
|
||||
img = np.stack((img,)*3, axis=-1)
|
||||
|
||||
def onselect(eclick, erelease):
|
||||
x1, y1 = eclick.xdata, eclick.ydata
|
||||
x2 = x1 + 150
|
||||
x2, y2 = erelease.xdata, erelease.ydata
|
||||
|
||||
img_copy = np.copy(img)
|
||||
res = patchMatch(img_copy,int(x1),int(y1),int(x2),int(y2))
|
||||
ax.imshow(res)
|
||||
plt.draw()
|
||||
print("drawed")
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.imshow(img)
|
||||
toggle_selector = RectangleSelector(ax, onselect, useblit=True,
|
||||
button=[1], minspanx=5, minspany=5, spancoords='pixels',
|
||||
interactive=True)
|
||||
plt.axis('off')
|
||||
plt.show()
|
After Width: | Height: | Size: 33 KiB |
Loading…
Reference in new issue