\newpage \subsection{Segmentierung und Bildmodifizierung} In diesem Arbeitspaket werden Sie auf Grundlage der vorherigen Analysen eine Segmentierung des magischen Umhangs realisieren. Anschließend werden Sie den segmentierten Bereich \glqq verschwinden\grqq\ lassen, indem sie ein statisches Bild des Hintergrunds auf diese Flächen einfügen. \subsubsection{Statisches Schwellwertverfahren} Implementieren Sie die von Ihnen gefundene Regel nach Gleichung~\ref{equ:segrule}, um eine Binärmaske zu erhalten. Sie können die Randbedingungen wie im folgenden Code-Schnipsel \ref{lst:conditions} implementieren. \begin{lstlisting}[caption={Benutzung von Randbedingungen mit \textit{numpy}}, label={lst:conditions}] import cv2 import numpy as np channel1 = 0 lower_bound1, upper_bound1 = 15, 100 is_condition_1_true = (lower_bound1 < img[:, :, channel1]) * \ (img[:, :, channel1] < upper_bound1) channel2 = 1 lower_bound2, upper_bound2 = 65, 172 is_condition_2_true = (lower_bound2 < img[:, :, channel2]) * \ (img[:, :, channel2] < upper_bound2) binary_mask = is_condition_1_true * is_condition_2_true \end{lstlisting} Geben Sie die gefundene Binärmaske als Ausgangsbild auf dem Bildschirm aus. Sollten die gefundenen Wertebereich zu keinen sinnvollen Segmentierungen führen, dürfen Sie Gleichung~\ref{equ:segrule} selbstverständlich anpassen! Implementieren Sie ebenfalls eine Mausklick-Funktion, mit der Sie das aktuelle Bild und die dazugehörige Binärmaske abspeichern können. Für das Abspeichern von Bildern können Sie die Funktion \textit{cv2.imwrite(img, "path\_to\_store.png")} verwenden. \paragraph*{Aufgabe 1} Geben Sie Ihren Code an und beschreiben Sie ihn. Geben Sie nur relevante Code Bereiche an! Geben Sie ebenfalls das aufgenommene Bild sowie die dazugehörige Binärmaske an. \lstset{caption={Segmentierung und Bildmodifizierung, Aufgabe 1}} \begin{lstlisting} def _23_SegmentUndBildmodifizierung (self, img, save_binary_mask = False): # Convert BGR -> HSV hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Area 1: H = 0-10 (strong Rot) lower_red1 = np.array([0, 100, 50]) upper_red1 = np.array([0, 255, 255]) # Area 2: H = 169-179 (red-violet) lower_red2 = np.array([171, 100, 50]) upper_red2 = np.array([179, 255, 255]) # Create binary mask for both red areas mask1 = cv2.inRange(hsv, lower_red1, upper_red1) mask2 = cv2.inRange(hsv, lower_red2, upper_red2) # Combine both masks mask = cv2.bitwise_or(mask1, mask2) \end{lstlisting} \subsubsection{Binärmaske} Die in der vorherigen Aufgabe erhaltene Binärmaske ist ggf.\ ungeeignet für eine zufriedenstellende Segmentierung. Sie sollen die Maske nun optimieren. Wenden Sie dafür das \textit{Opening} und \textit{Closing} auf die Binärmaske an. Nutzen Sie die Funktionen \textit{cv2.erode(img, kernel)} und \textit{cv2.dilate(img, kernel)}. Wählen Sie zum Schluss die größte zusammenhänge Region segmentierter Pixel aus, und löschen alle anderen Segmente. Folgender Code-Schnipsel~\ref{lst:contours} soll als Hilfestellung dienen. Recherchieren Sie ggf.\ im Internet. \lstset{caption={Konturfindung}} \lstset{label={lst:contours}} \begin{lstlisting} (cnts, _) = cv2.findContours( binary_mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) c = max(cnts, key = cv2.contourArea) img = cv2.drawContours(img, [c], -1, color=255, -1) \end{lstlisting} \paragraph*{Aufgabe 2} Geben Sie Ihren Code an und beschreiben Sie ihn. Geben Sie nur relevante Code Bereiche an! \lstset{caption={Segmentierung und Bildmodifizierung, Aufgabe 2}} \begin{lstlisting} def _23_SegmentUndBildmodifizierung (self, img, save_binary_mask = False): # ... # Optimizing mask with opening and closing kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # Select biggest connected area cnts, _ = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) if cnts: c = max(cnts, key=cv2.contourArea) new_mask = np.zeros_like(mask) cv2.drawContours(new_mask, [c], -1, color = 255, thickness = -1) mask = new_mask else: mask = np.zeros_like(mask) \end{lstlisting} \paragraph*{Aufgabe 3} Welche Probleme oder Fehler können in der Binärmaske vorkommen, die mit den Maßnahmen beseitigt werden sollen? \color{blue} Durch das Opening und Closing können sich zwei Bereiche miteinander verbinden, die jedoch nicht zusammengehören. Die Wahl des größten zusammenhängenden Segments kann relevante Bereiche auch einfach auslassen, wenn das Opening und Closing diesen nicht zu größten Bereich zusammengeführt hat. \color{black} \subsubsection{Bildmodifizierung} Nach dem Fertigstellen der vorherigen Aufgabenstellungen sollten Sie nun eine Binärmaske erhalten, welche den \glqq magischen Umhang\grqq\ segmentiert. Die letzte Aufgabe befasst sich mit der Bildmodifizierung, welche den Eindruck verschwindender Objekte vermittelt. Sie sollen nun folgende Funktionen implementieren: Erstellen Sie eine Member-Variable (z.B. \textit{self.variable}) in die Algorithmus Funktion \textit{\_\_init\_\_()}. Initiieren Sie die Variable mit dem Wert \textit{None}. Modifizieren Sie den Algorithmus, sodass Sie mit einem Mausklick ein Bild in die Variable speichern können. Dieses Bild wird als Hintergrund definiert. Mausklick-Funktionen aus vorherigen Aufgaben können überschrieben werden! Solange kein Bild in der Variable gespeichert ist, soll das Eingangsbild direkt wieder ausgegeben werden. Sobald ein Hintergrund vorhanden ist soll folgendes passieren: Modifizieren Sie das Bild, indem Sie das Ausgangsbild aus dem derzeitigen Kamera-Stream und dem Hintergrund zusammenfügen. Die durch die Binärmaske segmentierte Fläche soll aus dem Hintergrund entnommen werden, die unsegmentierte Fläche aus dem derzeitigen Videostream. \textbf{Hinweis:} Verlassen Sie das Sichtfeld der Kamera, während Sie die Hintergrund Aufnahme aufnehmen. \paragraph*{Aufgabe 4} Geben Sie Ihren Code an und beschreiben Sie ihn. Geben Sie nur relevante Code Bereiche an! \lstset{caption={Segmentierung und Bildmodifizierung, Aufgabe 4}} \begin{lstlisting} def _23_SegmentUndBildmodifizierung (self, img, save_binary_mask = False): # ... # Return image if no background is set if self.background is None: return img # 3-channel mask for binary operations mask_3ch = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # Background are: Get from save background image background_part = cv2.bitwise_and(self.background, mask_3ch) # Foreground area: Extract from current image foreground_part = cv2.bitwise_and(img, cv2.bitwise_not(mask_3ch)) # Merge both areas output = cv2.add(background_part, foreground_part) return output \end{lstlisting} \paragraph*{Aufgabe 5} Geben Sie ein Bild (z.B. Screenshot) an, in dem die Funktion Ihres \glqq magischen Umhangs\grqq\ gezeigt wird! \begin{figure} \centering \includegraphics[width=10cm]{fig/Endergebnis.png} \caption{Endergebnis} \label{fig:histogram-endergebnis} \end{figure}