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.
104 lines
4.5 KiB
104 lines
4.5 KiB
import random
|
|
import numpy as np
|
|
from maskedImage import MaskedImage
|
|
|
|
class Nnf:
|
|
def __init__(self,input,output,patchSize):
|
|
self.input = input
|
|
self.output = output
|
|
self.patchSize = patchSize
|
|
|
|
def randomize(self):
|
|
self.field = np.zeros((self.input.height, self.input.width, 3), dtype=int)
|
|
self.field[:,:,2] = MaskedImage.DSCALE
|
|
self.field[:,:,0] = np.random.randint(0,self.output.width,(self.input.height,self.input.width))
|
|
self.field[:,:,1] = np.random.randint(0,self.output.height,(self.input.height,self.input.width))
|
|
self.initialize()
|
|
|
|
def initializeFromNnf(self,nnf):
|
|
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)
|
|
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)
|
|
self.initialize()
|
|
|
|
def initialize(self):
|
|
for y in range(self.input.height):
|
|
for x in range(self.input.width):
|
|
self.field[y,x,2] = self.distance(x,y,self.field[y,x,0],self.field[y,x,1])
|
|
iter= 0
|
|
maxIter = 10
|
|
while (self.field[y,x,2] == MaskedImage.DSCALE and iter<maxIter):
|
|
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):
|
|
for i in range(nbPass):
|
|
for y in range(self.input.height-1):
|
|
for x in range(self.input.width-1):
|
|
if (self.field[y,x,2]>0):
|
|
self.minimizeLink(x,y,1)
|
|
for y in range(self.input.height-1,0,-1):
|
|
for x in range(self.input.width-1,0,-1):
|
|
if (self.field[y,x,2]>0):
|
|
self.minimizeLink(x,y,-1)
|
|
|
|
def minimizeLink(self,x,y,direction):
|
|
# horizontale
|
|
if (0<x-direction<self.input.width):
|
|
xp = self.field[y,x-direction,0] +direction
|
|
yp = self.field[y,x-direction,1]
|
|
dp = self.distance(x,y,xp,yp)
|
|
if (dp<self.field[y,x,2]):
|
|
self.field[y,x] = (xp,yp,dp)
|
|
|
|
# verticale
|
|
if (0<y-direction<self.input.height):
|
|
xp = self.field[y-direction,x,0]
|
|
yp = self.field[y-direction,x,1] + direction
|
|
dp = self.distance(x,y,xp,yp)
|
|
if (dp<self.field[y,x,2]):
|
|
self.field[y,x] = (xp,yp,dp)
|
|
|
|
# recherche random
|
|
zoneRecherche = max(self.output.height,self.output.width)
|
|
while zoneRecherche>0:
|
|
xp = self.field[y,x,0] + random.randint(0,2*zoneRecherche)-zoneRecherche
|
|
xp = self.field[y,x,1] + random.randint(0,2*zoneRecherche)-zoneRecherche
|
|
xp = max(0,min(self.output.width-1,xp))
|
|
yp = max(0,min(self.output.height-1,yp))
|
|
dp = self.distance(x,y,xp,yp)
|
|
if (dp<self.field[y,x,2]):
|
|
self.field[y,x] = (xp,yp,dp)
|
|
zoneRecherche = int(zoneRecherche/2)
|
|
|
|
def distance(self,x,y,xp,yp):
|
|
return distance(self.input,x,y,self.output,xp,yp,self.patchSize)
|
|
|
|
def distance(source, xs, ys, target, xt, yt, patchSize):
|
|
ssd_max = 255 * 255
|
|
distance, wsum = 0, ssd_max * (patchSize*2)**2
|
|
for dy in range(-patchSize, patchSize):
|
|
yks, ykt = ys + dy, yt + dy
|
|
if not (1 <= yks < source.height - 1 and 1 <= ykt < target.height - 1):
|
|
distance += ssd_max * patchSize * 2
|
|
continue
|
|
for dx in range(-patchSize, patchSize):
|
|
xks, xkt = xs + dx, xt + dx
|
|
if not (1 <= xks < source.width - 1 and 1 <= xkt < target.width - 1):
|
|
distance += ssd_max
|
|
continue
|
|
if source.containsMask(xks, yks,patchSize):
|
|
distance += ssd_max
|
|
continue
|
|
if target.containsMask(xkt, ykt,patchSize):
|
|
distance += ssd_max
|
|
continue
|
|
ssd = np.sum((source.image[yks, xks] - target.image[ykt, xkt]) ** 2)
|
|
distance += ssd
|
|
return int(MaskedImage.DSCALE * distance / wsum)
|