Bildervergleich / Pixelerfassung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
CyberspaceCobra
User
Beiträge: 2
Registriert: Montag 3. Dezember 2018, 13:18

Hallo Forum,

Ich habe folgendes Problem. Es sind 2 Bilder vorhanden, welche einen Prägeprozess von Karton im Querschnitt darstellen.
Bild1: https://picload.org/view/dcllirdp/v1_01_01.png.html
Bild2: https://picload.org/view/dcllirdw/v1_01_02.png.html

Im ersten Bild ist der Karton noch geradlinig. Im zweiten Bild sinusförmig, da er geprägt wurde.
Der Karton ist in den Bildern lila dargestellt.
Grundsätzlich soll die Verschiebung des Materials herausgefunden/dargestellt werden.

Meine Idee ist dazu markante Punkte (stark lila gefärbte Punkte) zu vergleichen. Also theoretisch dürfte es mehrere Punkte im lila gefärbten Bereich geben, welche identisch sind. Diese Pixel sollten besser kenntlich gemacht werden und in eine definierte Farbe gefärbt werden.
Zur besseren Verständnis habe ich dies manuell mit Photoshop getan.

Bild1: https://picload.org/view/dcllirdr/v1.jpg.html
Bild2: https://picload.org/view/dcllirdd/v2.jpg.html

Meine erste Frage ist, geht das auch automatisch, solche Punkte zu erkennen und einzufärben mit Python?
Eventuell müssten die Punkte auch benannt oder definiert werden.
Wenn das erfolgt ist, würde ich gerne die Bilder voneinander subtrahieren oder vergleichen, sodass dann jeweils die zusammengehörigen Punkte verbunden werden und der Vektor dann die Verschiebung darstellt.

Ich habe leider sehr wenig Erfahrung mit Programmierung, vor allem mit Python. Ich bin froh wenn ich die Bilder reinladen und anzeigen kann :lol:
Deshalb wäre meine generelle Frage, ob meine Ideen so umsetzbar sind in Python und ob jemand eventuell Codebefehle kennt für die automatische Pixelerkennung oder die Vektorenerstellung zwischen den Punkten der 2 Bilder.
Ich bin für jede Hilfe und jeden Rat dankbar!

Gruß Cyber
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Bibliothek die du dazu benutzen willst nennt sich "OpenCV", und ist fuer Python verfuegbar. Damit hast du einen ganzen Sack von Funktionen, mit denen du dein Problem bearbeiten kannst:

- Transformation in den HSV-Raum, um nach Farbe zu segmentieren.
- Tools zur Ecken-Erkennung, um Bildanteile an Kanten zu segmentieren.
- Morphologische Operationen, um diese Anteile sauber zu machen.
- Dinge wie Hough-Lines, linear fits, contour extraction und polygon-annaeherung, mit denen du dir ein Aehnlichkeitsmass bauen kannst.

Das ganze setzt aber durchaus eine ganze Menge an Programmier- und Computer-Vision-Erfahrung vorraus, wenn man das robust hinkriegen will.

Eine Alternative sind natuerlich ggf. auch maschinelle Lernverfahren, allerdings muss man dafuer auch ausreichend Trainingsdaten haben.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil ich lange nix mehr mit opencv gemacht habe - hier ein Stueck Code, welches eine korrekte Klassifikation fuer deine beiden Testbilder abliefert:

Code: Alles auswählen

import sys
from functools import wraps, partial
from collections import namedtuple, deque

import cv2
import numpy as np


Settings = namedtuple(
    "Settings",
    "Hhigh Hlow Slow Shigh Vlow Vhigh kernel_size"
)

# through clicking determined
S = 60
S_ADJUST = 20
V = 220
V_ADJUST = 20

DEFAULT_SETTINGS = Settings(
    Hhigh=130,
    Hlow=124,
    Shigh=S + S_ADJUST,
    Slow=S - S_ADJUST,
    Vhigh=V + V_ADJUST,
    Vlow=V - V_ADJUST,
    kernel_size=20,
)


def memoize(f):
    @wraps(f)
    def _d(*a, **k):
        key = a, tuple((key, value) for key, value in k.items())
        if key not in f._cache:
            f._cache[key] = f(*a, **k)
        return f._cache[key]

    f._cache = {}
    return _d


def create_hsv_preview(img):
    """
    Takes an HSV-image, and returns
    a copy where the SV components
    are maxed out, in BGR-colorspace.
    This allows to perceive the way sectioning
    in H-space  works.
    """
    hsv_preview = img.copy()
    hsv_preview[:, :, 1:] = [255, 255]
    return cv2.cvtColor(hsv_preview, cv2.COLOR_HSV2BGR)


def filter_for_color_range(roi, s):
    lower = range_array(s.Hlow, s.Slow, s.Vlow)
    upper = range_array(s.Hhigh, s.Shigh, s.Vhigh)
    return cv2.inRange(roi, lower, upper)


@memoize
def range_array(*a):
    return np.array(a, dtype="uint8")


def mouse_callback(queue, event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        queue.append((x, y))


def setup_mouse_callback(q):
    cv2.namedWindow("original")
    cv2.setMouseCallback("original", partial(mouse_callback, q))


def morph(image, size=5):
    kernel = np.ones((size, size), np.uint8)
    a = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
    return cv2.morphologyEx(a, cv2.MORPH_OPEN, kernel)


def main():
    image = cv2.imread(sys.argv[1])
    clicks = deque()
    setup_mouse_callback(clicks)
    cv2.imshow("original", image)
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    cv2.imshow("hsv", create_hsv_preview(hsv))
    filtered = filter_for_color_range(
        hsv,
        DEFAULT_SETTINGS,
    )
    cv2.imshow("filtered", filtered)

    morphed = morph(filtered, DEFAULT_SETTINGS.kernel_size)
    cv2.imshow("morphed", morphed)

    _, contours, _ = cv2.findContours(
        morphed,
        cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE,
    )
    assert len(contours) == 1

    contour = image.copy()

    epsilon = 0.001 * cv2.arcLength(contours[0], True)
    approx = cv2.approxPolyDP(contours[0], epsilon, True)
    print(len(approx))
    cv2.drawContours(contour, contours, 0, (255, 255, 0))
    cv2.drawContours(contour, [approx], 0, (0, 255, 255))
    cv2.imshow("contour", contour)

    print("gebogen" if len(approx) > 20 else "gerade")
    while True:
        key = cv2.waitKey(10)
        if key == 27:
            break
        for x, y in clicks:
            print(hsv[y,x,:])
        clicks.clear()

if __name__ == '__main__':
    main()
Laufen gelassen unter Ubuntu 18.04 python 3.6 und dem dafuer verfuegbaren OpenCV 3.
CyberspaceCobra
User
Beiträge: 2
Registriert: Montag 3. Dezember 2018, 13:18

Super das hilft mir auf jeden Fall schon mal weiter.
Danke!
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn es dir um die Verschiebung geht, muss man da noch mehr machen. Aber das Polygon das berechnet wird ist dafür schon der richtige Schritt.
Pathfinder
User
Beiträge: 3
Registriert: Samstag 29. Dezember 2018, 12:16

Servus deets,
ich habe jetzt längers versucht diesen Code iwie zum laufen zu kriegen aber bei funktioniert es einfach nicht. Ich bin ebenfalls aus der Projektgruppe, die dieses Projekt bearbeitet...also genauso ein Nichtkönner :D
Muss ich irgendwas beachten wenn ich mir den Code rauskopiere? Iwas umstellen? Wo die Bilder anlegen, einlesen?
Entschuldige falls dies doofe Fragen sind :D Kann das auch an Ubuntu/Windows liegen?

Liebe Grüße Path
__deets__ hat geschrieben: Montag 3. Dezember 2018, 18:41 Weil ich lange nix mehr mit opencv gemacht habe - hier ein Stueck Code, welches eine korrekte Klassifikation fuer deine beiden Testbilder abliefert:

Code: Alles auswählen

import sys
from functools import wraps, partial
from collections import namedtuple, deque

import cv2
import numpy as np


Settings = namedtuple(
    "Settings",
    "Hhigh Hlow Slow Shigh Vlow Vhigh kernel_size"
)

# through clicking determined
S = 60
S_ADJUST = 20
V = 220
V_ADJUST = 20

DEFAULT_SETTINGS = Settings(
    Hhigh=130,
    Hlow=124,
    Shigh=S + S_ADJUST,
    Slow=S - S_ADJUST,
    Vhigh=V + V_ADJUST,
    Vlow=V - V_ADJUST,
    kernel_size=20,
)


def memoize(f):
    @wraps(f)
    def _d(*a, **k):
        key = a, tuple((key, value) for key, value in k.items())
        if key not in f._cache:
            f._cache[key] = f(*a, **k)
        return f._cache[key]

    f._cache = {}
    return _d


def create_hsv_preview(img):
    """
    Takes an HSV-image, and returns
    a copy where the SV components
    are maxed out, in BGR-colorspace.
    This allows to perceive the way sectioning
    in H-space  works.
    """
    hsv_preview = img.copy()
    hsv_preview[:, :, 1:] = [255, 255]
    return cv2.cvtColor(hsv_preview, cv2.COLOR_HSV2BGR)


def filter_for_color_range(roi, s):
    lower = range_array(s.Hlow, s.Slow, s.Vlow)
    upper = range_array(s.Hhigh, s.Shigh, s.Vhigh)
    return cv2.inRange(roi, lower, upper)


@memoize
def range_array(*a):
    return np.array(a, dtype="uint8")


def mouse_callback(queue, event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        queue.append((x, y))


def setup_mouse_callback(q):
    cv2.namedWindow("original")
    cv2.setMouseCallback("original", partial(mouse_callback, q))


def morph(image, size=5):
    kernel = np.ones((size, size), np.uint8)
    a = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
    return cv2.morphologyEx(a, cv2.MORPH_OPEN, kernel)


def main():
    image = cv2.imread(sys.argv[1])
    clicks = deque()
    setup_mouse_callback(clicks)
    cv2.imshow("original", image)
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    cv2.imshow("hsv", create_hsv_preview(hsv))
    filtered = filter_for_color_range(
        hsv,
        DEFAULT_SETTINGS,
    )
    cv2.imshow("filtered", filtered)

    morphed = morph(filtered, DEFAULT_SETTINGS.kernel_size)
    cv2.imshow("morphed", morphed)

    _, contours, _ = cv2.findContours(
        morphed,
        cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE,
    )
    assert len(contours) == 1

    contour = image.copy()

    epsilon = 0.001 * cv2.arcLength(contours[0], True)
    approx = cv2.approxPolyDP(contours[0], epsilon, True)
    print(len(approx))
    cv2.drawContours(contour, contours, 0, (255, 255, 0))
    cv2.drawContours(contour, [approx], 0, (0, 255, 255))
    cv2.imshow("contour", contour)

    print("gebogen" if len(approx) > 20 else "gerade")
    while True:
        key = cv2.waitKey(10)
        if key == 27:
            break
        for x, y in clicks:
            print(hsv[y,x,:])
        clicks.clear()

if __name__ == '__main__':
    main()
Laufen gelassen unter Ubuntu 18.04 python 3.6 und dem dafuer verfuegbaren OpenCV 3.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

"Geht nicht" ist keine sinnvolle Fehlerbeschreibung. Was passiert, wenn du das Skript aufrufst? Gibt es eine Fehlermeldung, wenn ja, wie genau lautet die? Bitte VOLLSTAENDIG reinkopieren, und nicht paraphrasieren.

Und das Skript muss mit dem Bild als Argument aufgerufen werden.
Pathfinder
User
Beiträge: 3
Registriert: Samstag 29. Dezember 2018, 12:16

__deets__ hat geschrieben: Samstag 29. Dezember 2018, 13:24 "Geht nicht" ist keine sinnvolle Fehlerbeschreibung. Was passiert, wenn du das Skript aufrufst? Gibt es eine Fehlermeldung, wenn ja, wie genau lautet die? Bitte VOLLSTAENDIG reinkopieren, und nicht paraphrasieren.

Und das Skript muss mit dem Bild als Argument aufgerufen werden.
Tschuldige! Mein Fehler, vergessen reinzukopieren.

Also hier wie ich deinen Code ausführe:

Code: Alles auswählen

import sys
from functools import wraps, partial
from collections import namedtuple, deque

import cv2
import numpy as np


img = cv2.imread('V1_01_01.png')
#img = cv2.imread('V1_01_02.png')

Settings = namedtuple("Settings", "Hhigh Hlow Slow Shigh Vlow Vhigh kernel_size")

# through clicking determined
S = 60
S_ADJUST = 20
V = 220
V_ADJUST = 20

DEFAULT_SETTINGS = Settings(Hhigh=130, Hlow=124, Shigh=S+S_ADJUST, Slow=S-S_ADJUST, Vhigh=V+V_ADJUST, Vlow=V-V_ADJUST, kernel_size=20)


def memoize(f):
    @wraps(f)
    def _d(*a, **k):
        key = a, tuple((key, value) for key, value in k.items())
        if key not in f._cache:
            f._cache[key] = f(*a, **k)
        return f._cache[key]

    f._cache = {}
    return _d


def create_hsv_preview(img):
    """
    Takes an HSV-image, and returns
    a copy where the SV components
    are maxed out, in BGR-colorspace.
    This allows to perceive the way sectioning
    in H-space  works.
    """
    hsv_preview = img.copy()
    hsv_preview[:, :, 1:] = [255, 255]
    return cv2.cvtColor(hsv_preview, cv2.COLOR_HSV2BGR)


def filter_for_color_range(roi, s):
    lower = range_array(s.Hlow, s.Slow, s.Vlow)
    upper = range_array(s.Hhigh, s.Shigh, s.Vhigh)
    return cv2.inRange(roi, lower, upper)


@memoize
def range_array(*a):
    return np.array(a, dtype="uint8")


def mouse_callback(queue, event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        queue.append((x, y))


def setup_mouse_callback(q):
    cv2.namedWindow("original")
    cv2.setMouseCallback("original", partial(mouse_callback, q))


def morph(image, size=5):
    kernel = np.ones((size, size), np.uint8)
    a = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
    return cv2.morphologyEx(a, cv2.MORPH_OPEN, kernel)


def main():
    image = cv2.imread(sys.argv[1])
    clicks = deque()
    setup_mouse_callback(clicks)
    cv2.imshow("original", image)
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    cv2.imshow("hsv", create_hsv_preview(hsv))
    filtered = filter_for_color_range(
        hsv,
        DEFAULT_SETTINGS,
    )
    cv2.imshow("filtered", filtered)

    morphed = morph(filtered, DEFAULT_SETTINGS.kernel_size)
    cv2.imshow("morphed", morphed)

    _, contours, _ = cv2.findContours(
        morphed,
        cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE,
    )
    assert len(contours) == 1

    contour = image.copy()

    epsilon = 0.001 * cv2.arcLength(contours[0], True)
    approx = cv2.approxPolyDP(contours[0], epsilon, True)
    print(len(approx))
    cv2.drawContours(contour, contours, 0, (255, 255, 0))
    cv2.drawContours(contour, [approx], 0, (0, 255, 255))
    cv2.imshow("contour", contour)

    print("gebogen" if len(approx) > 20 else "gerade")
    while True:
        key = cv2.waitKey(10)
        if key == 27:
            break
        for x, y in clicks:
            print(hsv[y,x,:])
        clicks.clear()

if __name__ == '__main__':
    main()

Anschließend kommt folgende Fehlermeldung. Wiegesagt entschuldige, bin völliger Anfänger und versuche iwie zurecht zu kommen :)

Code: Alles auswählen

runfile('C:/Users/kh94/Documents/HTWK_DVM/HTWK_2_Semester/Mustererkennung/Tests/Test_8_SkriptForum/SkriptForum.py', wdir='C:/Users/kh94/Documents/HTWK_DVM/HTWK_2_Semester/Mustererkennung/Tests/Test_8_SkriptForum')
Traceback (most recent call last):

  File "<ipython-input-1-dc236a07e07b>", line 1, in <module>
    runfile('C:/Users/kh94/Documents/HTWK_DVM/HTWK_2_Semester/Mustererkennung/Tests/Test_8_SkriptForum/SkriptForum.py', wdir='C:/Users/kh94/Documents/HTWK_DVM/HTWK_2_Semester/Mustererkennung/Tests/Test_8_SkriptForum')

  File "C:\Users\kh94\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 668, in runfile
    execfile(filename, namespace)

  File "C:\Users\kh94\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Users/kh94/Documents/HTWK_DVM/HTWK_2_Semester/Mustererkennung/Tests/Test_8_SkriptForum/SkriptForum.py", line 126, in <module>
    main()

  File "C:/Users/kh94/Documents/HTWK_DVM/HTWK_2_Semester/Mustererkennung/Tests/Test_8_SkriptForum/SkriptForum.py", line 85, in main
    image = cv2.imread(sys.argv[1])

IndexError: list index out of range
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

__deets__ hat geschrieben: Und das Skript muss mit dem Bild als Argument aufgerufen werden.
Hast Du aber nicht gemacht. Dafür lädst Du am Anfang ein Bild als `img`, das aber nie verwendet wird und an der Stelle auch gar nicht stehen sollte.
Pathfinder
User
Beiträge: 3
Registriert: Samstag 29. Dezember 2018, 12:16

Hei,

sorry aber wir studieren leider alle Verpackungstechnik und sollen hier iwas programmieren...(sehr sinnvoll ich weiß).
Wie rufe ich das Skript mit dem Bild als Argument auf?

Im Skript also nichts mehr ändern und es zusammen über die cmd ausführen oder verstehe ich das wieder falsch?
So habe ich es zumindest in anderen Fällen schon gesehen.

Danke dir vielmals im voraus!
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das funktioniert doch niemals. Das Skript ist doch nur eine Ideenskizze. Bis da die geforderte Aufgabe (so wie zumindest beschrieben im ersten Post) bei rum kommt, ist noch eine Menge zu tun. Wer denkt sich denn eine solche Nummer aus?

Und ja: nichts ändern. “Python Skript.py Bild.png” (ohne Anführungszeichen!) in der Eingabeaufforderung eingeben. Die Pfade zu den drei Bestandteilen müssen natürlich passen.
Antworten