commentaire

master
Ludovic CASTIGLIA 4 months ago
parent 66b99b2960
commit 63d7218f08

@ -1,10 +1,10 @@
from maskedImage import MaskedImage from maskedImage import MaskedImage
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from nnf import Nnf import concurrent.futures
from imageRelation import ImageRelation
import numpy as np import numpy as np
import cv2 import cv2
import concurrent.futures
def read(file): def read(file):
# fonction qui renvoit une image à partir de son chemin # fonction qui renvoit une image à partir de son chemin
@ -19,7 +19,7 @@ def doTheInpainting(img,mask,radius):
def maximizeForTheScale(scale): def maximizeForTheScale(scale):
# fonction interne qui effectue l'impainting pour une version réduite de l'image # fonction interne qui effectue l'impainting pour une version réduite de l'image
iterEM = 1+2*scale iterEM = 1+2*scale
iterNnf = min(7,1+scale) npPass = min(7,1+scale)
source = sourceToTarget.input source = sourceToTarget.input
target = targetToSource.output target = targetToSource.output
newTarget = None newTarget = None
@ -34,7 +34,7 @@ def doTheInpainting(img,mask,radius):
if not source.containsMask(x,y,radius): if not source.containsMask(x,y,radius):
targetToSource.field[y,x] = (x,y,0) targetToSource.field[y,x] = (x,y,0)
# on cherche les patchs # on cherche les patchs
targetToSource.minimize(iterNnf) targetToSource.findBestPatch(npPass)
# on crée la source et la target # on crée la source et la target
upscaled = False upscaled = False
if scale>=1 and emloop == iterEM: if scale>=1 and emloop == iterEM:
@ -67,45 +67,45 @@ def doTheInpainting(img,mask,radius):
if (level == maxLevel-1): if (level == maxLevel-1):
target = source.copy() target = source.copy()
target.mask[0:target.height,0:target.width] = False target.mask[0:target.height,0:target.width] = False
sourceToTarget = Nnf(source,target,radius) sourceToTarget = ImageRelation(source,target,radius)
sourceToTarget.randomize() sourceToTarget.randomize()
targetToSource = Nnf(target,source,radius) targetToSource = ImageRelation(target,source,radius)
targetToSource.randomize() targetToSource.randomize()
else: else:
newNnf = Nnf(source,target,radius) newImRel = ImageRelation(source,target,radius)
newNnf.initializeFromNnf(sourceToTarget) newImRel.initializeFromImageRelation(sourceToTarget)
sourceToTarget = newNnf sourceToTarget = newImRel
newNnfRev = Nnf(target,source,radius) newImRelRev = ImageRelation(target,source,radius)
newNnfRev.initializeFromNnf(targetToSource) newImRelRev.initializeFromImageRelation(targetToSource)
targetToSource = newNnfRev targetToSource = newImRelRev
target, sourceToTarget, targetToSource = maximizeForTheScale(level) target, sourceToTarget, targetToSource = maximizeForTheScale(level)
plt.imshow(target.image) plt.imshow(target.image)
plt.pause(0.01) plt.pause(0.01)
return target.image return target.image
def ExpectationStep(nnf, vote, source, upscale): def ExpectationStep(imRel, vote, source, upscale):
def ExpectationStepForNb(nb): def ExpectationStepForNb(nb):
# ajoute au vote pour toutes les pixels les valeurs déterminé lors de la recherche des patchs # ajoute au vote pour toutes les pixels les valeurs déterminé lors de la recherche des patchs
wid = nnf.input.width//7 wid = imRel.input.width//7
for y in range(nnf.input.height): for y in range(imRel.input.height):
for x in range(nb*wid,(nb+1)*wid if nb != 7 else nnf.input.width): # divise par 8 l'image dans la largeur pour calculer ses 8 parties en même temps grâce aux threads for x in range(nb*wid,(nb+1)*wid if nb != 7 else imRel.input.width): # divise par 8 l'image dans la largeur pour calculer ses 8 parties en même temps grâce aux threads
xp, yp, dp = nnf.field[y,x] xp, yp, dp = imRel.field[y,x]
w = MaskedImage.similarity[dp] w = MaskedImage.similarity[dp]
for dy in range(-nnf.patchSize,nnf.patchSize): # pour toutes les pixels du patch qui ne sorte pas de l'image for dy in range(-imRel.patchSize,imRel.patchSize): # pour toutes les pixels du patch qui ne sorte pas de l'image
ys = yp+dy ys = yp+dy
if not 0<=ys<nnf.input.height: if not 0<=ys<imRel.input.height:
continue continue
yt = y+dy yt = y+dy
if not 0<=yt<nnf.input.height: if not 0<=yt<imRel.input.height:
continue continue
for dx in range(-nnf.patchSize,nnf.patchSize): for dx in range(-imRel.patchSize,imRel.patchSize):
xs = xp+dx xs = xp+dx
if not 0<=xs<nnf.input.width: if not 0<=xs<imRel.input.width:
continue continue
xt = x+dx xt = x+dx
if not 0<=xt<nnf.input.width: if not 0<=xt<imRel.input.width:
continue continue
if upscale: # si on change d'échelle prendre les 4 pixels autour pour faire comme un knn if upscale: # si on change d'échelle prendre les 4 pixels autour pour faire comme un knn
weightedCopy(source,2*xs,2*ys,vote,2*xt,2*yt,w) weightedCopy(source,2*xs,2*ys,vote,2*xt,2*yt,w)

@ -1,8 +1,8 @@
import random
import numpy as np
from maskedImage import MaskedImage from maskedImage import MaskedImage
import numpy as np
import random
class Nnf: class ImageRelation:
def __init__(self,input,output,patchSize): def __init__(self,input,output,patchSize):
self.input = input self.input = input
self.output = output self.output = output
@ -16,16 +16,16 @@ class Nnf:
self.field[:,:,1] = np.random.randint(0,self.output.height,(self.input.height,self.input.width)) self.field[:,:,1] = np.random.randint(0,self.output.height,(self.input.height,self.input.width))
self.initialize() # on calcule la vrai distance et on change les patch si ils ne conviennent pas self.initialize() # on calcule la vrai distance et on change les patch si ils ne conviennent pas
def initializeFromNnf(self,nnf): def initializeFromImageRelation(self,imRel):
# on crée l'assignation zone patch à partir des assignations précédentes # on crée l'assignation zone patch à partir des assignations précédentes
self.field = np.zeros((self.input.height, self.input.width, 3), dtype=int) self.field = np.zeros((self.input.height, self.input.width, 3), dtype=int)
fx = int(self.input.width/nnf.input.width) fx = int(self.input.width/imRel.input.width)
fy = int(self.input.height/nnf.input.height) fy = int(self.input.height/imRel.input.height)
for y in range(self.input.height): for y in range(self.input.height):
for x in range(self.input.width): for x in range(self.input.width):
xl = min(int(x/fx),nnf.input.width-1) xl = min(int(x/fx),imRel.input.width-1)
yl = min(int(y/fy),nnf.input.height-1) yl = min(int(y/fy),imRel.input.height-1)
self.field[y,x] = (nnf.field[yl,xl,0]*fx, nnf.field[yl,xl,1]*fy, MaskedImage.DSCALE) self.field[y,x] = (imRel.field[yl,xl,0]*fx, imRel.field[yl,xl,1]*fy, MaskedImage.DSCALE)
self.initialize() # on calcule la vrai distance et on change si ils ne conviennent pas self.initialize() # on calcule la vrai distance et on change si ils ne conviennent pas
def initialize(self): def initialize(self):
@ -38,18 +38,20 @@ class Nnf:
self.field[y,x] = (random.randint(0,self.output.width),random.randint(0,self.output.height),self.distance(x,y,self.field[y,x,0],self.field[y,x,1])) self.field[y,x] = (random.randint(0,self.output.width),random.randint(0,self.output.height),self.distance(x,y,self.field[y,x,0],self.field[y,x,1]))
iter += 1 iter += 1
def minimize(self,nbPass): def findBestPatch(self,nbPass):
# recherche les meilleurs patch pour toutes les zones
for i in range(nbPass): for i in range(nbPass):
for y in range(self.input.height-1): # on cherche le meilleur patch à droit et en bas for y in range(self.input.height-1): # on cherche le meilleur patch à droit et en bas
for x in range(self.input.width-1): for x in range(self.input.width-1):
if (self.field[y,x,2]>0): if (self.field[y,x,2]>0):
self.minimizeLink(x,y,i) self.findBestPatchFroOne(x,y,i)
for y in range(self.input.height-1,0,-1): # on cherche le meilleur patche en haut et à gauche for y in range(self.input.height-1,0,-1): # on cherche le meilleur patche en haut et à gauche
for x in range(self.input.width-1,0,-1): for x in range(self.input.width-1,0,-1):
if (self.field[y,x,2]>0): if (self.field[y,x,2]>0):
self.minimizeLink(x,y,-i) self.findBestPatchFroOne(x,y,-i)
def minimizeLink(self,x,y,direction): def findBestPatchFroOne(self,x,y,direction):
# recherche le meilleur patch pour une zone en particulier dans un sens (en haut et à gauche | à droite et en bas) + cherche random
# horizontale # horizontale
if (0<x-direction<self.input.width): if (0<x-direction<self.input.width):
xp = self.field[y,x-direction,0] +direction xp = self.field[y,x-direction,0] +direction
@ -81,10 +83,10 @@ class Nnf:
zoneRecherche = int(zoneRecherche/2) zoneRecherche = int(zoneRecherche/2)
def distance(self,x,y,xp,yp): def distance(self,x,y,xp,yp):
# simple interface # simple interface avec la function distance
return distance(self.input,x,y,self.output,xp,yp,self.patchSize) return distance(self.input,x,y,self.output,xp,yp,self.patchSize)
def distance(source, xs, ys, target, xt, yt, patchSize): def distance(source, xs, ys, target, xt, yt, patchSize): # cette function est ici et pas dans function pour éviter les import circulaire et car ce fichier est le seul qui l'utilise
# calcule la distance entre deux patch (pas la distance physique mais la distance des valeurs de leurs pixels) # calcule la distance entre deux patch (pas la distance physique mais la distance des valeurs de leurs pixels)
# en utilisant la somme des erreurs au carré # en utilisant la somme des erreurs au carré
# la valeurs maximal de cette fonction est MaskedImage.DSCALE et n'est retourné en pratique presque que quand # la valeurs maximal de cette fonction est MaskedImage.DSCALE et n'est retourné en pratique presque que quand
Loading…
Cancel
Save