You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
3.9 KiB
81 lines
3.9 KiB
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
|