2017-01-10 65 views

cevap

11

cv::Mat::copyTo çıkış matrisi başlatıldı olmasına bağlı olarak iki şeyden birini yapar ile gider. Çıktı matrisiniz başlatılamıyorsa, bir maske ile copyTo kullanarak, girişle aynı türde yeni bir çıktı matrisi oluşturur ve tüm değerler tüm kanallarda 0 olarak ayarlanır. Bu olduğunda, maske tarafından tanımlanan görüntü verileri, matrisin 0'a ayarlanmış olan geri kalanıyla kopyalanır. Çıkış matrisiniz , başlatılmışsa ve halihazırda içerik içeriyorsa, copyTo, içinde tanımlanan piksellerin üzerine kopyalar. maskeyi kaynağından ve maskenin parçası olmayan pikselleri hedefte bozulmamış olarak bırakır. Bu nedenle, maske tarafından kaynak görüntüden tanımlanan piksellerin değiştirilmesi, çıktıya kopyalanır.

OpenCV artık kütüphaneyle arabirim kurmak için numpy kullanıyorsa, her iki yöntemi de yapmak çok kolaydır. Bu yazıda görülen diğer cevaptan ayırt etmek için, ilk yöntem, maskeyi görüntü ile basitçe çarparak gerçekleştirilebilir. girişinizi img denir ve ben maskesi 2D varsayıyorum nerede ikili maske mask denir varsayarak, sadece aşağıdakileri yapın:

Yukarıdaki kod olsa varsayar
import numpy as np 
import cv2 

mask = ... # define mask here 
img = cv2.imread(...) # Define input image here 

# Create new image 
new_image = img * (mask.astype(img.dtype)) 

her iki img ve mask pay aynı sayıda kanalları. Kaynak olarak renkli bir görüntü ve önceden varsaydığım gibi maske 2'yi kullanmanız zorlaşır. Bu nedenle, toplam kanal sayısı 2'dir ve 3 değildir ve bu nedenle yukarıdaki sözdizimi, ikisi arasındaki boyutlar artık uyumlu olmadığından size bir hata verecektir. Renkli görüntüleri kullanırken bunun için yer almanız gerekecek. Bunu, maskeye tek bir üçüncü boyut ekleyerek yapabilirsiniz, böylece yayının avantajından yararlanılabilir.

ikinci yaklaşım için

import numpy as np 
import cv2 

mask = ... # define mask here 
img = cv2.imread(...) # Define input image here 

# Create new image 
# Case #1 - Other image is grayscale and source image is colour 
if len(img.shape) == 3 and len(mask.shape) != 3: 
    new_image = img * (mask[:,:,None].astype(img.dtype)) 
# Case #2 - Both images are colour or grayscale 
elif (len(img.shape) == 3 and len(mask.shape) == 3) or \ 
    (len(img.shape) == 1 and len(mask.shape) == 1): 
    new_image = img * (mask.astype(img.dtype)) 
# Otherwise, we can't do this 
else: 
    raise Exception("Incompatible input and mask dimensions") 
, en başka görüntü hedef görüntüye img geri maskenin tarafından tanımlanan bu görüntüde içeriğini kopyalamak istediğiniz other_image denilen olduğunu varsayalım. Bu durumda, ilk olarak yaptığınız şey, maskenin numpy.where'u kullanarak sıfır olmayan tüm konumlarını belirler, ardından bunları kopyalamak istediğiniz konumun yanı sıra resminize dizinlemek veya dilimlemek için bunları kullanın. Ayrıca sadece birinci yaklaşımla gibi iki resim arasında kanal sayısına dikkatli olmak zorunda:

import numpy as np 
import cv2 

mask = ... # define mask here 
img = cv2.imread(...) # Define input image here 
other_image = cv2.imread(...) # Define other image here 

locs = np.where(mask != 0) # Get the non-zero mask locations 

# Case #1 - Other image is grayscale and source image is colour 
if len(img.shape) == 3 and len(other_image.shape) != 3: 
    img[locs[0], locs[1]] = other_image[locs[0], locs[1], None] 
# Case #2 - Both images are colour or grayscale 
elif (len(img.shape) == 3 and len(other_image.shape) == 3) or \ 
    (len(img.shape) == 1 and len(other_image.shape) == 1): 
    img[locs[0], locs[1]] = other_image[locs[0], locs[1]] 
# Otherwise, we can't do this 
else: 
    raise Exception("Incompatible input and output dimensions") 

İşte iki yaklaşımda için bir örnek turu. Çoğu görüntü işleme algoritmasında görülen standart bir test görüntüsü olan Cameraman görüntüsünü kullanacağım.

enter image description here

Ben de yapay o gri tonlarında görsel oluyor ama şiddetler tüm kanallara üzerine kopyalanır rağmen, görüntü rengini yaptık. Ben de ilk 100 x 100 alt bölgesine sol basitçe bir maske tanımlamak için gidiyorum ve bu yüzden bir çıkış görüntüsü oluşturur yalnızca kopyalar bu alt bölge:

import numpy as np 
import cv2 

# Define image 
img = cv2.imread("cameraman.png") 

# Define mask 
mask = np.zeros(img.shape, dtype=np.bool) 
mask[:100, :100] = True 

ilk yöntemini kullandığınızda ve ne zaman biz sonuçlarını gösterir, elde ederiz:

enter image description here

Biz üst alt bölgesine 0'a Bu eşit ayarlanmış piksel geri kalanı ile bizim görüntü verilerini içeren 100 x 100 sol bir çıkış görüntü oluşturdu görebilirsiniz

maske konumlarına tabidir True olarak ayarlayın. İkinci yaklaşım için, diğer görüntülerin, tüm kanallar için [0, 255]'dan gelen giriş görüntüsü ile aynı boyutta rastgele olan bir resim oluşturacağız. ikinci yaklaşımla kod üzerinden çalıştırmak sonra

# Define other image 
other_image = (255*np.random.rand(*img.shape)).astype(np.uint8) 

, şimdi bu resim olsun:

enter image description here

Gördüğünüz gibi, görüntünün sol üst köşesi olarak güncellendi True olarak ayarlanmış olan maske konumlarına tabidir.

+0

Teşekkür ederim, parlak bir açıklama ve tabi ki - işe yarıyor! – mikevanis

+0

Çok teşekkürler! Yardımcı olduğuma sevindim. – rayryeng

2

Not emin, ben cv2.bitwise_

new_image = cv2.bitwise_and(old_image,binary_mask) 
+0

Oh, pardon, ne sorduğumdan emin değildim – Soltius

+0

Sorun değil. FWIW, reddetmedim. – rayryeng

+0

Aslında, belgelere bakıldığında, 'cv :: Mat :: copyTo' maskeye ait olmayan pikselleri sıfırlar, bu yüzden doğrudur. OP'nin maskeden etkilenmeyen pikselleri kopyalamak istemesi durumunda cevabımı yukarıda bırakacağım. – rayryeng