parent
3c0e7a9dde
commit
abdfaf7304
@ -0,0 +1,79 @@
|
||||
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('/home/UCA/lucastigli/patchMatch/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,97 @@
|
||||
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
|
||||
img_copy = np.copy(img)
|
||||
xx1 = max(0, x1-patchSize)
|
||||
yy1 = max(0, y1-patchSize)
|
||||
xx2 = min(width, x2+patchSize)
|
||||
yy2 = min(height, y2+patchSize)
|
||||
|
||||
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 = [(-1,0), (1,0), (0,-1), (0,1), (-1,-1), (-1,1), (1,-1), (1,1)]
|
||||
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/10)):
|
||||
for y in range(yy1,yy2-patchSize,int(patchSize/10)):
|
||||
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
|
||||
|
||||
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 = 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