[PYTHON] Bildanpassung und Punktgruppenausrichtung mit PatchMatch

Lass uns mit PatchMatch spielen.

Was ist PatchMatch? (Grob)

ダウンロード.png

Eine grobe Übersicht über PatchMatch ist Finde Ähnlichkeiten in einem Bild und einem anderen! Es ist ein Algorithmus namens.

In Photoshop werden bestimmte Teile aus einem Bild gelöscht. hqdefault.jpg

Die Idee der Basis ist wie folgt.

1. 1. Stellen Sie die Entsprechung zwischen allen Pixeln des Hauptbilds und des Zielbilds zufällig ein.
Letztendlich wird dieses Korrespondenzpaar ein Paar ähnlicher Pixel sein.

2. Basierend auf der Idee, dass benachbarte Pixel wahrscheinlich Teile desselben Teils sind
Vergleichen Sie die aktuelle Ähnlichkeit mit der Ähnlichkeit benachbarter Pixel.
Wenn es größer ist (höhere Ähnlichkeit) als die aktuell eingestellte Ähnlichkeit, wird es auf diesen Wert aktualisiert.

3. 3. Wiederholen Sie unten

PatchMatch wird manchmal wie Template Matching verwendet. Außerdem basiert auf der gemeinsamen Idee, dass benachbarte Teile gleich sein werden Die gleiche Seite ist die gleiche Tiefe! Unter diesem Gesichtspunkt wird Colmap verwendet, um die Tiefe abzuschätzen. Es ist eine Theorie, die allgemein anwendbar zu sein scheint. tester.png

Versuchen Sie, die beiden Bilder abzugleichen.

Der wichtige Punkt in diesem Artikel ist Wenn Sie PatchMatch verwenden, können Sie ähnliche Teile in zwei Bildern sehen. Dies bedeutet, dass es auf Pixelebene beurteilt werden kann.

ダウンロード.jpeg

Da der Feature-Point-Abgleich ein Prozess mit Feature-Punkten ist, Es wird leicht von der Umgebung beeinflusst, und wenn die Anzahl der Feature-Punkte gering ist, schlägt die Verarbeitung fehl.

Mit PatchMatch können Sie die Anzahl der Übereinstimmungen erhöhen, oder? Lassen Sie uns in diesem Sinne mit der folgenden Verarbeitung spielen.

1. Führen Sie Patch Match mit 2 Bildern aus. Berechnen Sie mit SAD einen Satz von Pixeln, die allen Pixeln ähnlich sind
2. Führen Sie Ransac für die beiden übereinstimmenden Paare aus. Ausreißer entfernen.

Mal sehen, wie genau und in vielen Fällen PatchMatch abgeglichen werden kann. Als nächstes werde ich versuchen, Punkte mithilfe des RGBD-Bildes und der Informationen zu internen Parametern zu gruppieren und auszurichten. Wenn Sie gut zusammenpassen können, Möglicherweise können Sie sich gut ausrichten, ohne von Rauschen betroffen zu sein.

3. 3. Punktgruppierung aus einem Satz extrahierter Pixel
4. Richten Sie die extrahierten Punkte aus
Richten Sie sich mit dem Parameter 5.4 an der Hauptpunktgruppe aus

Code

https://github.com/MingtaoGuo/PatchMatch

Der obige Code wird für den Kernverarbeitungsteil ausgeliehen. Wenn Sie es so verwenden, wie es ist, wird Marias Gesicht zu einem Avatar Ändern Sie diese Option, um nur das Ausführungsergebnis von PatchMatch zu verwenden.

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]])

    #Wenden Sie als Nächstes die ähnlichen Pixel an, die durch Patch Match erhalten wurden.
    #Ein Bild, das Bild A unter Verwendung der Pixel von Bild B rekonstruiert
    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!="":
        #Wenn Bildtiefen-Daten / interne Parameter vorhanden sind,
        #Versuchen Sie, Punkte zu gruppieren und mit übereinstimmenden Informationen auszurichten.
        #Nur PatchMatch A Die folgende Verarbeitung ist nicht erforderlich

        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:Nicht kompatibel"

        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
            #Tiefendatenerfassung
            in_csvPath = path
            with open(in_csvPath) as f:
                reader = csv.reader(f)
                csvlist = [row for row in reader]

            return csvlist

        #Tiefendaten(CSV)
        Adepthlist = getDepthCSPerView(AdepthPath)
        Bdepthlist = getDepthCSPerView(BdepthPath)
        pclA=[]
        pclB=[]
        colorA=[]
        colorB=[]

        ALLpclA=[]
        ALLpclB=[]
        ALLcolorA=[]
        ALLcolorB=[]

        #Der Tiefenwert ist 1.Stellen Sie die Reichweite von 5 m zur Punktgruppe wieder her
        depth_threshold = 1.5  #Meter
        depth_scale = 0.0002500000118743628
        threshold = depth_threshold / depth_scale

        #Interne Parameter der RGB-Kamera
        # 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)

Ergebnis: Bildanpassung

Ich werde es versuchen.

outputMerge.jpg

Das ist

outputMatchAddLine.jpg

so was. Ich verstehe nicht wirklich. Extrahiert und zeigt die übereinstimmenden Pixel an und die Ausreißer wurden durch Ransac entfernt.

outputMatch.jpg

Ich weiß nicht mehr als nein. Aber irgendwie scheinen die Formen zu passen. Ich bin der Meinung, dass es zur Verfolgung, Bewegungserkennung usw. verwendet werden kann.

Ergebnis: Punktgruppenausrichtung

Ich weiß nicht, ob die Antwort mit dem vorherigen Ergebnis übereinstimmt, aber Lassen Sie uns die Punktgruppen der beiden Gesichtspunkte basierend auf den extrahierten Informationen ausrichten.

3. 3. Punktgruppierung aus einem Satz extrahierter Pixel
4. Richten Sie die extrahierten Punkte aus
Richten Sie sich mit dem Parameter 5.4 an der Hauptpunktgruppe aus

Das ist 無題.png

so was. 無題.png

Hmm! Es ist subtil! das ist alles.

[Zusatz] 無題.png

Das vorherige Ergebnis war in der Tiefe nicht genau Mit verschiedenen Daten validiert.

Es ist eine Gruppe von Punkten voller Lärm, Liegt es daran, dass der zweidimensionale Abgleich erfolgreich ist? Ich konnte natürlich gut zusammenpassen.

Ich habe nur Ransac verwendet, um Ausreißer während des Abgleichs zu entfernen. Da ich eine Gruppe von Punkten erstellt habe, werde ich beim nächsten Mal den Abstand der übereinstimmenden Punkte berücksichtigen Versuchen Sie, die Ausreißer zu entfernen.

Recommended Posts

Bildanpassung und Punktgruppenausrichtung mit PatchMatch
Punktwolke mit Pfeffer
Bildverarbeitung mit MyHDL
Bilderkennung mit Keras
Bildverarbeitung mit Python
Ich habe versucht, die affine Matrix in der Bildausrichtung (Feature-Point-Matching) mithilfe der affinen Transformation zu finden
Bildverarbeitung mit PIL
Erfassung der 3D-Punktgruppe mit Pepper of Softbank (Choregraphe, Python)