import numpy as np class MaskedImage: DSCALE = 10_000 # valeur arbitraire qui est le nombre max de la function de distance base = [1.0, 0.99, 0.96, 0.83, 0.38, 0.11, 0.02, 0.005, 0.0006, 0.0001, 0] similarity = np.interp(np.linspace(0, 1, DSCALE), np.linspace(0, 1, len(base)), base) # base et similarity permettent de calculer le poid à appliquer en fonction de la distance (plus la distance est grande plus le poid vas être élevé pour obtenir la prochaine fois une distance faible) def __init__(self,image=None,mask=None,width=None,height=None): # deux méthodes de création d'objet: # - à partir des dimentions # - à partir d'une image et d'un mask déjà existant if image is not None: self.image = image self.height, self.width = image.shape[:2] self.mask = mask return self.width = width self.height = height self.image = np.zeros((self.height, self.width, 3), dtype=np.uint8) self.mask = np.zeros((self.height, self.width), dtype=bool) def containsMask(self,x,y,patchSize): # renvoit vrai si le patch centrer en x,y est en partie dans le trou for dy in range(-patchSize,patchSize): if (y+dy < 0 or self.height <= y+dy): continue for dx in range(-patchSize,patchSize): if (x+dx < 0 or self.width <= x+dx): continue if self.mask[y+dy,x+dx]: return True return False def copy(self): return MaskedImage(image=self.image.copy(), mask=self.mask.copy()) def downScale(self): # réduit la qualité d'une image par deux en faisant la moyene des valeurs des pixels qui disparaisse newW, newH = self.width // 2, self.height // 2 poids = np.array([1, 5, 10, 10, 5, 1]) # poid du vote en fonction de la distance avec le centre newimage = np.zeros((newH, newW, 3), dtype=np.uint8) newmask = np.zeros((newH, newW), dtype=bool) for y in range(0, self.height - 1, 2): for x in range(0, self.width - 1, 2): r, g, b, ttP, m = 0, 0, 0, 0, 0 for dy in range(-2, 4): # faire un vote de la couleur avec toutes les pixels à deux de distance (x et/ou y) du centre yk = y + dy if (yk<0 or yk >= self.height): continue ky = poids[2 + dy] for dx in range(-2, 4): xk = x + dx if (xk<0 or xk >= self.width): continue if self.mask[yk, xk]: continue k = poids[2 + dx] * ky r += k * self.image[yk, xk, 0] # ajout du vote pour les valeurs r g et b g += k * self.image[yk, xk, 1] b += k * self.image[yk, xk, 2] ttP += k m += 1 if ttP > 0: newimage[y // 2, x // 2] = (r // ttP, g // ttP, b // ttP) # assignation aux pixels de la moyenne pondéré des voisines newmask[y // 2, x // 2] = False else: newmask[y // 2, x // 2] = True return MaskedImage(image=newimage, mask=newmask) def upScale(self, newH, newW): # renvoit une nouvelle image aux bonnes dimentions y_indices = np.floor(np.linspace(0, self.height-1, newH)).astype(int) x_indices = np.floor(np.linspace(0, self.width-1, newW)).astype(int) y_coords, x_coords = np.meshgrid(y_indices, x_indices, indexing='ij') newImage = MaskedImage(width=newW, height=newH) newImage.image = self.image[y_coords, x_coords] newImage.mask = self.mask[y_coords, x_coords] return newImage