2012-05-06 39 views
15

Làm cách nào để áp dụng mặt nạ cho ảnh màu trong ràng buộc python mới nhất (cv2)? Trong trăn trước ràng buộc cách đơn giản nhất là sử dụng cv.Copy ví dụ:OpenCV - Áp dụng mặt nạ cho hình ảnh màu

cv.Copy(dst, src, mask)

Nhưng chức năng này không có sẵn trong ràng buộc cv2. Có cách nào khác mà không sử dụng mã soạn sẵn?

+0

bạn đang cố gắng làm gì.? vì nó có hỗ trợ gọn gàng, bạn có thể sử dụng các chức năng gọn gàng. –

+0

Tôi đang thực hiện một số chức năng lọc trong không gian màu HSV cho ảnh gốc – pzo

Trả lời

30

Ở đây, bạn có thể sử dụng chức năng cv2.bitwise_and nếu bạn đã có hình ảnh mặt nạ.

Đối với kiểm tra mã dưới đây:

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

Kết quả sẽ như sau cho một hình ảnh lena, và cho mặt nạ hình chữ nhật.

enter image description here

+0

Tôi đang cố gắng làm một việc tương tự. Mặt nạ phải có màu đen hoặc trắng? Xin lỗi cho câu hỏi cơ bản, tôi là một newbie với opencv. Cảm ơn –

+2

Ya, bạn đúng, mặt nạ phải là màu đen/trắng và một kênh. Cho dù khu vực nào trong hình ảnh bạn muốn xử lý, vùng đó trong mặt nạ phải có màu trắng, mọi thứ khác đều màu đen. Và bạn không cần phải xin lỗi vì hỏi câu hỏi này, mọi người đều là người mới khi bắt đầu học, kể cả tôi nữa. –

+0

Cảm ơn rất nhiều Abid! Tôi sẽ thử nó đêm nay khi tôi trở về nhà. Tôi phải chia một hình ảnh thành nhiều khu vực (và lặp lại quá trình này thành nhiều hình ảnh). Trân trọng! –

-1

Câu trả lời được đưa ra bởi Abid Rahman K không hoàn toàn chính xác. Tôi cũng đã thử nó và thấy rất hữu ích nhưng đã bị mắc kẹt.

Đây là cách tôi sao chép hình ảnh bằng một mặt nạ đã cho.

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] 

Điều này hơi chậm nhưng cho kết quả chính xác.

EDIT:

Cách Pythonic.

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

Điều gì không chính xác về câu trả lời của Abid? –

+0

Không cần phải phát minh lại bánh xe ở đây khi phương thức "bitwise_and" trong cv2 hoạt động 100% khi được hỏi. Không chỉ vậy, nhưng nó là rất rõ ràng như những gì nó làm. –

6

Vâng, đây là giải pháp nếu bạn muốn nền không phải là màu đen. Chúng tôi chỉ cần đảo ngược mặt nạ và áp dụng mặt nạ đó trong hình nền có cùng kích thước và sau đó kết hợp cả nền và nền trước. Một chuyên gia của giải pháp này là nền có thể là bất cứ điều gì (ngay cả hình ảnh khác).

Ví dụ này được sửa đổi từ Hough Circle Transform. Hình ảnh đầu tiên là logo OpenCV, thứ hai là mặt nạ gốc, thứ ba nền + nền trước được kết hợp.

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) 

Lưu ý: Nó là tốt hơn để sử dụng các phương pháp opencv vì họ được tối ưu hóa.

1

Các phương pháp khác được mô tả giả định mặt nạ nhị phân. Nếu bạn muốn sử dụng một hình ảnh màu xám đơn kênh thực có giá trị như một mặt nạ (ví dụ như từ một kênh alpha), bạn có thể mở rộng nó để ba kênh và sau đó sử dụng nó cho phép nội suy:

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 

Lưu ý rằng mask nhu cầu nằm trong phạm vi 0..1 để hoạt động thành công. Nó cũng giả định rằng 1.0 mã hóa chỉ giữ nền trước, trong khi 0.0 có nghĩa là chỉ giữ nền.

Nếu mặt nạ có thể có hình dạng (h, w, 1), điều này giúp:

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

Đây np.atleast_3d(mask) làm mặt nạ (h, w, 1) nếu nó là (h, w)np.squeeze(...) reshapes kết quả (h, w, 3, 1)-(h, w, 3).

Các vấn đề liên quan