Initial commit
This commit is contained in:
parent
83414655b0
commit
756b0a190a
5 changed files with 2340 additions and 0 deletions
505
Apprentissage_MSELoss_avec_GPU.ipynb
Executable file
505
Apprentissage_MSELoss_avec_GPU.ipynb
Executable file
File diff suppressed because one or more lines are too long
424
Apprentissage_MSELoss_avec_GPU.py
Normal file
424
Apprentissage_MSELoss_avec_GPU.py
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
# In[1]:
|
||||||
|
|
||||||
|
|
||||||
|
#Tous les codes sont basés sur l'environnement suivant
|
||||||
|
#python 3.7
|
||||||
|
#opencv 3.1.0
|
||||||
|
#pytorch 1.4.0
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from torch.autograd import Variable
|
||||||
|
import torch.nn as nn
|
||||||
|
import torch.nn.functional as F
|
||||||
|
import cv2
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import random
|
||||||
|
import math
|
||||||
|
import pickle
|
||||||
|
import random
|
||||||
|
from PIL import Image
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# In[3]:
|
||||||
|
|
||||||
|
|
||||||
|
#Les fonctions dans ce bloc ne sont pas utilisées par le réseau, mais certaines fonctions d'outils
|
||||||
|
|
||||||
|
|
||||||
|
def tensor_imshow(im_tensor,cannel):
|
||||||
|
b,c,h,w=im_tensor.shape
|
||||||
|
if c==1:
|
||||||
|
plt.imshow(im_tensor.squeeze().detach().numpy())
|
||||||
|
else:
|
||||||
|
plt.imshow(im_tensor.squeeze().detach().numpy()[cannel,:])
|
||||||
|
|
||||||
|
# Obtenez des données d'entraînement
|
||||||
|
# frag,vt=get_training_fragment(frag_size,image)
|
||||||
|
# frag est un patch carrée de taille (frag_size*frag_size) a partir du image(Son emplacement est aléatoire)
|
||||||
|
# vt est la vérité terrain de la forme Dirac.
|
||||||
|
def get_training_fragment(frag_size,im):
|
||||||
|
h,w,c=im.shape
|
||||||
|
n=random.randint(0,int(h/frag_size)-1)
|
||||||
|
m=random.randint(0,int(w/frag_size)-1)
|
||||||
|
shape=frag_size/4
|
||||||
|
vt_h=math.ceil((h+1)/shape)
|
||||||
|
vt_w=math.ceil((w+1)/shape)
|
||||||
|
vt=np.zeros([vt_h,vt_w])
|
||||||
|
vt_h_po=round((vt_h-1)*(n*frag_size/(h-1)+(n+1)*frag_size/(h-1))/2)
|
||||||
|
vt_w_po=round((vt_w-1)*(m*frag_size/(w-1)+(m+1)*frag_size/(w-1))/2)
|
||||||
|
vt[vt_h_po,vt_w_po]=1
|
||||||
|
vt = np.float32(vt)
|
||||||
|
vt=torch.from_numpy(vt.reshape(1,1,vt_h,vt_w))
|
||||||
|
|
||||||
|
return im[n*frag_size:(n+1)*frag_size,m*frag_size:(m+1)*frag_size,:],vt
|
||||||
|
|
||||||
|
# Cette fonction convertit l'image en variable de type Tensor.
|
||||||
|
# Toutes les données de calcul du réseau sont de type Tensor
|
||||||
|
# Img.shape=[Height,Width,Channel]
|
||||||
|
# Tensor.shape=[Batch,Channel,Height,Width]
|
||||||
|
def img2tensor(im):
|
||||||
|
im=np.array(im,dtype="float32")
|
||||||
|
tensor_cv = torch.from_numpy(np.transpose(im, (2, 0, 1)))
|
||||||
|
im_tensor=tensor_cv.unsqueeze(0)
|
||||||
|
return im_tensor
|
||||||
|
|
||||||
|
# Trouvez les coordonnées de la valeur maximale dans une carte de corrélation
|
||||||
|
# x,y=show_coordonnee(carte de corrélation)
|
||||||
|
def show_coordonnee(position_pred):
|
||||||
|
map_corre=position_pred.squeeze().detach().numpy()
|
||||||
|
h,w=map_corre.shape
|
||||||
|
max_value=map_corre.max()
|
||||||
|
coordonnee=np.where(map_corre==max_value)
|
||||||
|
return coordonnee[0].mean()/h,coordonnee[1].mean()/w
|
||||||
|
|
||||||
|
# Filtrer les patchs en fonction du nombre de pixels noirs dans le patch
|
||||||
|
# Si seuls les pixels non noirs sont plus grands qu'une certaine proportion(seuillage), revenez à True, sinon False
|
||||||
|
def test_fragment32_32(frag,seuillage):
|
||||||
|
a=frag[:,:,0]+frag[:,:,1]+frag[:,:,2]
|
||||||
|
mask = (a == 0)
|
||||||
|
arr_new = a[mask]
|
||||||
|
if arr_new.size/a.size<=(1-seuillage):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Ces deux fonctions permettent de sauvegarder le réseau dans un fichier
|
||||||
|
# ou de load le réseau stocké à partir d'un fichier
|
||||||
|
def save_net(file_path,net):
|
||||||
|
pkl_file = open(file_path, 'wb')
|
||||||
|
pickle.dump(net,pkl_file)
|
||||||
|
pkl_file.close()
|
||||||
|
def load_net(file_path):
|
||||||
|
pkl_file = open(file_path, 'rb')
|
||||||
|
net= pickle.load(pkl_file)
|
||||||
|
pkl_file.close()
|
||||||
|
return net
|
||||||
|
|
||||||
|
|
||||||
|
# In[4]:
|
||||||
|
|
||||||
|
|
||||||
|
# Les fonctions de ce bloc sont utilisées pour construire le réseau
|
||||||
|
|
||||||
|
# Créer un poids de type DeepMatch comme valeur initiale de Conv1 (non obligatoire)
|
||||||
|
def ini():
|
||||||
|
kernel=torch.zeros([8,3,3,3])
|
||||||
|
array_0=np.array([[1,2,1],[0,0,0],[-1,-2,-1]],dtype='float32')
|
||||||
|
array_1=np.array([[2,1,0],[1,0,-1],[0,-1,-2]],dtype='float32')
|
||||||
|
array_2=np.array([[1,0,-1],[2,0,-2],[1,0,-1]],dtype='float32')
|
||||||
|
array_3=np.array([[0,-1,-2],[1,0,-1],[2,1,0]],dtype='float32')
|
||||||
|
array_4=np.array([[-1,-2,-1],[0,0,0],[1,2,1]],dtype='float32')
|
||||||
|
array_5=np.array([[-2,-1,0],[-1,0,1],[0,1,2]],dtype='float32')
|
||||||
|
array_6=np.array([[-1,0,1],[-2,0,2],[-1,0,1]],dtype='float32')
|
||||||
|
array_7=np.array([[0,1,2],[-1,0,1],[-2,-1,0]],dtype='float32')
|
||||||
|
for i in range(3):
|
||||||
|
kernel[0,i,:]=torch.from_numpy(array_0)
|
||||||
|
kernel[1,i,:]=torch.from_numpy(array_1)
|
||||||
|
kernel[2,i,:]=torch.from_numpy(array_2)
|
||||||
|
kernel[3,i,:]=torch.from_numpy(array_3)
|
||||||
|
kernel[4,i,:]=torch.from_numpy(array_4)
|
||||||
|
kernel[5,i,:]=torch.from_numpy(array_5)
|
||||||
|
kernel[6,i,:]=torch.from_numpy(array_6)
|
||||||
|
kernel[7,i,:]=torch.from_numpy(array_7)
|
||||||
|
return torch.nn.Parameter(kernel,requires_grad=True)
|
||||||
|
|
||||||
|
# Calculer le poids initial de la couche convolutive add
|
||||||
|
# n, m signifie qu'il y a n * m sous-patches dans le patch d'entrée
|
||||||
|
# Par exemple, le patch d'entrée est 16 * 16, pour les patchs 4 * 4 de la première couche, n = 4, m = 4
|
||||||
|
# pour les patchs 8 * 8 de la deuxième couche, n = 2, m = 2
|
||||||
|
def kernel_add_ini(n,m):
|
||||||
|
input_canal=int(n*m)
|
||||||
|
output_canal=int(n/2)*int(m/2)
|
||||||
|
for i in range(int(n/2)):
|
||||||
|
for j in range(int(m/2)):
|
||||||
|
kernel_add=np.zeros([1,input_canal],dtype='float32')
|
||||||
|
kernel_add[0,i*2*m+j*2]=1
|
||||||
|
kernel_add[0,i*2*m+j*2+1]=1
|
||||||
|
kernel_add[0,(i*2+1)*m+j*2]=1
|
||||||
|
kernel_add[0,(i*2+1)*m+j*2+1]=1
|
||||||
|
if i==0 and j==0:
|
||||||
|
add=torch.from_numpy(kernel_add.reshape(1,input_canal,1,1))
|
||||||
|
else:
|
||||||
|
add_=torch.from_numpy(kernel_add.reshape(1,input_canal,1,1))
|
||||||
|
add=torch.cat((add,add_),0)
|
||||||
|
return torch.nn.Parameter(add,requires_grad=False)
|
||||||
|
|
||||||
|
# Calculer le poids initial de la couche convolutive shift
|
||||||
|
# shift+add Peut réaliser l'étape de l'agrégation
|
||||||
|
# Voir ci-dessus pour les paramètres n et m.
|
||||||
|
# Pour des étapes plus détaillées, veuillez consulter mon rapport de stage
|
||||||
|
def kernel_shift_ini(n,m):
|
||||||
|
input_canal=int(n*m)
|
||||||
|
output_canal=int(n*m)
|
||||||
|
|
||||||
|
kernel_shift=torch.zeros([output_canal,input_canal,3,3])
|
||||||
|
|
||||||
|
array_0=np.array([[1,0,0],[0,0,0],[0,0,0]],dtype='float32')
|
||||||
|
array_1=np.array([[0,0,1],[0,0,0],[0,0,0]],dtype='float32')
|
||||||
|
array_2=np.array([[0,0,0],[0,0,0],[1,0,0]],dtype='float32')
|
||||||
|
array_3=np.array([[0,0,0],[0,0,0],[0,0,1]],dtype='float32')
|
||||||
|
|
||||||
|
kernel_shift_0=torch.from_numpy(array_0)
|
||||||
|
kernel_shift_1=torch.from_numpy(array_1)
|
||||||
|
kernel_shift_2=torch.from_numpy(array_2)
|
||||||
|
kernel_shift_3=torch.from_numpy(array_3)
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(m):
|
||||||
|
if i==0 and j==0:
|
||||||
|
kernel_shift[0,0,:]=kernel_shift_0
|
||||||
|
else:
|
||||||
|
if i%2==0 and j%2==0:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_0
|
||||||
|
if i%2==0 and j%2==1:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_1
|
||||||
|
if i%2==1 and j%2==0:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_2
|
||||||
|
if i%2==1 and j%2==1:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_3
|
||||||
|
|
||||||
|
return torch.nn.Parameter(kernel_shift,requires_grad=False)
|
||||||
|
|
||||||
|
# Trouvez le petit patch(4 * 4) dans la n ème ligne et la m ème colonne du patch d'entrée
|
||||||
|
# Ceci est utilisé pour calculer la convolution et obtenir la carte de corrélation
|
||||||
|
def get_patch(fragment,psize,n,m):
|
||||||
|
return fragment[:,:,n*psize:(n+1)*psize,m*psize:(m+1)*psize]
|
||||||
|
###################################################################################################################
|
||||||
|
class Net(nn.Module):
|
||||||
|
def __init__(self,frag_size,psize):
|
||||||
|
super(Net, self).__init__()
|
||||||
|
|
||||||
|
h_fr=frag_size
|
||||||
|
w_fr=frag_size
|
||||||
|
|
||||||
|
n=int(h_fr/psize) # n*m patches dans le patch d'entrée
|
||||||
|
m=int(w_fr/psize)
|
||||||
|
|
||||||
|
self.conv1 = nn.Conv2d(3,8,kernel_size=3,stride=1,padding=1)
|
||||||
|
# Si vous souhaitez initialiser Conv1 avec les poids de DeepMatch, exécutez la ligne suivante
|
||||||
|
# self.conv1.weight=ini()
|
||||||
|
self.Relu = nn.ReLU(inplace=True)
|
||||||
|
self.maxpooling=nn.MaxPool2d(3,stride=2, padding=1)
|
||||||
|
|
||||||
|
self.shift1=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)
|
||||||
|
self.shift1.weight=kernel_shift_ini(n,m)
|
||||||
|
self.add1 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)
|
||||||
|
self.add1.weight=kernel_add_ini(n,m)
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:# Si n=m=1,Notre réseau n'a plus besoin de plus de couches pour agréger les cartes de corrélation
|
||||||
|
self.shift2=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)
|
||||||
|
self.shift2.weight=kernel_shift_ini(n,m)
|
||||||
|
self.add2 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)
|
||||||
|
self.add2.weight=kernel_add_ini(n,m)
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
self.shift3=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)
|
||||||
|
self.shift3.weight=kernel_shift_ini(n,m)
|
||||||
|
self.add3 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)
|
||||||
|
self.add3.weight=kernel_add_ini(n,m)
|
||||||
|
|
||||||
|
def get_descripteur(self,img,using_cuda):
|
||||||
|
# Utilisez Conv1 pour calculer le descripteur,
|
||||||
|
descripteur_img=self.Relu(self.conv1(img))
|
||||||
|
b,c,h,w=descripteur_img.shape
|
||||||
|
couche_constante=0.5*torch.ones([1,1,h,w])
|
||||||
|
if using_cuda:
|
||||||
|
couche_constante=couche_constante.cuda()
|
||||||
|
# Ajouter une couche constante pour éviter la division par 0 lors de la normalisation
|
||||||
|
descripteur_img=torch.cat((descripteur_img,couche_constante),1)
|
||||||
|
# la normalisation
|
||||||
|
descripteur_img_norm=descripteur_img/torch.norm(descripteur_img,dim=1)
|
||||||
|
return descripteur_img_norm
|
||||||
|
|
||||||
|
def forward(self,img,frag,using_cuda):
|
||||||
|
psize=4
|
||||||
|
# Utilisez Conv1 pour calculer le descripteur,
|
||||||
|
descripteur_input1=self.get_descripteur(img,using_cuda)
|
||||||
|
descripteur_input2=self.get_descripteur(frag,using_cuda)
|
||||||
|
|
||||||
|
b,c,h,w=frag.shape
|
||||||
|
n=int(h/psize)
|
||||||
|
m=int(w/psize)
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Calculer la carte de corrélation par convolution pour les n*m patchs plus petit.
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(m):
|
||||||
|
if i==0 and j==0:
|
||||||
|
map_corre=F.conv2d(descripteur_input1,get_patch(descripteur_input2,psize,i,j),padding=2)
|
||||||
|
else:
|
||||||
|
a=F.conv2d(descripteur_input1,get_patch(descripteur_input2,psize,i,j),padding=2)
|
||||||
|
map_corre=torch.cat((map_corre,a),1)
|
||||||
|
########################################
|
||||||
|
# Étape de polymérisation
|
||||||
|
map_corre=self.maxpooling(map_corre)
|
||||||
|
map_corre=self.shift1(map_corre)
|
||||||
|
map_corre=self.add1(map_corre)
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Répétez l'étape d'agrégation jusqu'à obtenir le graphique de corrélation du patch d'entrée
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
map_corre=self.maxpooling(map_corre)
|
||||||
|
map_corre=self.shift2(map_corre)
|
||||||
|
map_corre=self.add2(map_corre)
|
||||||
|
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
map_corre=self.maxpooling(map_corre)
|
||||||
|
map_corre=self.shift3(map_corre)
|
||||||
|
map_corre=self.add3(map_corre)
|
||||||
|
|
||||||
|
|
||||||
|
b,c,h,w=map_corre.shape
|
||||||
|
# Normalisation de la division par maximum
|
||||||
|
map_corre=map_corre/(map_corre.max())
|
||||||
|
# Normalisation SoftMax
|
||||||
|
#map_corre=(F.softmax(map_corre.reshape(1,1,h*w,1),dim=2)).reshape(b,c,h,w)
|
||||||
|
return map_corre
|
||||||
|
|
||||||
|
|
||||||
|
# In[5]:
|
||||||
|
|
||||||
|
|
||||||
|
def run_net(net,img,frag,frag_size,using_cuda):
|
||||||
|
h,w,c=frag.shape
|
||||||
|
n=int(h/frag_size)
|
||||||
|
m=int(w/frag_size)
|
||||||
|
frag_list=[]
|
||||||
|
#####################################
|
||||||
|
# Obtenez des patchs carrés des fragments et mettez-les dans la frag_list
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(m):
|
||||||
|
frag_32=frag[i*frag_size:(i+1)*frag_size,j*frag_size:(j+1)*frag_size]
|
||||||
|
if test_fragment32_32(frag_32,0.6):
|
||||||
|
frag_list.append(frag_32)
|
||||||
|
img_tensor=img2tensor(img)
|
||||||
|
######################################
|
||||||
|
if using_cuda:
|
||||||
|
img_tensor=img_tensor.cuda()
|
||||||
|
|
||||||
|
coordonnee_list=[]
|
||||||
|
#######################################
|
||||||
|
# Utilisez le réseau pour calculer les positions de tous les patchs dans frag_list[]
|
||||||
|
# Mettez le résultat du calcul dans coordonnee_list[]
|
||||||
|
for i in range(len(frag_list)):
|
||||||
|
frag_tensor=img2tensor(frag_list[i])
|
||||||
|
if using_cuda:
|
||||||
|
frag_tensor=frag_tensor.cuda()
|
||||||
|
res=net.forward(img_tensor,frag_tensor,using_cuda)
|
||||||
|
if using_cuda:
|
||||||
|
res=res.cpu()
|
||||||
|
po_h,po_w=show_coordonnee(res)
|
||||||
|
coordonnee_list.append([po_h,po_w])
|
||||||
|
h_img,w_img,c=img.shape
|
||||||
|
position=[]
|
||||||
|
for i in range(len(coordonnee_list)):
|
||||||
|
x=int(round(h_img*coordonnee_list[i][0]))
|
||||||
|
y=int(round(w_img*coordonnee_list[i][1]))
|
||||||
|
position.append([x,y])
|
||||||
|
return position
|
||||||
|
|
||||||
|
|
||||||
|
# In[10]:
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
|
||||||
|
# La taille du patch d'entrée est de 16*16
|
||||||
|
frag_size=16
|
||||||
|
# La taille du plus petit patch dans réseau est de 4 *4 fixée
|
||||||
|
psize=4
|
||||||
|
using_cuda=True
|
||||||
|
|
||||||
|
|
||||||
|
net=Net(frag_size,psize)
|
||||||
|
|
||||||
|
# Pour chaque fresque, le nombre d'itérations est de 1000
|
||||||
|
itera=1000
|
||||||
|
|
||||||
|
if using_cuda:
|
||||||
|
net=net.cuda()
|
||||||
|
|
||||||
|
# Choisissez l'optimiseur et la fonction de coût
|
||||||
|
optimizer = torch.optim.Adam(net.parameters())
|
||||||
|
loss_func = torch.nn.MSELoss()
|
||||||
|
|
||||||
|
# Dans le processus d'apprentissage du réseau,le changement d'erreur est placé dans loss_value=[]
|
||||||
|
# et le changement de Conv1 poids est placé dans para_value[]
|
||||||
|
loss_value=[]
|
||||||
|
para_value=[]
|
||||||
|
####################################################training_net
|
||||||
|
|
||||||
|
#Les données d'entraînement sont 6 fresques
|
||||||
|
for n in range(6):
|
||||||
|
im_path="./fresque"+str(n)+".ppm"
|
||||||
|
img_training=cv2.imread(im_path)
|
||||||
|
h,w,c=img_training.shape
|
||||||
|
|
||||||
|
# Si la peinture murale est trop grande, sous-échantillonnez-la et rétrécissez-la
|
||||||
|
while h*w>(1240*900):
|
||||||
|
img_training=cv2.resize(img_training,(int(h/2),int(w/2)),interpolation=cv2.INTER_CUBIC)
|
||||||
|
h,w,c=img_training.shape
|
||||||
|
im_tensor=img2tensor(img_training)
|
||||||
|
|
||||||
|
if using_cuda:
|
||||||
|
im_tensor=im_tensor.cuda()
|
||||||
|
for i in range(itera):
|
||||||
|
# Tous les 100 cycles, enregistrez le changement de poids
|
||||||
|
if i%100==0:
|
||||||
|
para=net.conv1.weight
|
||||||
|
para=para.detach().cpu()
|
||||||
|
para_value.append(para)
|
||||||
|
frag,vt=get_training_fragment(frag_size,img_training)
|
||||||
|
frag_tensor=img2tensor(frag)
|
||||||
|
if using_cuda:
|
||||||
|
vt=vt.cuda()
|
||||||
|
frag_tensor=frag_tensor.cuda()
|
||||||
|
# Utilisez des patchs et des fresques de données d'entraînement pour faire fonctionner le réseau
|
||||||
|
frag_pred=net.forward(im_tensor,frag_tensor,using_cuda)
|
||||||
|
b,c,h,w=vt.shape
|
||||||
|
# Utilisez la fonction de coût pour calculer l'erreur
|
||||||
|
err_=loss_func(vt,frag_pred)
|
||||||
|
# Utilisez l'optimiseur pour ajuster le poids de Conv1
|
||||||
|
optimizer.zero_grad()
|
||||||
|
err_.backward(retain_graph=True)
|
||||||
|
optimizer.step()
|
||||||
|
|
||||||
|
loss_value.append(err_.tolist())
|
||||||
|
|
||||||
|
del frag_tensor,frag_pred,err_,vt
|
||||||
|
torch.cuda.empty_cache()
|
||||||
|
|
||||||
|
|
||||||
|
# In[7]:
|
||||||
|
|
||||||
|
|
||||||
|
len(loss_value)
|
||||||
|
|
||||||
|
|
||||||
|
# In[11]:
|
||||||
|
|
||||||
|
|
||||||
|
plt.plot(loss_value)
|
||||||
|
|
||||||
|
|
||||||
|
# In[12]:
|
||||||
|
|
||||||
|
|
||||||
|
file_path="./net_trainned6000"
|
||||||
|
save_net(file_path,net)
|
||||||
|
|
871
Frag_Match_avec_rotation.ipynb
Executable file
871
Frag_Match_avec_rotation.ipynb
Executable file
|
@ -0,0 +1,871 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#Tous les codes sont basés sur l'environnement suivant\n",
|
||||||
|
"#python 3.7\n",
|
||||||
|
"#opencv 3.1.0\n",
|
||||||
|
"#pytorch 1.4.0\n",
|
||||||
|
"\n",
|
||||||
|
"import torch\n",
|
||||||
|
"from torch.autograd import Variable\n",
|
||||||
|
"import torch.nn as nn\n",
|
||||||
|
"import torch.nn.functional as F\n",
|
||||||
|
"import cv2\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import random\n",
|
||||||
|
"import math\n",
|
||||||
|
"import pickle\n",
|
||||||
|
"import random\n",
|
||||||
|
"from PIL import Image\n",
|
||||||
|
"import sys"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Les fonctions dans ce bloc ne sont pas utilisées par le réseau, mais certaines fonctions d'outils\n",
|
||||||
|
"\n",
|
||||||
|
"# Les fonctions de ce bloc se trouvent dans le programme d'apprentissage \n",
|
||||||
|
"# “Apprentissage_MSELoss_avec_GPU“\n",
|
||||||
|
"# et les commentaires détaillés se trouvent dans le programme d'apprentissage\n",
|
||||||
|
"\n",
|
||||||
|
"def tensor_imshow(im_tensor,cannel):\n",
|
||||||
|
" b,c,h,w=im_tensor.shape\n",
|
||||||
|
" if c==1:\n",
|
||||||
|
" plt.imshow(im_tensor.squeeze().detach().numpy())\n",
|
||||||
|
" else:\n",
|
||||||
|
" plt.imshow(im_tensor.squeeze().detach().numpy()[cannel,:])\n",
|
||||||
|
" \n",
|
||||||
|
"def get_training_fragment(frag_size,im):\n",
|
||||||
|
" h,w,c=im.shape\n",
|
||||||
|
" n=random.randint(0,int(h/frag_size)-1)\n",
|
||||||
|
" m=random.randint(0,int(w/frag_size)-1)\n",
|
||||||
|
" \n",
|
||||||
|
" shape=frag_size/4\n",
|
||||||
|
" vt_h=math.ceil((h+1)/shape)\n",
|
||||||
|
" vt_w=math.ceil((w+1)/shape)\n",
|
||||||
|
" vt=np.zeros([vt_h,vt_w])\n",
|
||||||
|
" vt_h_po=round((vt_h-1)*(n*frag_size/(h-1)+(n+1)*frag_size/(h-1))/2)\n",
|
||||||
|
" vt_w_po=round((vt_w-1)*(m*frag_size/(w-1)+(m+1)*frag_size/(w-1))/2)\n",
|
||||||
|
" vt[vt_h_po,vt_w_po]=1\n",
|
||||||
|
" vt = np.float32(vt)\n",
|
||||||
|
" vt=torch.from_numpy(vt.reshape(1,1,vt_h,vt_w))\n",
|
||||||
|
" \n",
|
||||||
|
" return im[n*frag_size:(n+1)*frag_size,m*frag_size:(m+1)*frag_size,:],vt\n",
|
||||||
|
"\n",
|
||||||
|
"def write_result_in_file(result,file_name):\n",
|
||||||
|
" n=0\n",
|
||||||
|
" with open(file_name,'w') as file:\n",
|
||||||
|
" for i in range(len(result)):\n",
|
||||||
|
" while n<result[i][0]:\n",
|
||||||
|
" s=str(n)\n",
|
||||||
|
" n=n+1\n",
|
||||||
|
" s=s+\"\\n\"\n",
|
||||||
|
" file.write(s)\n",
|
||||||
|
" s=str(result[i][0])+\" \"+str(result[i][1])+\" \"+str(result[i][2])+\" \"+str(result[i][3])\n",
|
||||||
|
" s=s+\"\\n\"\n",
|
||||||
|
" n=n+1\n",
|
||||||
|
" file.write(s)\n",
|
||||||
|
" file.close()\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
"def img2tensor(im):\n",
|
||||||
|
" im=np.array(im,dtype=\"float32\")\n",
|
||||||
|
" tensor_cv = torch.from_numpy(np.transpose(im, (2, 0, 1)))\n",
|
||||||
|
" im_tensor=tensor_cv.unsqueeze(0)\n",
|
||||||
|
" return im_tensor\n",
|
||||||
|
"\n",
|
||||||
|
"def show_coordonnee(position_pred):\n",
|
||||||
|
" map_corre=position_pred.squeeze().detach().numpy()\n",
|
||||||
|
" score=sum(sum(map_corre))\n",
|
||||||
|
" h,w=map_corre.shape\n",
|
||||||
|
" max_value=map_corre.max()\n",
|
||||||
|
" coordonnee=np.where(map_corre==max_value)\n",
|
||||||
|
" return score,coordonnee[0].mean()/h,coordonnee[1].mean()/w\n",
|
||||||
|
"\n",
|
||||||
|
"def test_fragment32_32(frag,seuillage):\n",
|
||||||
|
" a=frag[:,:,0]+frag[:,:,1]+frag[:,:,2]\n",
|
||||||
|
" mask = (a == 0)\n",
|
||||||
|
" arr_new = a[mask]\n",
|
||||||
|
" if arr_new.size/a.size<=(1-seuillage):\n",
|
||||||
|
" return True\n",
|
||||||
|
" else:\n",
|
||||||
|
" return False\n",
|
||||||
|
"\n",
|
||||||
|
"def save_net(file_path,net):\n",
|
||||||
|
" pkl_file = open(file_path, 'wb')\n",
|
||||||
|
" pickle.dump(net,pkl_file)\n",
|
||||||
|
" pkl_file.close()\n",
|
||||||
|
" \n",
|
||||||
|
"def load_net(file_path): \n",
|
||||||
|
" pkl_file = open(file_path, 'rb')\n",
|
||||||
|
" net= pickle.load(pkl_file)\n",
|
||||||
|
" pkl_file.close()\n",
|
||||||
|
" return net"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Les fonctions de ce bloc sont utilisées pour construire le réseau\n",
|
||||||
|
"\n",
|
||||||
|
"# Les fonctions de ce bloc se trouvent dans le programme d'apprentissage \n",
|
||||||
|
"# “Apprentissage_MSELoss_avec_GPU“\n",
|
||||||
|
"# et les commentaires détaillés se trouvent dans le programme d'apprentissage\n",
|
||||||
|
"\n",
|
||||||
|
"def ini():\n",
|
||||||
|
" kernel=torch.zeros([8,3,3,3])\n",
|
||||||
|
" array_0=np.array([[1,2,1],[0,0,0],[-1,-2,-1]],dtype='float32')\n",
|
||||||
|
" array_1=np.array([[2,1,0],[1,0,-1],[0,-1,-2]],dtype='float32')\n",
|
||||||
|
" array_2=np.array([[1,0,-1],[2,0,-2],[1,0,-1]],dtype='float32')\n",
|
||||||
|
" array_3=np.array([[0,-1,-2],[1,0,-1],[2,1,0]],dtype='float32')\n",
|
||||||
|
" array_4=np.array([[-1,-2,-1],[0,0,0],[1,2,1]],dtype='float32')\n",
|
||||||
|
" array_5=np.array([[-2,-1,0],[-1,0,1],[0,1,2]],dtype='float32')\n",
|
||||||
|
" array_6=np.array([[-1,0,1],[-2,0,2],[-1,0,1]],dtype='float32')\n",
|
||||||
|
" array_7=np.array([[0,1,2],[-1,0,1],[-2,-1,0]],dtype='float32')\n",
|
||||||
|
" for i in range(3):\n",
|
||||||
|
" kernel[0,i,:]=torch.from_numpy(array_0)\n",
|
||||||
|
" kernel[1,i,:]=torch.from_numpy(array_1)\n",
|
||||||
|
" kernel[2,i,:]=torch.from_numpy(array_2)\n",
|
||||||
|
" kernel[3,i,:]=torch.from_numpy(array_3)\n",
|
||||||
|
" kernel[4,i,:]=torch.from_numpy(array_4)\n",
|
||||||
|
" kernel[5,i,:]=torch.from_numpy(array_5)\n",
|
||||||
|
" kernel[6,i,:]=torch.from_numpy(array_6)\n",
|
||||||
|
" kernel[7,i,:]=torch.from_numpy(array_7)\n",
|
||||||
|
" return torch.nn.Parameter(kernel,requires_grad=True) \n",
|
||||||
|
"\n",
|
||||||
|
"def kernel_add_ini(n,m):\n",
|
||||||
|
" input_canal=int(n*m)\n",
|
||||||
|
" output_canal=int(n/2)*int(m/2)\n",
|
||||||
|
" for i in range(int(n/2)):\n",
|
||||||
|
" for j in range(int(m/2)):\n",
|
||||||
|
" kernel_add=np.zeros([1,input_canal],dtype='float32')\n",
|
||||||
|
" kernel_add[0,i*2*m+j*2]=1\n",
|
||||||
|
" kernel_add[0,i*2*m+j*2+1]=1\n",
|
||||||
|
" kernel_add[0,(i*2+1)*m+j*2]=1\n",
|
||||||
|
" kernel_add[0,(i*2+1)*m+j*2+1]=1\n",
|
||||||
|
" if i==0 and j==0:\n",
|
||||||
|
" add=torch.from_numpy(kernel_add.reshape(1,input_canal,1,1))\n",
|
||||||
|
" else:\n",
|
||||||
|
" add_=torch.from_numpy(kernel_add.reshape(1,input_canal,1,1))\n",
|
||||||
|
" add=torch.cat((add,add_),0)\n",
|
||||||
|
" return torch.nn.Parameter(add,requires_grad=False) \n",
|
||||||
|
"\n",
|
||||||
|
"def kernel_shift_ini(n,m):\n",
|
||||||
|
" input_canal=int(n*m)\n",
|
||||||
|
" output_canal=int(n*m)\n",
|
||||||
|
" \n",
|
||||||
|
" kernel_shift=torch.zeros([output_canal,input_canal,3,3])\n",
|
||||||
|
" \n",
|
||||||
|
" array_0=np.array([[1,0,0],[0,0,0],[0,0,0]],dtype='float32')\n",
|
||||||
|
" array_1=np.array([[0,0,1],[0,0,0],[0,0,0]],dtype='float32')\n",
|
||||||
|
" array_2=np.array([[0,0,0],[0,0,0],[1,0,0]],dtype='float32')\n",
|
||||||
|
" array_3=np.array([[0,0,0],[0,0,0],[0,0,1]],dtype='float32')\n",
|
||||||
|
" \n",
|
||||||
|
" kernel_shift_0=torch.from_numpy(array_0)\n",
|
||||||
|
" kernel_shift_1=torch.from_numpy(array_1)\n",
|
||||||
|
" kernel_shift_2=torch.from_numpy(array_2)\n",
|
||||||
|
" kernel_shift_3=torch.from_numpy(array_3)\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" for i in range(n):\n",
|
||||||
|
" for j in range(m):\n",
|
||||||
|
" if i==0 and j==0:\n",
|
||||||
|
" kernel_shift[0,0,:]=kernel_shift_0\n",
|
||||||
|
" else:\n",
|
||||||
|
" if i%2==0 and j%2==0:\n",
|
||||||
|
" kernel_shift[i*m+j,i*m+j,:]=kernel_shift_0\n",
|
||||||
|
" if i%2==0 and j%2==1:\n",
|
||||||
|
" kernel_shift[i*m+j,i*m+j,:]=kernel_shift_1\n",
|
||||||
|
" if i%2==1 and j%2==0:\n",
|
||||||
|
" kernel_shift[i*m+j,i*m+j,:]=kernel_shift_2\n",
|
||||||
|
" if i%2==1 and j%2==1:\n",
|
||||||
|
" kernel_shift[i*m+j,i*m+j,:]=kernel_shift_3\n",
|
||||||
|
" \n",
|
||||||
|
" return torch.nn.Parameter(kernel_shift,requires_grad=False) \n",
|
||||||
|
"\n",
|
||||||
|
"def get_patch(fragment,psize,n,m):\n",
|
||||||
|
" return fragment[:,:,n*psize:(n+1)*psize,m*psize:(m+1)*psize]\n",
|
||||||
|
"\n",
|
||||||
|
"class Net(nn.Module):\n",
|
||||||
|
" def __init__(self,frag_size,psize):\n",
|
||||||
|
" super(Net, self).__init__()\n",
|
||||||
|
" \n",
|
||||||
|
" h_fr=frag_size\n",
|
||||||
|
" w_fr=frag_size\n",
|
||||||
|
" \n",
|
||||||
|
" n=int(h_fr/psize) #n*m patches\n",
|
||||||
|
" m=int(w_fr/psize)\n",
|
||||||
|
" \n",
|
||||||
|
" self.conv1 = nn.Conv2d(3,8,kernel_size=3,stride=1,padding=1)\n",
|
||||||
|
" #self.conv1.weight=ini()\n",
|
||||||
|
" self.Relu = nn.ReLU(inplace=True)\n",
|
||||||
|
" self.maxpooling=nn.MaxPool2d(3,stride=2, padding=1)\n",
|
||||||
|
" \n",
|
||||||
|
" self.shift1=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)\n",
|
||||||
|
" self.shift1.weight=kernel_shift_ini(n,m)\n",
|
||||||
|
" self.add1 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)\n",
|
||||||
|
" self.add1.weight=kernel_add_ini(n,m)\n",
|
||||||
|
" \n",
|
||||||
|
" n=int(n/2)\n",
|
||||||
|
" m=int(m/2)\n",
|
||||||
|
" if n>=2 and m>=2:\n",
|
||||||
|
" self.shift2=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)\n",
|
||||||
|
" self.shift2.weight=kernel_shift_ini(n,m)\n",
|
||||||
|
" self.add2 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)\n",
|
||||||
|
" self.add2.weight=kernel_add_ini(n,m)\n",
|
||||||
|
" \n",
|
||||||
|
" n=int(n/2)\n",
|
||||||
|
" m=int(m/2)\n",
|
||||||
|
" if n>=2 and m>=2:\n",
|
||||||
|
" self.shift3=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)\n",
|
||||||
|
" self.shift3.weight=kernel_shift_ini(n,m)\n",
|
||||||
|
" self.add3 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)\n",
|
||||||
|
" self.add3.weight=kernel_add_ini(n,m)\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" def get_descripteur(self,img,using_cuda):\n",
|
||||||
|
" descripteur_img=self.Relu(self.conv1(img))\n",
|
||||||
|
" b,c,h,w=descripteur_img.shape\n",
|
||||||
|
" couche_constante=0.5*torch.ones([1,1,h,w])\n",
|
||||||
|
" if using_cuda:\n",
|
||||||
|
" couche_constante=couche_constante.cuda()\n",
|
||||||
|
" descripteur_img=torch.cat((descripteur_img,couche_constante),1)\n",
|
||||||
|
" descripteur_img_norm=descripteur_img/torch.norm(descripteur_img,dim=1)\n",
|
||||||
|
" return descripteur_img_norm\n",
|
||||||
|
" \n",
|
||||||
|
" def forward(self,img,frag,using_cuda):\n",
|
||||||
|
" psize=4\n",
|
||||||
|
" \n",
|
||||||
|
" descripteur_input1=self.get_descripteur(img,using_cuda)\n",
|
||||||
|
" descripteur_input2=self.get_descripteur(frag,using_cuda)\n",
|
||||||
|
" \n",
|
||||||
|
" b,c,h,w=frag.shape\n",
|
||||||
|
" n=int(h/psize)\n",
|
||||||
|
" m=int(w/psize)\n",
|
||||||
|
" \n",
|
||||||
|
" for i in range(n):\n",
|
||||||
|
" for j in range(m):\n",
|
||||||
|
" if i==0 and j==0:\n",
|
||||||
|
" map_corre=F.conv2d(descripteur_input1,get_patch(descripteur_input2,psize,i,j),padding=2)\n",
|
||||||
|
" else:\n",
|
||||||
|
" a=F.conv2d(descripteur_input1,get_patch(descripteur_input2,psize,i,j),padding=2)\n",
|
||||||
|
" map_corre=torch.cat((map_corre,a),1)\n",
|
||||||
|
" #shift\n",
|
||||||
|
" map_corre=self.maxpooling(map_corre)\n",
|
||||||
|
" map_corre=self.shift1(map_corre)\n",
|
||||||
|
" map_corre=self.add1(map_corre)\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" n=int(n/2)\n",
|
||||||
|
" m=int(m/2)\n",
|
||||||
|
" if n>=2 and m>=2:\n",
|
||||||
|
" map_corre=self.maxpooling(map_corre)\n",
|
||||||
|
" map_corre=self.shift2(map_corre)\n",
|
||||||
|
" map_corre=self.add2(map_corre)\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" n=int(n/2)\n",
|
||||||
|
" m=int(m/2)\n",
|
||||||
|
" if n>=2 and m>=2:\n",
|
||||||
|
" map_corre=self.maxpooling(map_corre)\n",
|
||||||
|
" map_corre=self.shift3(map_corre)\n",
|
||||||
|
" map_corre=self.add3(map_corre)\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" b,c,h,w=map_corre.shape\n",
|
||||||
|
" map_corre=map_corre/(map_corre.max())\n",
|
||||||
|
" #map_corre=(F.softmax(map_corre.reshape(1,1,h*w,1),dim=2)).reshape(b,c,h,w)\n",
|
||||||
|
" return map_corre"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Les fonctions de ce bloc sont utilisées pour appliquer le réseau à des fragments (pas à des patchs carrés)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# Cette fonction permet de sélectionner un ensemble de patchs carrés à partir d'un fragment\n",
|
||||||
|
"# Le paramètre “frag_size” fait ici référence à la taille du patch d'entrée carré (16 * 16)\n",
|
||||||
|
"# Le paramètre “seuillage” limite la proportion de pixels non noirs dans chaque patch\n",
|
||||||
|
"# Le paramètre “limite” peut limiter le nombre de correctifs trouvés dans chaque fragment\n",
|
||||||
|
"def get_patch_list(frag,frag_size,limite,seuillage):\n",
|
||||||
|
" n=0\n",
|
||||||
|
" m=0\n",
|
||||||
|
" h,w,c=frag.shape\n",
|
||||||
|
" patch_list=[]\n",
|
||||||
|
" position_list=[]\n",
|
||||||
|
" for i in range(4):\n",
|
||||||
|
" if len(patch_list)>limite and limite!=0:\n",
|
||||||
|
" break\n",
|
||||||
|
" for j in range(4):\n",
|
||||||
|
" if len(patch_list)>limite and limite!=0:\n",
|
||||||
|
" break\n",
|
||||||
|
" n_offset=i*4 # n offset\n",
|
||||||
|
" m_offset=j*4 # m offset\n",
|
||||||
|
" n=0\n",
|
||||||
|
" while n+frag_size+n_offset<h:\n",
|
||||||
|
" m=0\n",
|
||||||
|
" while m+frag_size+m_offset<w:\n",
|
||||||
|
" patch=frag[n+n_offset:n+frag_size+n_offset,m+m_offset:m+frag_size+m_offset,:]\n",
|
||||||
|
" if test_fragment32_32(patch,seuillage):\n",
|
||||||
|
" patch_list.append(patch)\n",
|
||||||
|
" position_list.append([int((n+frag_size/2)+n_offset),int((m+frag_size/2)+m_offset)])\n",
|
||||||
|
" m=m+frag_size\n",
|
||||||
|
" n=n+frag_size\n",
|
||||||
|
" return patch_list,position_list\n",
|
||||||
|
"\n",
|
||||||
|
"# Entrez du fragment et de la fresque, exécutez le réseau\n",
|
||||||
|
"def run_net_v3(net,img,frag,frag_size,limite,seuillage,using_cuda,rotation):\n",
|
||||||
|
" Img=Image.fromarray(frag)\n",
|
||||||
|
" frag=np.array(Img.rotate(rotation))\n",
|
||||||
|
" img_tensor=img2tensor(img)\n",
|
||||||
|
" \n",
|
||||||
|
" # la collection de patchs carrée dans le fragement \"sont frag_list[]\"\n",
|
||||||
|
" # La position de leur centre dans la fragment sont \"position_frag[]\"\n",
|
||||||
|
" frag_list,position_frag=get_patch_list(frag,frag_size,limite,seuillage)\n",
|
||||||
|
" if using_cuda:\n",
|
||||||
|
" img_tensor=img_tensor.cuda()\n",
|
||||||
|
" \n",
|
||||||
|
" score_list=[]\n",
|
||||||
|
" coordonnee_list=[]\n",
|
||||||
|
" \n",
|
||||||
|
" # Pour chaque patch carré dans la collection, effectuez un calcul en réseau de leur position\n",
|
||||||
|
" # Le résultat est placé en \"coordonnee_list[]\"\n",
|
||||||
|
" # \"score_list[]\" pas utile dans notre programme\n",
|
||||||
|
" for i in range(len(frag_list)):\n",
|
||||||
|
" frag_tensor=img2tensor(frag_list[i])\n",
|
||||||
|
" if using_cuda:\n",
|
||||||
|
" frag_tensor=frag_tensor.cuda()\n",
|
||||||
|
" res=net.forward(img_tensor,frag_tensor,using_cuda)\n",
|
||||||
|
" if using_cuda:\n",
|
||||||
|
" res=res.cpu()\n",
|
||||||
|
" score,po_h,po_w=show_coordonnee(res)\n",
|
||||||
|
" coordonnee_list.append([po_h,po_w])\n",
|
||||||
|
" score_list.append(score)\n",
|
||||||
|
" h_img,w_img,c=img.shape\n",
|
||||||
|
" position=[]\n",
|
||||||
|
" \n",
|
||||||
|
" # Mettez les paires correspondante en \"position[]\"\n",
|
||||||
|
" # [x,y,x',y']\n",
|
||||||
|
" # La position (x,y) dans le fragment correspond à la position (x',y') dans la fresque\n",
|
||||||
|
" for i in range(len(coordonnee_list)):\n",
|
||||||
|
" x0=position_frag[i][0]\n",
|
||||||
|
" y0=position_frag[i][1]\n",
|
||||||
|
" x1=int(round(h_img*coordonnee_list[i][0]))\n",
|
||||||
|
" y1=int(round(w_img*coordonnee_list[i][1]))\n",
|
||||||
|
" position.append([x0,y0,x1,y1])\n",
|
||||||
|
" return score_list,position"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Cette partie du code consiste à implémenter l'algorithme RANSAC amélioré\n",
|
||||||
|
"\n",
|
||||||
|
"# Ecrire le point sous forme [x,y,1]T,\n",
|
||||||
|
"# Utilisé pour construire l'équation de la matrice de transformation\n",
|
||||||
|
"def creer_point(x,y):\n",
|
||||||
|
" p=np.zeros((3,1))\n",
|
||||||
|
" p[0][0]=x\n",
|
||||||
|
" p[1][0]=y\n",
|
||||||
|
" p[2][0]=1\n",
|
||||||
|
" return p\n",
|
||||||
|
"\n",
|
||||||
|
"# Sélectionnez aléatoirement n points sans duplication à partir de M points\n",
|
||||||
|
"def selectionner_points(n,M):\n",
|
||||||
|
" table=[]\n",
|
||||||
|
" for i in range(M):\n",
|
||||||
|
" table.append(i)\n",
|
||||||
|
" result=[]\n",
|
||||||
|
" for i in range(n):\n",
|
||||||
|
" index=random.randint(0,M-i-1)\n",
|
||||||
|
" result.append(table[index])\n",
|
||||||
|
" table[index]=table[M-1-i]\n",
|
||||||
|
" return result\n",
|
||||||
|
"\n",
|
||||||
|
"# Selon la matrice de transformation affine, calculer la position centrale transformée et l'angle de rotation\n",
|
||||||
|
"def position_rotation(h,centre_frag):\n",
|
||||||
|
" centre=h@centre_frag\n",
|
||||||
|
" cos_rot=(h[0][0]+h[1][1])/2\n",
|
||||||
|
" sin_rot=(h[1][0]-h[0][1])/2\n",
|
||||||
|
" tan_rot=sin_rot/(cos_rot+0.0000001)\n",
|
||||||
|
" if cos_rot>0:\n",
|
||||||
|
" rot_frag=math.atan(tan_rot)*(180/pi)\n",
|
||||||
|
" else:\n",
|
||||||
|
" rot_frag=math.atan(tan_rot)*(180/pi)+180\n",
|
||||||
|
" rot_frag=-rot_frag\n",
|
||||||
|
" if rot_frag>0:\n",
|
||||||
|
" rot_frag-=360\n",
|
||||||
|
" return centre[0][0],centre[1][0],rot_frag\n",
|
||||||
|
"\n",
|
||||||
|
"# Vérifiez les résultats de Ransac en avec des changements de distance euclidienne\n",
|
||||||
|
"def test_frag(inline,frag,fres):\n",
|
||||||
|
" itera=10\n",
|
||||||
|
" frag_inline=[]\n",
|
||||||
|
" fres_inline=[]\n",
|
||||||
|
" # Metter les coordonnées du point inline dans \"frag_inline[]\",et \"fres_inline[]\"\n",
|
||||||
|
" for i in range(np.size(inline,0)):\n",
|
||||||
|
" if inline[i]==1:\n",
|
||||||
|
" frag_inline.append([frag[i][0],frag[i][1]])\n",
|
||||||
|
" fres_inline.append([fres[i][0],fres[i][1]])\n",
|
||||||
|
" p=[]\n",
|
||||||
|
" \n",
|
||||||
|
" # Faites une boucle dix fois, \n",
|
||||||
|
" # sélectionnez à chaque fois deux paires correspondantes inline \n",
|
||||||
|
" # calculer le changement de leur distance euclidienne\n",
|
||||||
|
" for i in range(itera):\n",
|
||||||
|
" point_test=selectionner_points(2,np.size(frag_inline,0))\n",
|
||||||
|
" diff_x_frag=frag_inline[point_test[1]][0]-frag_inline[point_test[0]][0]\n",
|
||||||
|
" diff_y_frag=frag_inline[point_test[1]][1]-frag_inline[point_test[0]][1]\n",
|
||||||
|
" diff_frag=sqrt(pow(diff_x_frag,2)+pow(diff_y_frag,2))\n",
|
||||||
|
" \n",
|
||||||
|
" diff_x_fres=fres_inline[point_test[1]][0]-fres_inline[point_test[0]][0]\n",
|
||||||
|
" diff_y_fres=fres_inline[point_test[1]][1]-fres_inline[point_test[0]][1]\n",
|
||||||
|
" diff_fres=sqrt(pow(diff_x_fres,2)+pow(diff_y_fres,2))\n",
|
||||||
|
" if diff_frag !=0:\n",
|
||||||
|
" fsf=diff_fres/diff_frag\n",
|
||||||
|
" p.append([fsf])\n",
|
||||||
|
" result=np.mean(p)\n",
|
||||||
|
" return result\n",
|
||||||
|
"\n",
|
||||||
|
"def frag_match(frag,img,position):\n",
|
||||||
|
" \n",
|
||||||
|
" frag_size=frag.shape\n",
|
||||||
|
" centre_frag=creer_point(frag_size[0]/2,frag_size[1]/2)\n",
|
||||||
|
" \n",
|
||||||
|
" retained_matches = []\n",
|
||||||
|
" frag=[]\n",
|
||||||
|
" fres=[]\n",
|
||||||
|
" \n",
|
||||||
|
" for i in range(len(position)):\n",
|
||||||
|
" frag.append([float(position[i][0]),float(position[i][1])])\n",
|
||||||
|
" fres.append([float(position[i][2]),float(position[i][3])])\n",
|
||||||
|
" \n",
|
||||||
|
" if np.size(frag)>0:\n",
|
||||||
|
" # Calculer la matrice de transformation affine à l'aide de la méthode Ransac\n",
|
||||||
|
" h,inline=cv2.estimateAffinePartial2D(np.array(frag),np.array(fres))\n",
|
||||||
|
" # Si “h” n'est pas sous la forme de matrice 2 * 3, la matrice de transformation affine n'est pas trouvée\n",
|
||||||
|
" if np.size(h)!=6:\n",
|
||||||
|
" return ([-1])\n",
|
||||||
|
" else:\n",
|
||||||
|
" x,y,rot=position_rotation(h,centre_frag)\n",
|
||||||
|
" pourcenttage=sum(inline)/np.size(frag,0)\n",
|
||||||
|
" # Le nombre de points inline doit être supérieur à un certain nombre\n",
|
||||||
|
" if sum(inline)>3:\n",
|
||||||
|
" p=test_frag(inline,frag,fres)\n",
|
||||||
|
" # La distance euclidienne entre les points correspondants ne doit pas trop changer, \n",
|
||||||
|
" # sinon cela prouve que le résultat de Ransac est incorrect\n",
|
||||||
|
" # ici,le changement de la distance euclidienne sont entre 0.7 et 1.3\n",
|
||||||
|
" if abs(p-1)<0.3:\n",
|
||||||
|
" # Ce n'est qu'alors que Ransac renvoie le résultat correct\n",
|
||||||
|
" return([round(y),round(x),round(rot,3)])\n",
|
||||||
|
" else:\n",
|
||||||
|
" return ([-2])\n",
|
||||||
|
" else:\n",
|
||||||
|
" return ([-3])\n",
|
||||||
|
" else:\n",
|
||||||
|
" return ([-4]) "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 14,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"if __name__==\"__main__\":\n",
|
||||||
|
" \n",
|
||||||
|
" frag_size=16\n",
|
||||||
|
" using_cuda=True\n",
|
||||||
|
" net=load_net(\"./net_trainned6000\")\n",
|
||||||
|
" img_test=cv2.imread(\"./fresque0.ppm\")\n",
|
||||||
|
" \n",
|
||||||
|
" result=[]\n",
|
||||||
|
" for n in range(315):\n",
|
||||||
|
" if n<10:\n",
|
||||||
|
" frag_test=cv2.imread(\"./frag_eroded0/frag_eroded_000\"+str(n)+\".ppm\")\n",
|
||||||
|
" elif n<100:\n",
|
||||||
|
" frag_test=cv2.imread(\"./frag_eroded0/frag_eroded_00\"+str(n)+\".ppm\")\n",
|
||||||
|
" else:\n",
|
||||||
|
" frag_test=cv2.imread(\"./frag_eroded0/frag_eroded_0\"+str(n)+\".ppm\")\n",
|
||||||
|
" \n",
|
||||||
|
" # Faites pivoter les pièces de 20 degrés à chaque fois pour correspondre, répétez 18 fois\n",
|
||||||
|
" for i in range(18):\n",
|
||||||
|
" rotation=20*i\n",
|
||||||
|
" score_list,position=run_net_v3(net,img_test,frag_test,frag_size,60,0.7,using_cuda,rotation)\n",
|
||||||
|
" frag_position=frag_match(frag_test,img_test,position)\n",
|
||||||
|
" # Lorsque Ransac obtient le bon résultat, sortez de la boucle\n",
|
||||||
|
" if len(frag_position)==3:\n",
|
||||||
|
" rotation_base=i*20\n",
|
||||||
|
" break\n",
|
||||||
|
" # Enregistrez les fragments correctement localisés dans \"result[]\"\n",
|
||||||
|
" if len(frag_position)==3:\n",
|
||||||
|
" frag_position[2]=rotation_base-360-frag_position[2]\n",
|
||||||
|
" if frag_position[2]>0:\n",
|
||||||
|
" frag_position[2]=frag_position[2]-360\n",
|
||||||
|
" result.append([n,frag_position[0],frag_position[1],round(frag_position[2],3)])\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 15,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[[0, 520.0, 575.0, -356.388],\n",
|
||||||
|
" [1, 535.0, 460.0, -113.454],\n",
|
||||||
|
" [2, 971.0, 270.0, -40.966],\n",
|
||||||
|
" [3, 1641.0, 650.0, -119.543],\n",
|
||||||
|
" [4, 1349.0, 68.0, -336.356],\n",
|
||||||
|
" [5, 1509.0, 192.0, -298.759],\n",
|
||||||
|
" [6, 107.0, 521.0, -74.179],\n",
|
||||||
|
" [7, 420.0, 440.0, -174.266],\n",
|
||||||
|
" [8, 287.0, 533.0, -299.677],\n",
|
||||||
|
" [9, 1518.0, 167.0, -290.164],\n",
|
||||||
|
" [10, 231.0, 429.0, -180.983],\n",
|
||||||
|
" [11, 666.0, 483.0, -230.948],\n",
|
||||||
|
" [12, 855.0, 104.0, -346.884],\n",
|
||||||
|
" [13, 1267.0, 87.0, -305.562],\n",
|
||||||
|
" [14, 16.0, 705.0, -30.087],\n",
|
||||||
|
" [15, 924.0, 120.0, -146.41],\n",
|
||||||
|
" [16, 657.0, 372.0, -175.323],\n",
|
||||||
|
" [17, 1409.0, 528.0, -329.829],\n",
|
||||||
|
" [18, 618.0, 427.0, -350.062],\n",
|
||||||
|
" [19, 631.0, 269.0, -87.332],\n",
|
||||||
|
" [20, 1345.0, 579.0, -320.597],\n",
|
||||||
|
" [21, 1670.0, 139.0, -282.108],\n",
|
||||||
|
" [22, 1310.0, 4.0, -180.0],\n",
|
||||||
|
" [23, 1418.0, 29.0, -112.925],\n",
|
||||||
|
" [24, 874.0, 496.0, -312.046],\n",
|
||||||
|
" [25, 812.0, 537.0, -4.393],\n",
|
||||||
|
" [26, 47.0, 728.0, -82.997],\n",
|
||||||
|
" [27, 1411.0, 200.0, -324.46],\n",
|
||||||
|
" [28, 767.0, 595.0, -339.734],\n",
|
||||||
|
" [29, 361.0, 434.0, -349.088],\n",
|
||||||
|
" [30, 1264.0, 732.0, -211.149],\n",
|
||||||
|
" [31, 958.0, 738.0, -356.008],\n",
|
||||||
|
" [32, 1307.0, 679.0, -145.032],\n",
|
||||||
|
" [33, 704.0, 553.0, -197.736],\n",
|
||||||
|
" [34, 867.0, 344.0, -355.599],\n",
|
||||||
|
" [35, 1702.0, 164.0, -315.301],\n",
|
||||||
|
" [36, 1483.0, 307.0, -330.954],\n",
|
||||||
|
" [37, 1365.0, 661.0, -158.589],\n",
|
||||||
|
" [38, 35.0, 623.0, -301.166],\n",
|
||||||
|
" [39, 968.0, 40.0, -355.307],\n",
|
||||||
|
" [40, 137.0, 650.0, -127.38],\n",
|
||||||
|
" [41, 1527.0, 239.0, -113.919],\n",
|
||||||
|
" [42, 1176.0, 736.0, -218.247],\n",
|
||||||
|
" [43, 466.0, 676.0, -139.007],\n",
|
||||||
|
" [44, 297.0, 659.0, -22.509],\n",
|
||||||
|
" [45, 1075.0, 363.0, -1.866],\n",
|
||||||
|
" [46, 973.0, 658.0, -118.442],\n",
|
||||||
|
" [47, 658.0, 589.0, -134.967],\n",
|
||||||
|
" [48, 1438.0, 245.0, -63.213],\n",
|
||||||
|
" [49, 1019.0, 381.0, -4.052],\n",
|
||||||
|
" [50, 898.0, 586.0, -320.709],\n",
|
||||||
|
" [51, 738.0, 258.0, -298.33],\n",
|
||||||
|
" [52, 1668.0, 167.0, -257.834],\n",
|
||||||
|
" [53, 306.0, 201.0, -304.816],\n",
|
||||||
|
" [54, 129.0, 353.0, -123.722],\n",
|
||||||
|
" [55, 1612.0, 527.0, -201.46],\n",
|
||||||
|
" [56, 1406.0, 400.0, -132.928],\n",
|
||||||
|
" [57, 1223.0, 629.0, -243.388],\n",
|
||||||
|
" [58, 1603.0, 770.0, -223.688],\n",
|
||||||
|
" [59, 1451.0, 323.0, -4.008],\n",
|
||||||
|
" [60, 1262.0, -8.0, -143.496],\n",
|
||||||
|
" [61, 1409.0, 358.0, -244.745],\n",
|
||||||
|
" [62, 426.0, 567.0, -107.651],\n",
|
||||||
|
" [63, 1093.0, 536.0, -11.543],\n",
|
||||||
|
" [64, 1570.0, 763.0, -340.0],\n",
|
||||||
|
" [65, 599.0, 29.0, -352.066],\n",
|
||||||
|
" [66, 38.0, 522.0, -237.017],\n",
|
||||||
|
" [67, 1076.0, 29.0, -152.794],\n",
|
||||||
|
" [68, 1629.0, 79.0, -70.396],\n",
|
||||||
|
" [69, 1464.0, 311.0, -306.565],\n",
|
||||||
|
" [70, 1595.0, 260.0, -53.364],\n",
|
||||||
|
" [71, 1343.0, 273.0, -256.237],\n",
|
||||||
|
" [72, 1074.0, 236.0, -1.801],\n",
|
||||||
|
" [73, 132.0, 35.0, -160.03],\n",
|
||||||
|
" [74, 1627.0, 762.0, -235.274],\n",
|
||||||
|
" [75, 713.0, 361.0, -136.338],\n",
|
||||||
|
" [76, 1485.0, 85.0, -90.974],\n",
|
||||||
|
" [77, 1243.0, 153.0, -268.034],\n",
|
||||||
|
" [78, 1026.0, 511.0, -118.767],\n",
|
||||||
|
" [79, 240.0, 181.0, -51.205],\n",
|
||||||
|
" [80, 1085.0, 680.0, -53.483],\n",
|
||||||
|
" [81, 73.0, 212.0, -299.054],\n",
|
||||||
|
" [82, 1237.0, 389.0, -306.557],\n",
|
||||||
|
" [83, 1269.0, 87.0, -330.538],\n",
|
||||||
|
" [84, 29.0, 175.0, -298.41],\n",
|
||||||
|
" [85, 982.0, 97.0, -80.0],\n",
|
||||||
|
" [86, 1487.0, 276.0, -211.009],\n",
|
||||||
|
" [87, 1226.0, 114.0, -321.565],\n",
|
||||||
|
" [88, 60.0, 317.0, -127.895],\n",
|
||||||
|
" [89, 1351.0, 285.0, -322.595],\n",
|
||||||
|
" [90, 233.0, 33.0, -144.993],\n",
|
||||||
|
" [91, 807.0, 211.0, -1.747],\n",
|
||||||
|
" [92, 997.0, 558.0, -326.669],\n",
|
||||||
|
" [93, 1682.0, 283.0, -312.023],\n",
|
||||||
|
" [94, 1178.0, 691.0, -242.927],\n",
|
||||||
|
" [95, 1116.0, 487.0, -288.69],\n",
|
||||||
|
" [96, 952.0, 14.0, -275.225],\n",
|
||||||
|
" [97, 140.0, 765.0, -206.9],\n",
|
||||||
|
" [98, 772.0, 81.0, -112.039],\n",
|
||||||
|
" [99, 640.0, 682.0, -57.917],\n",
|
||||||
|
" [100, 121.0, 757.0, -231.821],\n",
|
||||||
|
" [101, 1484.0, 218.0, -15.255],\n",
|
||||||
|
" [102, 1304.0, 164.0, -273.435],\n",
|
||||||
|
" [103, 862.0, 192.0, -303.177],\n",
|
||||||
|
" [104, 258.0, 766.0, -257.769],\n",
|
||||||
|
" [105, 540.0, 714.0, -183.176],\n",
|
||||||
|
" [106, 1283.0, 264.0, -330.905],\n",
|
||||||
|
" [107, 507.0, 196.0, -333.629],\n",
|
||||||
|
" [108, 1428.0, 438.0, -209.806],\n",
|
||||||
|
" [109, 391.0, 739.0, -243.391],\n",
|
||||||
|
" [110, 250.0, 640.0, -287.596],\n",
|
||||||
|
" [111, 704.0, 102.0, -78.376],\n",
|
||||||
|
" [112, 1060.0, 227.0, -300.726],\n",
|
||||||
|
" [113, 1509.0, 302.0, -318.749],\n",
|
||||||
|
" [114, 895.0, 662.0, -199.664],\n",
|
||||||
|
" [115, 1453.0, 254.0, -260.0],\n",
|
||||||
|
" [116, 1058.0, 199.0, -218.275],\n",
|
||||||
|
" [117, 1416.0, 779.0, 0.0],\n",
|
||||||
|
" [118, 1054.0, 740.0, -197.173],\n",
|
||||||
|
" [119, 1352.0, 393.0, -309.992],\n",
|
||||||
|
" [120, 1273.0, 585.0, -334.957],\n",
|
||||||
|
" [121, 952.0, 566.0, -193.436],\n",
|
||||||
|
" [122, 1132.0, 456.0, -25.393],\n",
|
||||||
|
" [123, 598.0, 179.0, -308.525],\n",
|
||||||
|
" [124, 1270.0, 15.0, -260.0],\n",
|
||||||
|
" [125, 763.0, 462.0, -241.979],\n",
|
||||||
|
" [126, 1515.0, 307.0, -284.007],\n",
|
||||||
|
" [127, 1582.0, 608.0, -175.422],\n",
|
||||||
|
" [128, 388.0, 536.0, -166.952],\n",
|
||||||
|
" [129, 426.0, 667.0, -84.451],\n",
|
||||||
|
" [130, 1505.0, 18.0, -192.572],\n",
|
||||||
|
" [131, 976.0, 440.0, -260.194],\n",
|
||||||
|
" [132, 1467.0, 655.0, -345.072],\n",
|
||||||
|
" [133, 1085.0, 388.0, -323.091],\n",
|
||||||
|
" [134, 1189.0, 514.0, -99.219],\n",
|
||||||
|
" [135, 232.0, 751.0, -360.0],\n",
|
||||||
|
" [136, 1336.0, 91.0, -132.694],\n",
|
||||||
|
" [137, 765.0, 173.0, -54.653],\n",
|
||||||
|
" [138, 1451.0, 421.0, -291.464],\n",
|
||||||
|
" [139, 920.0, 370.0, -271.035],\n",
|
||||||
|
" [140, 314.0, 739.0, -302.917],\n",
|
||||||
|
" [141, 1225.0, 213.0, -281.565],\n",
|
||||||
|
" [143, 160.0, 716.0, -238.299],\n",
|
||||||
|
" [144, 503.0, 31.0, -348.257],\n",
|
||||||
|
" [145, 1159.0, 423.0, -94.766],\n",
|
||||||
|
" [146, 131.0, 716.0, -27.957],\n",
|
||||||
|
" [147, 20.0, 683.0, -230.611],\n",
|
||||||
|
" [148, 237.0, 756.0, -164.897],\n",
|
||||||
|
" [149, 1596.0, 19.0, -285.437],\n",
|
||||||
|
" [150, 238.0, 737.0, -17.033],\n",
|
||||||
|
" [151, 354.0, 151.0, -100.638],\n",
|
||||||
|
" [152, 887.0, 257.0, -318.435],\n",
|
||||||
|
" [153, 541.0, 142.0, -151.453],\n",
|
||||||
|
" [154, 1177.0, 82.0, -275.589],\n",
|
||||||
|
" [155, 1526.0, 594.0, -340.0],\n",
|
||||||
|
" [156, 1454.0, 307.0, -305.964],\n",
|
||||||
|
" [157, 327.0, 150.0, -161.526],\n",
|
||||||
|
" [158, 1288.0, 199.0, -314.289],\n",
|
||||||
|
" [159, 649.0, 179.0, -333.417],\n",
|
||||||
|
" [160, 1413.0, 255.0, -283.537],\n",
|
||||||
|
" [161, 1543.0, 61.0, -307.416],\n",
|
||||||
|
" [162, 1190.0, 144.0, -226.857],\n",
|
||||||
|
" [163, 587.0, 104.0, -151.213],\n",
|
||||||
|
" [164, 1320.0, 602.0, -315.852],\n",
|
||||||
|
" [165, 627.0, 104.0, -320.252],\n",
|
||||||
|
" [166, 1474.0, 413.0, -233.361],\n",
|
||||||
|
" [167, 699.0, 176.0, -178.052],\n",
|
||||||
|
" [168, 1024.0, 341.0, -259.2],\n",
|
||||||
|
" [169, 1701.0, 755.0, -304.039],\n",
|
||||||
|
" [170, 1684.0, 210.0, -244.828],\n",
|
||||||
|
" [171, 1330.0, 290.0, -21.864],\n",
|
||||||
|
" [172, 1053.0, 139.0, -324.51],\n",
|
||||||
|
" [173, 1643.0, 428.0, -331.469],\n",
|
||||||
|
" [174, 319.0, 542.0, -205.964],\n",
|
||||||
|
" [175, 1045.0, 91.0, -3.533],\n",
|
||||||
|
" [176, 828.0, 695.0, -295.602],\n",
|
||||||
|
" [177, 1631.0, 287.0, -132.225],\n",
|
||||||
|
" [178, 361.0, 677.0, -142.992],\n",
|
||||||
|
" [179, 1674.0, 350.0, -227.628],\n",
|
||||||
|
" [180, 1412.0, 764.0, -350.194],\n",
|
||||||
|
" [181, 845.0, 19.0, -27.206],\n",
|
||||||
|
" [183, 1239.0, 192.0, -317.673],\n",
|
||||||
|
" [184, 320.0, 39.0, -157.845],\n",
|
||||||
|
" [185, 1387.0, 749.0, -46.487],\n",
|
||||||
|
" [186, 166.0, 589.0, -211.473],\n",
|
||||||
|
" [187, 1339.0, 122.0, -258.435],\n",
|
||||||
|
" [188, 1216.0, 235.0, -163.194],\n",
|
||||||
|
" [189, 1677.0, 696.0, -275.899],\n",
|
||||||
|
" [190, 158.0, 762.0, -327.275],\n",
|
||||||
|
" [191, 1078.0, 254.0, -226.278],\n",
|
||||||
|
" [192, 468.0, 761.0, -280.0],\n",
|
||||||
|
" [193, 439.0, 44.0, -182.45],\n",
|
||||||
|
" [194, 161.0, 541.0, -354.612],\n",
|
||||||
|
" [195, 972.0, 502.0, -335.421],\n",
|
||||||
|
" [196, 427.0, 192.0, -300.872],\n",
|
||||||
|
" [197, 17.0, 358.0, -137.835],\n",
|
||||||
|
" [198, 210.0, 580.0, -7.095],\n",
|
||||||
|
" [199, 259.0, 601.0, -228.13],\n",
|
||||||
|
" [200, 583.0, 736.0, -154.988],\n",
|
||||||
|
" [201, 216.0, 751.0, -302.426],\n",
|
||||||
|
" [202, 826.0, 46.0, -162.036],\n",
|
||||||
|
" [203, 1592.0, 382.0, -344.745],\n",
|
||||||
|
" [204, 1533.0, 110.0, -332.592],\n",
|
||||||
|
" [205, 159.0, 761.0, -21.87],\n",
|
||||||
|
" [206, 1219.0, 473.0, -297.199],\n",
|
||||||
|
" [207, 1697.0, 711.0, -103.887],\n",
|
||||||
|
" [208, 1449.0, 289.0, -247.773],\n",
|
||||||
|
" [209, 1694.0, 749.0, -48.106],\n",
|
||||||
|
" [210, 842.0, 613.0, -235.221],\n",
|
||||||
|
" [211, 1046.0, 294.0, -134.05],\n",
|
||||||
|
" [212, 1696.0, 763.0, -258.435],\n",
|
||||||
|
" [213, 350.0, 83.0, -189.227],\n",
|
||||||
|
" [214, 1262.0, 482.0, -347.386],\n",
|
||||||
|
" [215, 310.0, 321.0, -211.399],\n",
|
||||||
|
" [216, 744.0, 22.0, -268.647],\n",
|
||||||
|
" [218, 1353.0, 732.0, -72.057],\n",
|
||||||
|
" [219, 1418.0, 770.0, -340.0],\n",
|
||||||
|
" [220, 496.0, 718.0, -20.0],\n",
|
||||||
|
" [221, 477.0, 149.0, -277.479],\n",
|
||||||
|
" [222, 1547.0, 87.0, -325.069],\n",
|
||||||
|
" [223, 1087.0, 345.0, -3.805],\n",
|
||||||
|
" [224, 259.0, 78.0, -19.36],\n",
|
||||||
|
" [225, 1530.0, 512.0, -276.062],\n",
|
||||||
|
" [226, 132.0, 730.0, -360.0],\n",
|
||||||
|
" [227, 944.0, 471.0, -170.0],\n",
|
||||||
|
" [228, 1245.0, 256.0, -155.672],\n",
|
||||||
|
" [229, 1615.0, 354.0, -81.565],\n",
|
||||||
|
" [230, 177.0, 72.0, -198.674],\n",
|
||||||
|
" [231, 1637.0, 470.0, -350.62],\n",
|
||||||
|
" [232, 540.0, 644.0, -4.911],\n",
|
||||||
|
" [233, 624.0, 625.0, -127.127],\n",
|
||||||
|
" [234, 420.0, 15.0, -187.058],\n",
|
||||||
|
" [235, 884.0, 751.0, -288.649],\n",
|
||||||
|
" [236, 267.0, 776.0, -339.146],\n",
|
||||||
|
" [237, 1129.0, 87.0, -10.008],\n",
|
||||||
|
" [238, 1700.0, 713.0, -240.764],\n",
|
||||||
|
" [239, 286.0, 283.0, -148.653],\n",
|
||||||
|
" [240, 679.0, 730.0, -336.762],\n",
|
||||||
|
" [241, 1129.0, 106.0, -326.244],\n",
|
||||||
|
" [242, 1292.0, 200.0, -203.69],\n",
|
||||||
|
" [243, 1693.0, 570.0, -140.0],\n",
|
||||||
|
" [244, 1529.0, 114.0, -341.565],\n",
|
||||||
|
" [245, 158.0, 759.0, -356.87],\n",
|
||||||
|
" [246, 1116.0, 563.0, -242.203],\n",
|
||||||
|
" [247, 283.0, 129.0, -309.725],\n",
|
||||||
|
" [248, 1597.0, 294.0, -312.875],\n",
|
||||||
|
" [249, 1709.0, 762.0, -273.435],\n",
|
||||||
|
" [250, 1377.0, 302.0, -314.179],\n",
|
||||||
|
" [251, 323.0, 364.0, -6.183],\n",
|
||||||
|
" [252, 1316.0, 485.0, -280.0],\n",
|
||||||
|
" [253, 962.0, 16.0, -280.0],\n",
|
||||||
|
" [254, 1198.0, 573.0, -11.792],\n",
|
||||||
|
" [255, 276.0, 384.0, -279.393],\n",
|
||||||
|
" [256, 1684.0, 734.0, -104.219],\n",
|
||||||
|
" [257, 1447.0, 333.0, -280.5],\n",
|
||||||
|
" [258, 999.0, 256.0, -227.883],\n",
|
||||||
|
" [259, 1014.0, 413.0, -325.59],\n",
|
||||||
|
" [260, 141.0, 724.0, -216.565],\n",
|
||||||
|
" [261, 1552.0, 545.0, -255.848],\n",
|
||||||
|
" [262, 292.0, 13.0, -191.87],\n",
|
||||||
|
" [263, 573.0, 681.0, -79.779],\n",
|
||||||
|
" [264, 1433.0, 740.0, -149.733],\n",
|
||||||
|
" [265, 138.0, 726.0, -311.027],\n",
|
||||||
|
" [266, 1617.0, 762.0, -327.995],\n",
|
||||||
|
" [267, 170.0, 141.0, -335.639],\n",
|
||||||
|
" [268, 1282.0, 441.0, -324.876],\n",
|
||||||
|
" [269, 322.0, 255.0, -143.393],\n",
|
||||||
|
" [270, 100.0, 762.0, -56.809],\n",
|
||||||
|
" [271, 1249.0, 533.0, -349.403],\n",
|
||||||
|
" [272, 1097.0, 584.0, -213.29],\n",
|
||||||
|
" [274, 1697.0, 712.0, -360.0],\n",
|
||||||
|
" [275, 399.0, 148.0, -176.849],\n",
|
||||||
|
" [276, 56.0, 452.0, -155.208],\n",
|
||||||
|
" [277, 166.0, 16.0, -336.461],\n",
|
||||||
|
" [278, 58.0, 406.0, -233.24],\n",
|
||||||
|
" [279, 1552.0, 79.0, -69.146],\n",
|
||||||
|
" [280, 746.0, 134.0, -259.441],\n",
|
||||||
|
" [281, 123.0, 106.0, -103.672],\n",
|
||||||
|
" [282, 160.0, 758.0, -64.289],\n",
|
||||||
|
" [283, 1454.0, 323.0, -100.71],\n",
|
||||||
|
" [284, 220.0, 98.0, -135.362],\n",
|
||||||
|
" [285, 1173.0, 234.0, -105.515],\n",
|
||||||
|
" [286, 1238.0, 576.0, -360.0],\n",
|
||||||
|
" [287, 383.0, 194.0, -259.057],\n",
|
||||||
|
" [288, 1693.0, 147.0, -322.49],\n",
|
||||||
|
" [289, 286.0, 351.0, -360.0],\n",
|
||||||
|
" [290, 648.0, 734.0, -27.933],\n",
|
||||||
|
" [292, 160.0, 492.0, -111.87],\n",
|
||||||
|
" [293, 1105.0, 621.0, -115.047],\n",
|
||||||
|
" [294, 1108.0, 241.0, -227.684],\n",
|
||||||
|
" [295, 1212.0, 278.0, -340.0],\n",
|
||||||
|
" [296, 844.0, 756.0, -338.456],\n",
|
||||||
|
" [298, 1693.0, 111.0, -278.435],\n",
|
||||||
|
" [299, 1530.0, 563.0, -335.376],\n",
|
||||||
|
" [301, 364.0, 316.0, -360.0],\n",
|
||||||
|
" [303, 1690.0, 15.0, -3.881],\n",
|
||||||
|
" [304, 1170.0, 179.0, -151.87],\n",
|
||||||
|
" [305, 1408.0, 331.0, -11.189],\n",
|
||||||
|
" [307, 1654.0, 12.0, -280.0],\n",
|
||||||
|
" [308, 1180.0, 207.0, -80.017],\n",
|
||||||
|
" [309, 86.0, 403.0, -185.0],\n",
|
||||||
|
" [313, 281.0, 317.0, -120.0]]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 15,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"result"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "py37",
|
||||||
|
"language": "python",
|
||||||
|
"name": "py37"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.7.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
515
Frag_Match_avec_rotation.py
Normal file
515
Frag_Match_avec_rotation.py
Normal file
|
@ -0,0 +1,515 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
# In[1]:
|
||||||
|
|
||||||
|
|
||||||
|
#Tous les codes sont basés sur l'environnement suivant
|
||||||
|
#python 3.7
|
||||||
|
#opencv 3.1.0
|
||||||
|
#pytorch 1.4.0
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from torch.autograd import Variable
|
||||||
|
import torch.nn as nn
|
||||||
|
import torch.nn.functional as F
|
||||||
|
import cv2
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import random
|
||||||
|
import math
|
||||||
|
import pickle
|
||||||
|
import random
|
||||||
|
from PIL import Image
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# In[2]:
|
||||||
|
|
||||||
|
|
||||||
|
# Les fonctions dans ce bloc ne sont pas utilisées par le réseau, mais certaines fonctions d'outils
|
||||||
|
|
||||||
|
# Les fonctions de ce bloc se trouvent dans le programme d'apprentissage
|
||||||
|
# “Apprentissage_MSELoss_avec_GPU“
|
||||||
|
# et les commentaires détaillés se trouvent dans le programme d'apprentissage
|
||||||
|
|
||||||
|
def tensor_imshow(im_tensor,cannel):
|
||||||
|
b,c,h,w=im_tensor.shape
|
||||||
|
if c==1:
|
||||||
|
plt.imshow(im_tensor.squeeze().detach().numpy())
|
||||||
|
else:
|
||||||
|
plt.imshow(im_tensor.squeeze().detach().numpy()[cannel,:])
|
||||||
|
|
||||||
|
def get_training_fragment(frag_size,im):
|
||||||
|
h,w,c=im.shape
|
||||||
|
n=random.randint(0,int(h/frag_size)-1)
|
||||||
|
m=random.randint(0,int(w/frag_size)-1)
|
||||||
|
|
||||||
|
shape=frag_size/4
|
||||||
|
vt_h=math.ceil((h+1)/shape)
|
||||||
|
vt_w=math.ceil((w+1)/shape)
|
||||||
|
vt=np.zeros([vt_h,vt_w])
|
||||||
|
vt_h_po=round((vt_h-1)*(n*frag_size/(h-1)+(n+1)*frag_size/(h-1))/2)
|
||||||
|
vt_w_po=round((vt_w-1)*(m*frag_size/(w-1)+(m+1)*frag_size/(w-1))/2)
|
||||||
|
vt[vt_h_po,vt_w_po]=1
|
||||||
|
vt = np.float32(vt)
|
||||||
|
vt=torch.from_numpy(vt.reshape(1,1,vt_h,vt_w))
|
||||||
|
|
||||||
|
return im[n*frag_size:(n+1)*frag_size,m*frag_size:(m+1)*frag_size,:],vt
|
||||||
|
|
||||||
|
def write_result_in_file(result,file_name):
|
||||||
|
n=0
|
||||||
|
with open(file_name,'w') as file:
|
||||||
|
for i in range(len(result)):
|
||||||
|
while n<result[i][0]:
|
||||||
|
s=str(n)
|
||||||
|
n=n+1
|
||||||
|
s=s+"\n"
|
||||||
|
file.write(s)
|
||||||
|
s=str(result[i][0])+" "+str(result[i][1])+" "+str(result[i][2])+" "+str(result[i][3])
|
||||||
|
s=s+"\n"
|
||||||
|
n=n+1
|
||||||
|
file.write(s)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
|
||||||
|
def img2tensor(im):
|
||||||
|
im=np.array(im,dtype="float32")
|
||||||
|
tensor_cv = torch.from_numpy(np.transpose(im, (2, 0, 1)))
|
||||||
|
im_tensor=tensor_cv.unsqueeze(0)
|
||||||
|
return im_tensor
|
||||||
|
|
||||||
|
def show_coordonnee(position_pred):
|
||||||
|
map_corre=position_pred.squeeze().detach().numpy()
|
||||||
|
score=sum(sum(map_corre))
|
||||||
|
h,w=map_corre.shape
|
||||||
|
max_value=map_corre.max()
|
||||||
|
coordonnee=np.where(map_corre==max_value)
|
||||||
|
return score,coordonnee[0].mean()/h,coordonnee[1].mean()/w
|
||||||
|
|
||||||
|
def test_fragment32_32(frag,seuillage):
|
||||||
|
a=frag[:,:,0]+frag[:,:,1]+frag[:,:,2]
|
||||||
|
mask = (a == 0)
|
||||||
|
arr_new = a[mask]
|
||||||
|
if arr_new.size/a.size<=(1-seuillage):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save_net(file_path,net):
|
||||||
|
pkl_file = open(file_path, 'wb')
|
||||||
|
pickle.dump(net,pkl_file)
|
||||||
|
pkl_file.close()
|
||||||
|
|
||||||
|
def load_net(file_path):
|
||||||
|
pkl_file = open(file_path, 'rb')
|
||||||
|
net= pickle.load(pkl_file)
|
||||||
|
pkl_file.close()
|
||||||
|
return net
|
||||||
|
|
||||||
|
|
||||||
|
# In[3]:
|
||||||
|
|
||||||
|
|
||||||
|
# Les fonctions de ce bloc sont utilisées pour construire le réseau
|
||||||
|
|
||||||
|
# Les fonctions de ce bloc se trouvent dans le programme d'apprentissage
|
||||||
|
# “Apprentissage_MSELoss_avec_GPU“
|
||||||
|
# et les commentaires détaillés se trouvent dans le programme d'apprentissage
|
||||||
|
|
||||||
|
def ini():
|
||||||
|
kernel=torch.zeros([8,3,3,3])
|
||||||
|
array_0=np.array([[1,2,1],[0,0,0],[-1,-2,-1]],dtype='float32')
|
||||||
|
array_1=np.array([[2,1,0],[1,0,-1],[0,-1,-2]],dtype='float32')
|
||||||
|
array_2=np.array([[1,0,-1],[2,0,-2],[1,0,-1]],dtype='float32')
|
||||||
|
array_3=np.array([[0,-1,-2],[1,0,-1],[2,1,0]],dtype='float32')
|
||||||
|
array_4=np.array([[-1,-2,-1],[0,0,0],[1,2,1]],dtype='float32')
|
||||||
|
array_5=np.array([[-2,-1,0],[-1,0,1],[0,1,2]],dtype='float32')
|
||||||
|
array_6=np.array([[-1,0,1],[-2,0,2],[-1,0,1]],dtype='float32')
|
||||||
|
array_7=np.array([[0,1,2],[-1,0,1],[-2,-1,0]],dtype='float32')
|
||||||
|
for i in range(3):
|
||||||
|
kernel[0,i,:]=torch.from_numpy(array_0)
|
||||||
|
kernel[1,i,:]=torch.from_numpy(array_1)
|
||||||
|
kernel[2,i,:]=torch.from_numpy(array_2)
|
||||||
|
kernel[3,i,:]=torch.from_numpy(array_3)
|
||||||
|
kernel[4,i,:]=torch.from_numpy(array_4)
|
||||||
|
kernel[5,i,:]=torch.from_numpy(array_5)
|
||||||
|
kernel[6,i,:]=torch.from_numpy(array_6)
|
||||||
|
kernel[7,i,:]=torch.from_numpy(array_7)
|
||||||
|
return torch.nn.Parameter(kernel,requires_grad=True)
|
||||||
|
|
||||||
|
def kernel_add_ini(n,m):
|
||||||
|
input_canal=int(n*m)
|
||||||
|
output_canal=int(n/2)*int(m/2)
|
||||||
|
for i in range(int(n/2)):
|
||||||
|
for j in range(int(m/2)):
|
||||||
|
kernel_add=np.zeros([1,input_canal],dtype='float32')
|
||||||
|
kernel_add[0,i*2*m+j*2]=1
|
||||||
|
kernel_add[0,i*2*m+j*2+1]=1
|
||||||
|
kernel_add[0,(i*2+1)*m+j*2]=1
|
||||||
|
kernel_add[0,(i*2+1)*m+j*2+1]=1
|
||||||
|
if i==0 and j==0:
|
||||||
|
add=torch.from_numpy(kernel_add.reshape(1,input_canal,1,1))
|
||||||
|
else:
|
||||||
|
add_=torch.from_numpy(kernel_add.reshape(1,input_canal,1,1))
|
||||||
|
add=torch.cat((add,add_),0)
|
||||||
|
return torch.nn.Parameter(add,requires_grad=False)
|
||||||
|
|
||||||
|
def kernel_shift_ini(n,m):
|
||||||
|
input_canal=int(n*m)
|
||||||
|
output_canal=int(n*m)
|
||||||
|
|
||||||
|
kernel_shift=torch.zeros([output_canal,input_canal,3,3])
|
||||||
|
|
||||||
|
array_0=np.array([[1,0,0],[0,0,0],[0,0,0]],dtype='float32')
|
||||||
|
array_1=np.array([[0,0,1],[0,0,0],[0,0,0]],dtype='float32')
|
||||||
|
array_2=np.array([[0,0,0],[0,0,0],[1,0,0]],dtype='float32')
|
||||||
|
array_3=np.array([[0,0,0],[0,0,0],[0,0,1]],dtype='float32')
|
||||||
|
|
||||||
|
kernel_shift_0=torch.from_numpy(array_0)
|
||||||
|
kernel_shift_1=torch.from_numpy(array_1)
|
||||||
|
kernel_shift_2=torch.from_numpy(array_2)
|
||||||
|
kernel_shift_3=torch.from_numpy(array_3)
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(m):
|
||||||
|
if i==0 and j==0:
|
||||||
|
kernel_shift[0,0,:]=kernel_shift_0
|
||||||
|
else:
|
||||||
|
if i%2==0 and j%2==0:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_0
|
||||||
|
if i%2==0 and j%2==1:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_1
|
||||||
|
if i%2==1 and j%2==0:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_2
|
||||||
|
if i%2==1 and j%2==1:
|
||||||
|
kernel_shift[i*m+j,i*m+j,:]=kernel_shift_3
|
||||||
|
|
||||||
|
return torch.nn.Parameter(kernel_shift,requires_grad=False)
|
||||||
|
|
||||||
|
def get_patch(fragment,psize,n,m):
|
||||||
|
return fragment[:,:,n*psize:(n+1)*psize,m*psize:(m+1)*psize]
|
||||||
|
|
||||||
|
class Net(nn.Module):
|
||||||
|
def __init__(self,frag_size,psize):
|
||||||
|
super(Net, self).__init__()
|
||||||
|
|
||||||
|
h_fr=frag_size
|
||||||
|
w_fr=frag_size
|
||||||
|
|
||||||
|
n=int(h_fr/psize) #n*m patches
|
||||||
|
m=int(w_fr/psize)
|
||||||
|
|
||||||
|
self.conv1 = nn.Conv2d(3,8,kernel_size=3,stride=1,padding=1)
|
||||||
|
#self.conv1.weight=ini()
|
||||||
|
self.Relu = nn.ReLU(inplace=True)
|
||||||
|
self.maxpooling=nn.MaxPool2d(3,stride=2, padding=1)
|
||||||
|
|
||||||
|
self.shift1=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)
|
||||||
|
self.shift1.weight=kernel_shift_ini(n,m)
|
||||||
|
self.add1 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)
|
||||||
|
self.add1.weight=kernel_add_ini(n,m)
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
self.shift2=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)
|
||||||
|
self.shift2.weight=kernel_shift_ini(n,m)
|
||||||
|
self.add2 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)
|
||||||
|
self.add2.weight=kernel_add_ini(n,m)
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
self.shift3=nn.Conv2d(n*m,n*m,kernel_size=3,stride=1,padding=1)
|
||||||
|
self.shift3.weight=kernel_shift_ini(n,m)
|
||||||
|
self.add3 = nn.Conv2d(n*m,int(n/2)*int(m/2),kernel_size=1,stride=1,padding=0)
|
||||||
|
self.add3.weight=kernel_add_ini(n,m)
|
||||||
|
|
||||||
|
|
||||||
|
def get_descripteur(self,img,using_cuda):
|
||||||
|
descripteur_img=self.Relu(self.conv1(img))
|
||||||
|
b,c,h,w=descripteur_img.shape
|
||||||
|
couche_constante=0.5*torch.ones([1,1,h,w])
|
||||||
|
if using_cuda:
|
||||||
|
couche_constante=couche_constante.cuda()
|
||||||
|
descripteur_img=torch.cat((descripteur_img,couche_constante),1)
|
||||||
|
descripteur_img_norm=descripteur_img/torch.norm(descripteur_img,dim=1)
|
||||||
|
return descripteur_img_norm
|
||||||
|
|
||||||
|
def forward(self,img,frag,using_cuda):
|
||||||
|
psize=4
|
||||||
|
|
||||||
|
descripteur_input1=self.get_descripteur(img,using_cuda)
|
||||||
|
descripteur_input2=self.get_descripteur(frag,using_cuda)
|
||||||
|
|
||||||
|
b,c,h,w=frag.shape
|
||||||
|
n=int(h/psize)
|
||||||
|
m=int(w/psize)
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(m):
|
||||||
|
if i==0 and j==0:
|
||||||
|
map_corre=F.conv2d(descripteur_input1,get_patch(descripteur_input2,psize,i,j),padding=2)
|
||||||
|
else:
|
||||||
|
a=F.conv2d(descripteur_input1,get_patch(descripteur_input2,psize,i,j),padding=2)
|
||||||
|
map_corre=torch.cat((map_corre,a),1)
|
||||||
|
#shift
|
||||||
|
map_corre=self.maxpooling(map_corre)
|
||||||
|
map_corre=self.shift1(map_corre)
|
||||||
|
map_corre=self.add1(map_corre)
|
||||||
|
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
map_corre=self.maxpooling(map_corre)
|
||||||
|
map_corre=self.shift2(map_corre)
|
||||||
|
map_corre=self.add2(map_corre)
|
||||||
|
|
||||||
|
|
||||||
|
n=int(n/2)
|
||||||
|
m=int(m/2)
|
||||||
|
if n>=2 and m>=2:
|
||||||
|
map_corre=self.maxpooling(map_corre)
|
||||||
|
map_corre=self.shift3(map_corre)
|
||||||
|
map_corre=self.add3(map_corre)
|
||||||
|
|
||||||
|
|
||||||
|
b,c,h,w=map_corre.shape
|
||||||
|
map_corre=map_corre/(map_corre.max())
|
||||||
|
#map_corre=(F.softmax(map_corre.reshape(1,1,h*w,1),dim=2)).reshape(b,c,h,w)
|
||||||
|
return map_corre
|
||||||
|
|
||||||
|
|
||||||
|
# In[4]:
|
||||||
|
|
||||||
|
|
||||||
|
# Les fonctions de ce bloc sont utilisées pour appliquer le réseau à des fragments (pas à des patchs carrés)
|
||||||
|
|
||||||
|
|
||||||
|
# Cette fonction permet de sélectionner un ensemble de patchs carrés à partir d'un fragment
|
||||||
|
# Le paramètre “frag_size” fait ici référence à la taille du patch d'entrée carré (16 * 16)
|
||||||
|
# Le paramètre “seuillage” limite la proportion de pixels non noirs dans chaque patch
|
||||||
|
# Le paramètre “limite” peut limiter le nombre de correctifs trouvés dans chaque fragment
|
||||||
|
def get_patch_list(frag,frag_size,limite,seuillage):
|
||||||
|
n=0
|
||||||
|
m=0
|
||||||
|
h,w,c=frag.shape
|
||||||
|
patch_list=[]
|
||||||
|
position_list=[]
|
||||||
|
for i in range(4):
|
||||||
|
if len(patch_list)>limite and limite!=0:
|
||||||
|
break
|
||||||
|
for j in range(4):
|
||||||
|
if len(patch_list)>limite and limite!=0:
|
||||||
|
break
|
||||||
|
n_offset=i*4 # n offset
|
||||||
|
m_offset=j*4 # m offset
|
||||||
|
n=0
|
||||||
|
while n+frag_size+n_offset<h:
|
||||||
|
m=0
|
||||||
|
while m+frag_size+m_offset<w:
|
||||||
|
patch=frag[n+n_offset:n+frag_size+n_offset,m+m_offset:m+frag_size+m_offset,:]
|
||||||
|
if test_fragment32_32(patch,seuillage):
|
||||||
|
patch_list.append(patch)
|
||||||
|
position_list.append([int((n+frag_size/2)+n_offset),int((m+frag_size/2)+m_offset)])
|
||||||
|
m=m+frag_size
|
||||||
|
n=n+frag_size
|
||||||
|
return patch_list,position_list
|
||||||
|
|
||||||
|
# Entrez du fragment et de la fresque, exécutez le réseau
|
||||||
|
def run_net_v3(net,img,frag,frag_size,limite,seuillage,using_cuda,rotation):
|
||||||
|
Img=Image.fromarray(frag)
|
||||||
|
frag=np.array(Img.rotate(rotation))
|
||||||
|
img_tensor=img2tensor(img)
|
||||||
|
|
||||||
|
# la collection de patchs carrée dans le fragement "sont frag_list[]"
|
||||||
|
# La position de leur centre dans la fragment sont "position_frag[]"
|
||||||
|
frag_list,position_frag=get_patch_list(frag,frag_size,limite,seuillage)
|
||||||
|
if using_cuda:
|
||||||
|
img_tensor=img_tensor.cuda()
|
||||||
|
|
||||||
|
score_list=[]
|
||||||
|
coordonnee_list=[]
|
||||||
|
|
||||||
|
# Pour chaque patch carré dans la collection, effectuez un calcul en réseau de leur position
|
||||||
|
# Le résultat est placé en "coordonnee_list[]"
|
||||||
|
# "score_list[]" pas utile dans notre programme
|
||||||
|
for i in range(len(frag_list)):
|
||||||
|
frag_tensor=img2tensor(frag_list[i])
|
||||||
|
if using_cuda:
|
||||||
|
frag_tensor=frag_tensor.cuda()
|
||||||
|
res=net.forward(img_tensor,frag_tensor,using_cuda)
|
||||||
|
if using_cuda:
|
||||||
|
res=res.cpu()
|
||||||
|
score,po_h,po_w=show_coordonnee(res)
|
||||||
|
coordonnee_list.append([po_h,po_w])
|
||||||
|
score_list.append(score)
|
||||||
|
h_img,w_img,c=img.shape
|
||||||
|
position=[]
|
||||||
|
|
||||||
|
# Mettez les paires correspondante en "position[]"
|
||||||
|
# [x,y,x',y']
|
||||||
|
# La position (x,y) dans le fragment correspond à la position (x',y') dans la fresque
|
||||||
|
for i in range(len(coordonnee_list)):
|
||||||
|
x0=position_frag[i][0]
|
||||||
|
y0=position_frag[i][1]
|
||||||
|
x1=int(round(h_img*coordonnee_list[i][0]))
|
||||||
|
y1=int(round(w_img*coordonnee_list[i][1]))
|
||||||
|
position.append([x0,y0,x1,y1])
|
||||||
|
return score_list,position
|
||||||
|
|
||||||
|
|
||||||
|
# In[12]:
|
||||||
|
|
||||||
|
|
||||||
|
# Cette partie du code consiste à implémenter l'algorithme RANSAC amélioré
|
||||||
|
|
||||||
|
# Ecrire le point sous forme [x,y,1]T,
|
||||||
|
# Utilisé pour construire l'équation de la matrice de transformation
|
||||||
|
def creer_point(x,y):
|
||||||
|
p=np.zeros((3,1))
|
||||||
|
p[0][0]=x
|
||||||
|
p[1][0]=y
|
||||||
|
p[2][0]=1
|
||||||
|
return p
|
||||||
|
|
||||||
|
# Sélectionnez aléatoirement n points sans duplication à partir de M points
|
||||||
|
def selectionner_points(n,M):
|
||||||
|
table=[]
|
||||||
|
for i in range(M):
|
||||||
|
table.append(i)
|
||||||
|
result=[]
|
||||||
|
for i in range(n):
|
||||||
|
index=random.randint(0,M-i-1)
|
||||||
|
result.append(table[index])
|
||||||
|
table[index]=table[M-1-i]
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Selon la matrice de transformation affine, calculer la position centrale transformée et l'angle de rotation
|
||||||
|
def position_rotation(h,centre_frag):
|
||||||
|
centre=h@centre_frag
|
||||||
|
cos_rot=(h[0][0]+h[1][1])/2
|
||||||
|
sin_rot=(h[1][0]-h[0][1])/2
|
||||||
|
tan_rot=sin_rot/(cos_rot+0.0000001)
|
||||||
|
if cos_rot>0:
|
||||||
|
rot_frag=math.atan(tan_rot)*(180/pi)
|
||||||
|
else:
|
||||||
|
rot_frag=math.atan(tan_rot)*(180/pi)+180
|
||||||
|
rot_frag=-rot_frag
|
||||||
|
if rot_frag>0:
|
||||||
|
rot_frag-=360
|
||||||
|
return centre[0][0],centre[1][0],rot_frag
|
||||||
|
|
||||||
|
# Vérifiez les résultats de Ransac en avec des changements de distance euclidienne
|
||||||
|
def test_frag(inline,frag,fres):
|
||||||
|
itera=10
|
||||||
|
frag_inline=[]
|
||||||
|
fres_inline=[]
|
||||||
|
# Metter les coordonnées du point inline dans "frag_inline[]",et "fres_inline[]"
|
||||||
|
for i in range(np.size(inline,0)):
|
||||||
|
if inline[i]==1:
|
||||||
|
frag_inline.append([frag[i][0],frag[i][1]])
|
||||||
|
fres_inline.append([fres[i][0],fres[i][1]])
|
||||||
|
p=[]
|
||||||
|
|
||||||
|
# Faites une boucle dix fois,
|
||||||
|
# sélectionnez à chaque fois deux paires correspondantes inline
|
||||||
|
# calculer le changement de leur distance euclidienne
|
||||||
|
for i in range(itera):
|
||||||
|
point_test=selectionner_points(2,np.size(frag_inline,0))
|
||||||
|
diff_x_frag=frag_inline[point_test[1]][0]-frag_inline[point_test[0]][0]
|
||||||
|
diff_y_frag=frag_inline[point_test[1]][1]-frag_inline[point_test[0]][1]
|
||||||
|
diff_frag=sqrt(pow(diff_x_frag,2)+pow(diff_y_frag,2))
|
||||||
|
|
||||||
|
diff_x_fres=fres_inline[point_test[1]][0]-fres_inline[point_test[0]][0]
|
||||||
|
diff_y_fres=fres_inline[point_test[1]][1]-fres_inline[point_test[0]][1]
|
||||||
|
diff_fres=sqrt(pow(diff_x_fres,2)+pow(diff_y_fres,2))
|
||||||
|
if diff_frag !=0:
|
||||||
|
fsf=diff_fres/diff_frag
|
||||||
|
p.append([fsf])
|
||||||
|
result=np.mean(p)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def frag_match(frag,img,position):
|
||||||
|
|
||||||
|
frag_size=frag.shape
|
||||||
|
centre_frag=creer_point(frag_size[0]/2,frag_size[1]/2)
|
||||||
|
|
||||||
|
retained_matches = []
|
||||||
|
frag=[]
|
||||||
|
fres=[]
|
||||||
|
|
||||||
|
for i in range(len(position)):
|
||||||
|
frag.append([float(position[i][0]),float(position[i][1])])
|
||||||
|
fres.append([float(position[i][2]),float(position[i][3])])
|
||||||
|
|
||||||
|
if np.size(frag)>0:
|
||||||
|
# Calculer la matrice de transformation affine à l'aide de la méthode Ransac
|
||||||
|
h,inline=cv2.estimateAffinePartial2D(np.array(frag),np.array(fres))
|
||||||
|
# Si “h” n'est pas sous la forme de matrice 2 * 3, la matrice de transformation affine n'est pas trouvée
|
||||||
|
if np.size(h)!=6:
|
||||||
|
return ([-1])
|
||||||
|
else:
|
||||||
|
x,y,rot=position_rotation(h,centre_frag)
|
||||||
|
pourcenttage=sum(inline)/np.size(frag,0)
|
||||||
|
# Le nombre de points inline doit être supérieur à un certain nombre
|
||||||
|
if sum(inline)>3:
|
||||||
|
p=test_frag(inline,frag,fres)
|
||||||
|
# La distance euclidienne entre les points correspondants ne doit pas trop changer,
|
||||||
|
# sinon cela prouve que le résultat de Ransac est incorrect
|
||||||
|
# ici,le changement de la distance euclidienne sont entre 0.7 et 1.3
|
||||||
|
if abs(p-1)<0.3:
|
||||||
|
# Ce n'est qu'alors que Ransac renvoie le résultat correct
|
||||||
|
return([round(y),round(x),round(rot,3)])
|
||||||
|
else:
|
||||||
|
return ([-2])
|
||||||
|
else:
|
||||||
|
return ([-3])
|
||||||
|
else:
|
||||||
|
return ([-4])
|
||||||
|
|
||||||
|
|
||||||
|
# In[14]:
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
|
||||||
|
frag_size=16
|
||||||
|
using_cuda=True
|
||||||
|
net=load_net("./net_trainned6000")
|
||||||
|
img_test=cv2.imread("./fresque0.ppm")
|
||||||
|
|
||||||
|
result=[]
|
||||||
|
for n in range(315):
|
||||||
|
if n<10:
|
||||||
|
frag_test=cv2.imread("./frag_eroded0/frag_eroded_000"+str(n)+".ppm")
|
||||||
|
elif n<100:
|
||||||
|
frag_test=cv2.imread("./frag_eroded0/frag_eroded_00"+str(n)+".ppm")
|
||||||
|
else:
|
||||||
|
frag_test=cv2.imread("./frag_eroded0/frag_eroded_0"+str(n)+".ppm")
|
||||||
|
|
||||||
|
# Faites pivoter les pièces de 20 degrés à chaque fois pour correspondre, répétez 18 fois
|
||||||
|
for i in range(18):
|
||||||
|
rotation=20*i
|
||||||
|
score_list,position=run_net_v3(net,img_test,frag_test,frag_size,60,0.7,using_cuda,rotation)
|
||||||
|
frag_position=frag_match(frag_test,img_test,position)
|
||||||
|
# Lorsque Ransac obtient le bon résultat, sortez de la boucle
|
||||||
|
if len(frag_position)==3:
|
||||||
|
rotation_base=i*20
|
||||||
|
break
|
||||||
|
# Enregistrez les fragments correctement localisés dans "result[]"
|
||||||
|
if len(frag_position)==3:
|
||||||
|
frag_position[2]=rotation_base-360-frag_position[2]
|
||||||
|
if frag_position[2]>0:
|
||||||
|
frag_position[2]=frag_position[2]-360
|
||||||
|
result.append([n,frag_position[0],frag_position[1],round(frag_position[2],3)])
|
||||||
|
|
||||||
|
|
||||||
|
# In[15]:
|
||||||
|
|
||||||
|
|
||||||
|
result
|
||||||
|
|
25
readme.txt
Normal file
25
readme.txt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
Notre code comprend deux parties.
|
||||||
|
|
||||||
|
1.L'apprentissage de réseaux neuronaux
|
||||||
|
"Apprentissage_MSELoss_avec_GPU.ipynb"
|
||||||
|
|
||||||
|
2.La fonctionnement de réseaux neuronaux
|
||||||
|
"Frag_Match_avec_rotation.ipynb"
|
||||||
|
***************************************************************************
|
||||||
|
Ce programme.ipynb peut être exécuté avec jupyter-notebook.
|
||||||
|
|
||||||
|
1.Ctrl+Alt+T Ouvrir le terminal
|
||||||
|
2.Input "jupyter-notebook" peut ouvrir une interface
|
||||||
|
3.Cliquez sur le programme pour l'ouvrir.
|
||||||
|
|
||||||
|
Il est recommandé d 'utiliser le programme jupyter-Notebook, qui non seulement fonctionne par blocs, mais aussi est configuré pour tous les environnements.
|
||||||
|
***************************************************************************
|
||||||
|
Si vous voulez utiliser le programme.py
|
||||||
|
"Apprentissage_MSELoss_avec_GPU.py"
|
||||||
|
et
|
||||||
|
"Frag_Match_avec_rotation.py"
|
||||||
|
|
||||||
|
1.Ctrl+Alt+T Ouvrir le terminal,Vous pouvez voir un "(base)" devant la ligne de commande.
|
||||||
|
2.Input instruction “conda activate py37” ,alors (base) va devenir (py37).
|
||||||
|
3.J'ai configuré l' environnement de py37 pour qu 'il fonctionne directement dans cet environnement.
|
||||||
|
|
Loading…
Reference in a new issue