2012-05-06 17 views
15

最新のpythonバインディング(cv2)でカラーイメージにマスクを適用するにはどうすればよいですか?以前のPythonバインディングでは、最も簡単な方法はcv.Copyです。OpenCV - マスクをカラーイメージに適用する

cv.Copy(dst, src, mask)

しかし、この機能は結合CV2では使用できません。ボイラープレートコードを使用しないで回避策はありますか?

+0

あなたは何をしようとしていますか? numpyのサポートがあるので、numpyの関数を使うことができます。 –

+0

私は元の画像にHSV色空間でいくつかのフィルタリングを行っています – pzo

答えて

30

ここでは、既にマスク画像がある場合はcv2.bitwise_and機能を使用できます。

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

レナ画像に対して、矩形マスクのために次のように出力は次のようになります。以下のコードをチェックするため

。 ABIDラーマンKによって与え

enter image description here

+0

私は同様のことをやろうとしています。マスクは黒または白でなければなりませんか?基本的な質問を申し訳ありません、私はopencvの初心者です。ありがとう –

+2

雅、あなたは正しいです、マスクは白​​黒とシングルチャンネルでなければなりません。画像のどの領域を処理したいかによって、マスク内の領域は白でなければなりません。その他はすべて黒です。そして、あなたはこの質問をしても大変申し訳ありません。誰もが初心者です。 –

+0

ありがとうAbid!私が帰ってきた今夜、私はそれを試してみるでしょう。私はいくつかの領域に画像を分割し、このプロセスをいくつかの画像に繰り返す必要があります。よろしく! –

-1

回答は完全に正しくありません。私もそれを試して、非常に有用だが、立ち往生した。

これは、特定のマスクで画像をコピーする方法です。

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] 

これは少し遅いですが、正しい結果が得られます。

編集:

Pythonic way。

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

Abidの答えは間違っていますか? –

+0

cv2の "bitwise_and"メソッドが100%尋ねられたように動作するとき、ここでホイールを再作成する必要はありません。それだけでなく、それが何をするのかは非常に明白です。 –

6

バックグラウンドを黒色以外の色にしたい場合のソリューションです。マスクを反転して、同じサイズの背景画像に適用する必要があります。背景と前景の両方を結合します。この解決方法のプロは、背景が何か(他の画像さえも)である可能性があるということです。

この例は、Hough Circle Transformから変更されています。最初の画像はOpenCVロゴ、2番目は元のマスク、3番目はバックグラウンド+フォアグラウンドを組み合わせたものです。

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) 

注:それは彼らが最適化されているので、OpenCVのメソッドを使用することをお勧めします。

1

説明した他の方法は、バイナリマスクを前提としています。あなたが(例えば、アルファチャンネルから)、次の3つのチャンネルにそれを展開し、補間のためにそれを使用することができますマスクとして実数値シングルチャンネルのグレースケール画像を使用したい場合:

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 

mask必要があること操作が成功するためには範囲0..1にあること。また、1.0はフォアグラウンドのみをエンコードし、0.0はバックグラウンドのみを保持することを意味します。

マスクは形状(h, w, 1)を持っている可能性がある場合は、このことができます:それは(h, w)あるとnp.squeeze(...)(h, w, 3, 1)から(h, w, 3)に結果を再形成する場合はここで

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

np.atleast_3d(mask)は、マスク(h, w, 1)になります。

関連する問題