[Python] Kombiniert zugeschnittene Bilder automatisch und nahtlos

Was du machen willst

Die beiden zugeschnittenen Bilder werden ** automatisch ** kombiniert, sodass die Nähte natürlich sind. 画像結合_イメージ_re.jpg

Idee

Ausgehend von den Rändern des oberen und unteren Bildes wird der Bereich allmählich verengt und verglichen. Der Bereich mit dem höchsten Übereinstimmungsgrad wird als gemeinsamer Bereich kombiniert. 画像結合_アルゴイメージ_re.jpg

Annahme

Flow (was ich studiert habe)

    1. Bildtrimmen
  1. Bilder vergleichen
    1. Bilder verketten
  2. Um den Rechenaufwand zu reduzieren

1. 1. Bildtrimmen

Dieses Mal habe ich "Image.crop ()" verwendet, um das Kissenformat zu kürzen.

Image.crop((X-Koordinate des linken Trimmendes,Top y Koordinate,X-Koordinate ganz rechts,Untere y-Koordinate))

Beachten Sie, dass das Argument als Taple angegeben werden muss und ** Klammern "(" ")" dupliziert werden **. Um den Rechenaufwand so weit wie möglich zu reduzieren, wird die kleinere der oberen und unteren Seite als Vergleichsstartbereich festgelegt und um 1 Pixel reduziert. (Wenn im oberen Code das obere Bild groß ist, wird der Höhenunterschied in der Variablen dif_h gespeichert und zur Angabe der oberen Trimmkoordinaten verwendet.)

2. Bilder vergleichen

Das zugeschnittene Bild wird in das OpenCV-Format konvertiert und die Bilder werden mit "cv2.matchTemplate ()" verglichen.

cv2.matchTemplate(Bild zum Vergleichen 1,Bild 2 zum Vergleichen,Matching-Modus)

Es scheint verschiedene Übereinstimmungsmodi zu geben, aber ich denke, dass alles (mit Ausnahmen) für diese Anwendung in Ordnung ist, also habe ich das standardähnliche "cv2.TM_CCOEFF_NORMED" verwendet. Da die Ausgabe von matchTemplate ein Graustufenbild ist (wahrscheinlich), das den Übereinstimmungsgrad in hell und dunkel anzeigt, wird der Maximalwert = das Übereinstimmungsbewertungsergebnis dieses Bildes unter Verwendung von "cv2.minMaxLoc ()" erhalten.

cv2.minMaxLoc(Graustufenbild zur Auswertung)[1]

Für den Rückgabewert von minmaxLoc wird der Maximalwert in der Sekunde gespeichert, sodass der Maximalwert mit [1] herausgenommen wird. (Details zum Abgleich von Bildvorlagen finden Sie auf dieser Seite Wird erklärt in)

Wiederholen Sie die obigen Schritte mit einer for-Anweisung, während Sie den Bereich ändern, um die Stelle zu finden, an der das übereinstimmende Bewertungsergebnis maximiert wird.

3. 3. Bilder verketten

Ich habe von dieser Seite zitiert. https://note.nkmk.me/python-pillow-concat-images/

def get_concat_v(im1, im2):
    dst = Image.new('RGB', (im1.width, im1.height + im2.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

Erstellen Sie im Bild im Kissenformat einen Bereich mit "Image.new ()" und fügen Sie das Bild ein, das mit "Image.paste ()" verbunden werden soll.

4. Um den Rechenaufwand zu reduzieren

Wie Sie sehen können, ** Je größer das Bild, desto länger dauert es **. Dieses Mal ist es grau skaliert, und das kleinere des oberen und des unteren Bildes wird als Größe des Vergleichsstartbereichs festgelegt. Obwohl diesmal nicht übernommen, kann der Rechenaufwand meiner Meinung nach reduziert werden, indem die Größe und der Vergleich von Bildern geändert, der zu vergleichende Bereich begrenzt und der Vergleich beendet wird, wenn ein bestimmter Bewertungswert überschritten wird.

Code abgeschlossen

import numpy as np
from PIL import Image
import cv2

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
def auto_img_concat_v(upper_img, under_img):

    max_res_num = 0  #Speichern Sie den Maximalwert des übereinstimmenden Bewertungsergebnisses
    over_pixel = 0  #Speichern Sie die Anzahl der überlappenden Pixel bei der maximalen Übereinstimmungsbewertung

    img_w = upper_img.width
    upper_h = upper_img.height
    under_h = under_img.height

    compare_height = min(upper_h, under_h)  #Anzahl der zu vergleichenden Pixel (Höhe)

    #Wenn die Höhe des obigen Bildes hoch ist, erhalten Sie die Differenz (andernfalls 0)
    dif_h = (upper_h - under_h) if upper_h > under_h else 0

    for i in range(1, compare_height):

        search_img = upper_img.crop((0, i + dif_h, img_w, upper_h))  #Schneiden Sie das obige Bild
        target_img = under_img.crop((0, 0, img_w, compare_height - i))  #Schneiden Sie das Bild unten

        search_np = np.array(search_img, dtype=np.uint8)  #Bild in Array konvertieren (oberes Bild)
        cv_search_img = cv2.cvtColor(search_np, cv2.COLOR_RGB2GRAY)  #Graustufen (oberes Bild)

        target_np = np.array(target_img, dtype=np.uint8)  #〃 (Bild unten)
        cv_target_img = cv2.cvtColor(target_np, cv2.COLOR_RGB2GRAY)  #〃 (Bild unten)

        res = cv2.matchTemplate(
            cv_search_img, cv_target_img, cv2.TM_CCOEFF_NORMED)  #Übereinstimmende Bewertung (Ausgabe ist ein Graustufenbild, das Ähnlichkeit zeigt)
        res_num = cv2.minMaxLoc(res)[1]  #Erhalten Sie eine passende Bewertung numerisch
        print(res_num, "\n", i)

        if max_res_num < res_num:  #Ermitteln Sie den Maximalwert des übereinstimmenden Bewertungsergebnisses
            max_res_num = res_num
            over_pixel = target_img.height  #Ermitteln Sie die Anzahl der überlappenden Pixel mit dem maximal übereinstimmenden Bewertungswert

    print("\n", max_res_num, "\n", over_pixel)

    if max_res_num > 0.98:  #Wenn der Auswertungswert über einem bestimmten Wert liegt, verbinden Sie die Verarbeitung
        result_img = get_concat_v(upper_img.crop(
            (0, 0, img_w, upper_h - over_pixel)), under_img)  #Bildkombination
        return result_img
    else:
        print("Bildkombination fehlgeschlagen")
        
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
#Funktion zum Verketten von Bildern (vertikale Richtung)
def get_concat_v(im1, im2):
    dst = Image.new('RGB', (im1.width, im1.height + im2.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
if __name__ == "__main__":
    upper = Image.open(r"C:\Users\aaa\Desktop\Danbo_upper.jpg ")
    under = Image.open(r"C:\Users\aaa\Desktop\Danbo_under.jpg ")
    concat_img = auto_img_concat_v(upper, under)

    if concat_img:
        concat_img.show()

Ergebnis

結果re.jpg Ich konnte mich gut kombinieren.

Zukunftspläne

Es gibt Probleme wie einen hohen Rechenaufwand und Inkompatibilität mit Bildern, die in horizontaler Richtung nicht übereinstimmen. Ich konnte tun, was ich vorerst tun wollte. In Zukunft möchte ich ein Tool erstellen, das gescrollte Bildschirme in Kombination mit pyautog automatisch verbindet.

Recommended Posts

[Python] Kombiniert zugeschnittene Bilder automatisch und nahtlos
Bilder mit Pupil, Python und OpenCV aufnehmen
Generiere automatisch Bilder von Koala und Bär
Importieren und Exportieren von GeoTiff-Bildern mit Python
Suchen und laden Sie YouTube-Videos automatisch mit Python herunter
Erstellen Sie automatisch Wort- und Excel-Berichte mit Python
Teilen Sie Python-Bilder und ordnen Sie sie nebeneinander an
Fügen Sie Bilder mit Python + α automatisch in Powerpo-Materialien ein
Übersetzen Sie DeepL automatisch mit Python und Selen ins Englische
[Python] Komprimieren und dekomprimieren
Python- und Numpy-Tipps
[Python] Pip und Wheel
Python Iterator und Generator
Python-Pakete und -Module
Vue-Cli- und Python-Integration
Führen Sie die Python-Datei automatisch aus
Ruby, Python und Map
Python-Eingabe und Ausgabe
Python und Ruby teilen sich
Python asyncio und ContextVar
Ich habe versucht, mit Python Modebilder und Textsätze zu [kratzen].
[Einführung in Python] Kombinieren Sie Nikkei-Durchschnitts- und NY Dow-CSV-Daten
So melden Sie sich mit Python bei AtCoder an und senden automatisch
Hinweise zum Lesen und Schreiben von float32 TIFF-Bildern mit Python