Jouons avec PatchMatch.
Un aperçu approximatif de PatchMatch est Trouvez des similitudes entre une image et une autre! C'est un algorithme appelé.
Dans Photoshop, il est utilisé pour effacer des parties spécifiques d'une image.
L'idée de la base est la suivante.
1. 1. Définissez aléatoirement la correspondance entre tous les pixels de l'image principale et l'image cible.
Finalement, cette paire de correspondances sera une paire de pixels similaires.
2. Basé sur l'idée que les pixels adjacents sont susceptibles de faire partie de la même pièce
Comparez la similitude actuelle avec la similitude des pixels adjacents,
S'il est plus grand que la similitude actuellement définie (similarité plus élevée), il est mis à jour à cette valeur.
3. 3. Répétez ci-dessous
PatchMatch est parfois utilisé comme correspondance de modèle, En outre, sur la base de l'idée commune que les pièces adjacentes seront les mêmes Le même côté est la même profondeur! De ce point de vue, Colmap est utilisé pour estimer la profondeur. C'est une théorie qui semble être largement applicable.
Le point important de cet article est Si vous utilisez PatchMatch, vous pouvez voir des parties similaires dans deux images. Cela signifie qu'il peut être jugé au niveau du pixel.
Lorsque vous faites de la SfM, le mot correspondant à un point caractéristique apparaît souvent, Étant donné que la correspondance des points caractéristiques est un processus avec des points caractéristiques, Il est facilement affecté par l'environnement et si le nombre de points caractéristiques est petit, le traitement échouera.
Avec PatchMatch, vous pouvez augmenter le nombre de correspondances, non? Dans cet esprit, jouons avec le traitement suivant.
1. Exécutez Patch Match avec 2 images. Calculer un ensemble de pixels similaire à tous les pixels avec SAD
2. Exécutez Ransac sur les deux paires correspondantes. Supprimez les valeurs aberrantes.
Voyons avec quelle précision et de nombreux cas peuvent être mis en correspondance avec PatchMatch. Ensuite, je vais essayer de regrouper et d'aligner les points en utilisant l'image RGBD et les informations des paramètres internes. Si vous pouvez bien correspondre, Vous pourrez peut-être bien vous aligner sans être affecté par le bruit.
3. 3. Regroupement de points à partir d'un ensemble de pixels extraits
4. Aligner les points extraits
Aligner avec le groupe de points principal en utilisant le paramètre de 5.4
https://github.com/MingtaoGuo/PatchMatch
Le code ci-dessus est emprunté pour la partie de traitement de base. Si vous l'utilisez tel quel, le visage de Maria deviendra un avatar, donc Modifiez pour n'utiliser que le résultat de l'exécution de PatchMatch.
reconstruction.py
def reconstruction(f, A, B,AdepthPath="",BdepthPath=""):
A_h = np.size(A, 0)
A_w = np.size(A, 1)
temp = np.zeros_like(A)
srcA=[]
dstB=[]
colorA=np.zeros_like(A)
colorB=np.zeros_like(A)
for i in range(A_h):
for j in range(A_w):
colorA[i, j, :] = A[[i],[j],:]
colorB[i, j, :] = B[f[i, j][0], f[i, j][1], :]
temp[i, j, :] = B[f[i, j][0], f[i, j][1], :]
srcA.append([i,j])
dstB.append([f[i, j][0], f[i, j][1]])
#Ensuite, appliquez les pixels similaires obtenus par Patch Match.
#Une image qui reconstruit l'image A en utilisant les pixels de l'image B
cv2.imwrite('colorB.jpg', colorB)
cv2.imwrite('colorA.jpg', colorA)
src=np.array(srcA)
dst=np.array(dstB)
print(src.shape)
print(dst.shape)
srcA_pts = src.reshape(-1, 1, 2)
dstB_pts = dst.reshape(-1, 1, 2)
# RANSAC
print(srcA_pts.shape)
print(dstB_pts.shape)
M, mask = cv2.findHomography(srcA_pts, dstB_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
im_h = cv2.hconcat([A,B])
cv2.imwrite('outputMerge.jpg', im_h)
outputA = np.zeros_like(A)
outputB = np.zeros_like(A)
for i in range(srcA_pts.shape[0]):
if mask[i] == 0: continue
srcIm = [srcA_pts[i][0][0],srcA_pts[i][0][1]]
dstIm = [dstB_pts[i][0][0],dstB_pts[i][0][1]]
outputA[srcIm[0],srcIm[1],:]=A[srcIm[0],srcIm[1],:]
outputB[dstIm[0],dstIm[1],:]=B[dstIm[0],dstIm[1],:]
im_h = cv2.hconcat([outputA, outputB])
cv2.imwrite('outputMatch.jpg', im_h)D
im_h = cv2.hconcat([A, B])
for i in range(srcA_pts.shape[0]):
if mask[i] == 0: continue
srcIm = [srcA_pts[i][0][0],srcA_pts[i][0][1]]
dstIm = [dstB_pts[i][0][0],dstB_pts[i][0][1]]
cv2.line(im_h, (srcIm[0], srcIm[1]),
(dstIm[0]+int(1280 * 0.3), dstIm[1]),
(0, 255, 0), thickness=1, lineType=cv2.LINE_4)
cv2.imwrite('outputMatchAddLine.jpg', im_h)
if AdepthPath!="":
#S'il y a des données de profondeur d'image / des paramètres internes,
#Essayez de regrouper les points et de vous aligner sur les informations correspondantes.
#PatchMatch uniquement A Pas besoin du traitement suivant
import open3d as o3d
def CPD_rejister(source, target):
from probreg import cpd
import copy
type = 'rigid'
tf_param, _, _ = cpd.registration_cpd(source, target, type)
result = copy.deepcopy(source)
result.points = tf_param.transform(result.points)
return result, tf_param.rot, tf_param.t, tf_param.scale
def Register(pclMVS_Main, pclMVS_Target):
# CPD : step1 Run CPD for SfM Data
result, rot, t, scale = CPD_rejister(pclMVS_Target, pclMVS_Main)
# CPD : step2 Apply CPD result for MVS Data
lastRow = np.array([[0, 0, 0, 1]])
ret_R = np.array(rot)
ret_t = np.array([t])
ret_R = scale * ret_R
transformation = np.concatenate((ret_R, ret_t.T), axis=1)
transformation = np.concatenate((transformation, lastRow), axis=0)
return transformation, rot, t, scale
def getPLYfromNumpy_RGB(nplist, colorList):
# nplist = np.array(nplist)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(nplist)
pcd.colors = o3d.utility.Vector3dVector(colorList)
return pcd
def numpy2Dto1D(arr):
if type(np.array([])) != type(arr):
arr = np.array(arr)
if arr.shape == (3, 1):
return np.array([arr[0][0], arr[1][0], arr[2][0]])
if arr.shape == (2, 1):
return np.array([arr[0][0], arr[1][0]])
else:
assert False, "numpy2Dto1D:Pas compatible"
def TransformPointI2C(pixel2D, K):
X = float(float(pixel2D[0] - K[0][2]) * pixel2D[2] / K[0][0])
Y = float(float(pixel2D[1] - K[1][2]) * pixel2D[2] / K[1][1])
Z = pixel2D[2]
CameraPos3D = np.array([[X], [Y], [Z]])
return CameraPos3D
def getDepthCSPerView(path):
import csv
#acquisition de données de profondeur
in_csvPath = path
with open(in_csvPath) as f:
reader = csv.reader(f)
csvlist = [row for row in reader]
return csvlist
#données de profondeur(CSV)
Adepthlist = getDepthCSPerView(AdepthPath)
Bdepthlist = getDepthCSPerView(BdepthPath)
pclA=[]
pclB=[]
colorA=[]
colorB=[]
ALLpclA=[]
ALLpclB=[]
ALLcolorA=[]
ALLcolorB=[]
#La valeur de profondeur est 1.Restaurer la portée de 5 m au groupe de points
depth_threshold = 1.5 #Mètre
depth_scale = 0.0002500000118743628
threshold = depth_threshold / depth_scale
#Paramètres internes de la caméra RVB
# width: 1280, height: 720, ppx: 648.721, ppy: 365.417, fx: 918.783, fy: 919.136,
retK = np.array([[918.783, 0, 648.721],
[0, 919.136, 365.417],
[0, 0, 1]])
cnt = 0
for y in range(len(Adepthlist)):
for x in range(len(Adepthlist[0])):
ADepth = float(Adepthlist[y][x])
BDepth = float(Bdepthlist[y][x])
if (ADepth == 0 or ADepth > threshold) or (BDepth == 0 or BDepth > threshold):
continue
AXYZ = TransformPointI2C([x,y, ADepth], retK)
BXYZ = TransformPointI2C([x,y, BDepth], retK)
ALLpclA.append(numpy2Dto1D(AXYZ))
ALLpclB.append(numpy2Dto1D(BXYZ))
color = A[int(srcIm[0])][int(srcIm[1])]
ALLcolorA.append([float(color[0] / 255), float(color[1] / 255), float(color[2] / 255)])
color = B[int(dstIm[0])][int(dstIm[1])]
ALLcolorB.append([float(color[0] / 255), float(color[1] / 255), float(color[2] / 255)])
ALLpclA = getPLYfromNumpy_RGB(ALLpclA,ALLcolorA)
ALLpclB = getPLYfromNumpy_RGB(ALLpclB,ALLcolorB)
o3d.io.write_point_cloud("ALL_pclA_Before.ply", ALLpclA)
o3d.io.write_point_cloud("ALL_pclB_Before.ply", ALLpclB)
for i in range(srcA_pts.shape[0]):
if mask[i] == 0: continue
srcIm = [srcA_pts[i][0][0], srcA_pts[i][0][1]]
dstIm = [dstB_pts[i][0][0], dstB_pts[i][0][1]]
ADepth = float(Adepthlist[int(srcIm[0])][int(srcIm[1])])
BDepth = float(Bdepthlist[int(dstIm[0])][int(dstIm[1])])
if (ADepth == 0 or ADepth > threshold) or (BDepth == 0 or BDepth > threshold):
continue
AXYZ = TransformPointI2C([int(srcIm[1]), int(srcIm[0]), ADepth], retK)
BXYZ = TransformPointI2C([int(dstIm[1]), int(dstIm[0]), BDepth], retK)
pclA.append(numpy2Dto1D(AXYZ))
pclB.append(numpy2Dto1D(BXYZ))
color = A[int(srcIm[0])][int(srcIm[1])]
colorA.append([float(color[0] / 255), float(color[1] / 255), float(color[2] / 255)])
color = B[int(dstIm[0])][int(dstIm[1])]
colorB.append([float(color[0] / 255), float(color[1] / 255), float(color[2] / 255)])
pclA = getPLYfromNumpy_RGB(pclA,colorA)
pclB = getPLYfromNumpy_RGB(pclB,colorB)
o3d.io.write_point_cloud("pclA_Before.ply", pclA)
o3d.io.write_point_cloud("pclB_Before.ply", pclB)
trans, rot, t, scale = Register(pclA, pclB)
pclB.transform(trans)
o3d.io.write_point_cloud("pclA_After.ply", pclA)
o3d.io.write_point_cloud("pclB_After.ply", pclB)
ALLpclB.transform(trans)
o3d.io.write_point_cloud("ALL_pclA_After.ply", ALLpclA)
o3d.io.write_point_cloud("ALL_pclB_After.ply", ALLpclB)
Je vais essayer.
C'est
comme ça. Je ne comprends pas vraiment. Extrait et affiche les pixels qui ont été mis en correspondance et les valeurs aberrantes ont été supprimées par ransac.
Je ne sais pas plus que non. Mais d'une manière ou d'une autre, les formes semblent correspondre. Je pense qu'il peut être utilisé pour le suivi, la détection de mouvement, etc.
Je ne sais pas si la réponse sera la même que le résultat précédent, mais Alignons les groupes de points des deux points de vue en fonction des informations extraites.
3. 3. Regroupement de points à partir d'un ensemble de pixels extraits
4. Aligner les points extraits
Aligner avec le groupe de points principal en utilisant le paramètre de 5.4
C'est
comme ça.
Hmm! C'est subtil! c'est tout.
[Une addition]
Le résultat précédent n'était pas précis en profondeur Je l'ai vérifié avec une autre donnée.
C'est un groupe de points plein de bruit, Est-ce parce que la correspondance bidimensionnelle est réussie? J'ai pu bien correspondre naturellement.
J'ai utilisé uniquement Ransac pour supprimer les valeurs aberrantes lors de la correspondance, Puisque j'ai fait un groupe de points, la prochaine fois, je considérerai la distance des points correspondants Essayez de supprimer les valeurs aberrantes.
Recommended Posts