commentaire

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

@ -1,10 +1,10 @@
from maskedImage import MaskedImage
import matplotlib.pyplot as plt
from nnf import Nnf
import concurrent.futures
from imageRelation import ImageRelation
import numpy as np
import cv2
import concurrent.futures
def read(file):
# fonction qui renvoit une image à partir de son chemin
@ -19,7 +19,7 @@ def doTheInpainting(img,mask,radius):
def maximizeForTheScale(scale):
# fonction interne qui effectue l'impainting pour une version réduite de l'image
iterEM = 1+2*scale
iterNnf = min(7,1+scale)
npPass = min(7,1+scale)
source = sourceToTarget.input
target = targetToSource.output
newTarget = None
@ -34,7 +34,7 @@ def doTheInpainting(img,mask,radius):
if not source.containsMask(x,y,radius):
targetToSource.field[y,x] = (x,y,0)
# on cherche les patchs
targetToSource.minimize(iterNnf)
targetToSource.findBestPatch(npPass)
# on crée la source et la target
upscaled = False
if scale>=1 and emloop == iterEM:
@ -67,45 +67,45 @@ def doTheInpainting(img,mask,radius):
if (level == maxLevel-1):
target = source.copy()
target.mask[0:target.height,0:target.width] = False
sourceToTarget = Nnf(source,target,radius)
sourceToTarget = ImageRelation(source,target,radius)
sourceToTarget.randomize()
targetToSource = Nnf(target,source,radius)
targetToSource = ImageRelation(target,source,radius)
targetToSource.randomize()
else:
newNnf = Nnf(source,target,radius)
newNnf.initializeFromNnf(sourceToTarget)
sourceToTarget = newNnf
newImRel = ImageRelation(source,target,radius)
newImRel.initializeFromImageRelation(sourceToTarget)
sourceToTarget = newImRel
newNnfRev = Nnf(target,source,radius)
newNnfRev.initializeFromNnf(targetToSource)
targetToSource = newNnfRev
newImRelRev = ImageRelation(target,source,radius)
newImRelRev.initializeFromImageRelation(targetToSource)
targetToSource = newImRelRev
target, sourceToTarget, targetToSource = maximizeForTheScale(level)
plt.imshow(target.image)
plt.pause(0.01)
return target.image
def ExpectationStep(nnf, vote, source, upscale):
def ExpectationStep(imRel, vote, source, upscale):
def ExpectationStepForNb(nb):
# ajoute au vote pour toutes les pixels les valeurs déterminé lors de la recherche des patchs
wid = nnf.input.width//7
for y in range(nnf.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
xp, yp, dp = nnf.field[y,x]
wid = imRel.input.width//7
for y in range(imRel.input.height):
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 = imRel.field[y,x]
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
if not 0<=ys<nnf.input.height:
if not 0<=ys<imRel.input.height:
continue
yt = y+dy
if not 0<=yt<nnf.input.height:
if not 0<=yt<imRel.input.height:
continue
for dx in range(-nnf.patchSize,nnf.patchSize):
for dx in range(-imRel.patchSize,imRel.patchSize):
xs = xp+dx
if not 0<=xs<nnf.input.width:
if not 0<=xs<imRel.input.width:
continue
xt = x+dx
if not 0<=xt<nnf.input.width:
if not 0<=xt<imRel.input.width:
continue
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)

@ -1,8 +1,8 @@
import random
import numpy as np
from maskedImage import MaskedImage
import numpy as np
import random
class Nnf:
class ImageRelation:
def __init__(self,input,output,patchSize):
self.input = input
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.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
self.field = np.zeros((self.input.height, self.input.width, 3), dtype=int)
fx = int(self.input.width/nnf.input.width)
fy = int(self.input.height/nnf.input.height)
fx = int(self.input.width/imRel.input.width)
fy = int(self.input.height/imRel.input.height)
for y in range(self.input.height):
for x in range(self.input.width):
xl = min(int(x/fx),nnf.input.width-1)
yl = min(int(y/fy),nnf.input.height-1)
self.field[y,x] = (nnf.field[yl,xl,0]*fx, nnf.field[yl,xl,1]*fy, MaskedImage.DSCALE)
xl = min(int(x/fx),imRel.input.width-1)
yl = min(int(y/fy),imRel.input.height-1)
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
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]))
iter += 1
def minimize(self,nbPass):
def findBestPatch(self,nbPass):
# recherche les meilleurs patch pour toutes les zones
for i in range(nbPass):
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):
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 x in range(self.input.width-1,0,-1):
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
if (0<x-direction<self.input.width):
xp = self.field[y,x-direction,0] +direction
@ -81,10 +83,10 @@ class Nnf:
zoneRecherche = int(zoneRecherche/2)
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)
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)
# 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
Loading…
Cancel
Save