2012-05-06 13 views
15

Wie kann ich Maske auf ein Farbbild in der neuesten Python-Bindung (CV2) anwenden? In der vorherigen Python-Bindung war der einfachste Weg die Verwendung von cv.Copy, z.OpenCV - Maske auf ein Farbbild anwenden

cv.Copy(dst, src, mask)

Aber diese Funktion ist in cv2 Bindung nicht zur Verfügung. Gibt es eine Umgehungslösung, ohne den Standardcode zu verwenden?

+0

was versuchst du zu tun? Da es numpy Unterstützung hat, können Sie numpy Funktionen verwenden. –

+0

Ich mache einige Filterung im HSV-Farbraum zu Originalbild – pzo

Antwort

30

Hier könnten Sie cv2.bitwise_and Funktion verwenden, wenn Sie bereits das Maskenbild haben.

für die unten überprüfen Code:

img = cv2.imread('lena.jpg') 
mask = cv2.imread('mask.png',0) 
res = cv2.bitwise_and(img,img,mask = mask) 

Der Ausgang wird als für ein lena Bild folgt und für rechteckige Maske.

enter image description here

+0

Ich versuche, etwas ähnliches zu tun. Die Maske sollte schwarz oder weiß sein? Sorry für die grundlegende Frage, ich bin ein Neuling mit opencv. Danke –

+2

Ya, du bist richtig, Maske sollte schwarz/weiß und einkanalig sein. Welche Region in dem Bild Sie auch verarbeiten möchten, diese Region in der Maske sollte weiß sein, alles andere ist schwarz. Und Sie müssen nicht bedauern, diese Frage zu stellen, jeder ist Anfänger, wenn er anfängt zu lernen, auch ich. –

+0

Vielen Dank Abid! Ich werde es heute Nacht versuchen, wenn ich wieder zu Hause bin. Ich muss ein Bild in mehrere Bereiche aufteilen (und diesen Vorgang in mehrere Bilder wiederholen). Grüße! –

-1

Antwort von Abid Rahman K gegeben ist nicht ganz korrekt. Ich habe es auch ausprobiert und fand es sehr hilfreich, aber steckte fest.

So kopiere ich das Bild mit einer gegebenen Maske.

x, y = np.where(mask!=0) 
pts = zip(x, y) 
# Assuming dst and src are of same sizes 
for pt in pts: 
    dst[pt] = src[pt] 

Dies ist ein bisschen langsam, aber liefert korrekte Ergebnisse.

BEARBEITEN:

Pythonischer Weg.

idx = (mask!=0) 
dst[idx] = src[idx] 
+0

Was ist falsch an Abids Antwort? –

+0

Es besteht keine Notwendigkeit, das Rad hier neu zu erfinden, wenn die "bitwise_and" -Methode in CV2 zu 100% wie gewünscht funktioniert. Nicht nur das, aber es ist sehr offensichtlich, was es tut. –

6

Nun, hier ist eine Lösung, wenn Sie möchten, dass der Hintergrund anders als eine feste schwarze Farbe ist. Wir müssen nur die Maske invertieren und sie in einem Hintergrundbild der gleichen Größe anwenden und dann beide Hintergrund und Vordergrund kombinieren. Ein Vorteil dieser Lösung ist, dass der Hintergrund alles sein kann (sogar ein anderes Bild).

Dieses Beispiel wurde geändert von Hough Circle Transform. Das erste Bild ist das OpenCV-Logo, das zweite die Originalmaske, das dritte der Hintergrund + Vordergrund kombiniert.

apply mask and get a customized background

# http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghcircles/py_houghcircles.html 
import cv2 
import numpy as np 

# load the image 
img = cv2.imread('E:\\FOTOS\\opencv\\opencv_logo.png') 
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 

# detect circles 
gray = cv2.medianBlur(cv2.cvtColor(img, cv2.COLOR_RGB2GRAY), 5) 
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=50, minRadius=0, maxRadius=0) 
circles = np.uint16(np.around(circles)) 

# draw mask 
mask = np.full((img.shape[0], img.shape[1]), 0, dtype=np.uint8) # mask is only 
for i in circles[0, :]: 
    cv2.circle(mask, (i[0], i[1]), i[2], (255, 255, 255), -1) 

# get first masked value (foreground) 
fg = cv2.bitwise_or(img, img, mask=mask) 

# get second masked value (background) mask must be inverted 
mask = cv2.bitwise_not(mask) 
background = np.full(img.shape, 255, dtype=np.uint8) 
bk = cv2.bitwise_or(background, background, mask=mask) 

# combine foreground+background 
final = cv2.bitwise_or(fg, bk) 

Hinweis: Es ist besser, die opencv Methoden zu verwenden, da sie optimiert sind.

1

Die anderen beschriebenen Methoden gehen von einer binären Maske aus. Wenn Sie eine reellwertige Einkanal-Graustufenbild als Maske (zB von einem Alphakanal) verwenden möchten, können Sie es auf drei Kanäle erweitern und es dann für die Interpolation verwendet werden:

assert len(mask.shape) == 2 and issubclass(mask.dtype.type, np.floating) 
assert len(foreground_rgb.shape) == 3 
assert len(background_rgb.shape) == 3 

alpha3 = np.stack([mask]*3, axis=2) 
blended = alpha3 * foreground_rgb + (1. - alpha3) * background_rgb 

Beachten Sie, dass mask Bedürfnisse im Bereich 0..1 liegen, damit der Vorgang erfolgreich ist. Es wird auch angenommen, dass 1.0 codiert, nur den Vordergrund zu behalten, während 0.0 bedeutet, nur den Hintergrund zu behalten.

Wenn der Maske die (h, w, 1) Form haben kann, das hilft:

alpha3 = np.squeeze(np.stack([np.atleast_3d(mask)]*3, axis=2)) 

Hier np.atleast_3d(mask) macht die Maske (h, w, 1) wenn es (h, w) und np.squeeze(...) umformt das Ergebnis (h, w, 3, 1)-(h, w, 3).