2017-01-10 5 views
6

ओपनसीवी में कॉपी टू फ़ंक्शन है, जो एक मास्क वाले क्षेत्र को एक मैट से दूसरे में कॉपी करने में सक्षम बनाता है।पायथन ओपनसीवी बाइंडिंग में कॉपी करने के बराबर?

http://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html#a4331fa88593a9a9c14c0998574695ebb

पायथन बाइंडिंग में इस के बराबर क्या है? मैं बाइनरी मास्क के साथ एक छवि के किसी क्षेत्र को दूसरी छवि में कॉपी करना चाहता हूं।

उत्तर

11

cv::Mat::copyTo कि क्या उत्पादन मैट्रिक्स प्रारंभ कर दिया गया है के आधार पर दो चीजों में से एक करता है जाना होगा। यदि आपका आउटपुट मैट्रिक्स प्रारंभ नहीं किया गया है, तो मास्क के साथ copyTo का उपयोग करके एक नया आउटपुट मैट्रिक्स बनाता है जो इनपुट के समान प्रकार है और सभी मान सभी चैनलों पर 0 पर सेट होते हैं। एक बार ऐसा होने पर, मुखौटा द्वारा परिभाषित छवि डेटा को 0 पर सेट किए गए शेष मैट्रिक्स के साथ कॉपी किया जाता है। यदि आपका आउटपुट मैट्रिक्स प्रारंभ होता है और इसमें पहले से ही सामग्री शामिल है, copyTo उन पिक्सेल पर प्रतियां जो परिभाषित हैं स्रोत से मुखौटा और पिक्सल छोड़ देता है जो गंतव्य में बरकरार रखने के लिए मुखौटा का हिस्सा नहीं थे। इसलिए, स्रोत छवि से मुखौटा द्वारा परिभाषित पिक्सल का प्रतिस्थापन आउटपुट पर कॉपी हो जाता है।

क्योंकि ओपनसीवी अब लाइब्रेरी के साथ इंटरफ़ेस के लिए numpy का उपयोग करता है, तो यह या तो विधियों को करना बहुत आसान है। इस पोस्ट में देखे गए दूसरे उत्तर से अलग होने के लिए, पहली विधि को छवि के साथ मास्क को तत्व-वार फैशन में गुणा करके पूरा किया जा सकता है। यह मानते हुए कि अपने इनपुट img कहा जाता है और अपने द्विआधारी मुखौटा mask कहा जाता है जहां मैं यह सोचते हैं हूँ मुखौटा 2 डी है, बस निम्न कार्य करें:

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)) 

ऊपर कोड हालांकि मानता है कि दोनों img और mask शेयर के एक ही नंबर चैनल। यदि आप पहले से ही मान चुके हैं तो स्रोत और मास्क 2 डी के रूप में रंग छवि का उपयोग कर रहे हैं तो यह मुश्किल हो जाता है। इसलिए, चैनलों की कुल संख्या 2 है और 3 नहीं है और इसलिए उपर्युक्त वाक्यविन्यास आपको एक त्रुटि देगा क्योंकि दोनों के बीच आयाम अब संगत नहीं हैं। जब आप रंगीन छवियों का उपयोग कर रहे हों तो आपको इसके लिए समायोजित करने की आवश्यकता होगी। आप मुखौटा में सिंगलटन तीसरा आयाम जोड़ कर ऐसा कर सकते हैं ताकि प्रसारण का लाभ उठाया जा सके।

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") 

दूसरा दृष्टिकोण के लिए, मान लेते हैं कि हम एक और छवि other_image जहां आपको यह चित्र वापस लक्ष्य छवि img करने के लिए अपने मुखौटा द्वारा परिभाषित में सामग्री कॉपी करना चाहते कहा जाता डालते हैं। इस मामले में, आप पहले क्या करेंगे मास्क में सभी स्थानों को निर्धारित करते हैं जो numpy.where का उपयोग करके गैर-शून्य हैं, फिर इन्हें अपनी छवि में इंडेक्स या स्लाइस के साथ-साथ जहां से आप कॉपी करना चाहते हैं, का उपयोग करें। हम यह भी सिर्फ पहला दृष्टिकोण के साथ की तरह दो छवियों के बीच चैनलों की संख्या के प्रति जागरूक होना जरूरी:

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") 

यहाँ दोनों दृष्टिकोण के लिए एक उदाहरण रन है। मैं कैमरामैन छवि का उपयोग करने जा रहा हूं जो कि अधिकांश छवि प्रसंस्करण एल्गोरिदम में देखी गई एक मानक परीक्षण छवि है।

enter image description here

मैं भी कृत्रिम रूप से छवि रंग कर दिया है, भले ही यह ग्रेस्केल के रूप में देखा है, लेकिन तीव्रता सभी चैनलों को कॉपी कर दिए जाएंगे। मैं भी एक मुखौटा बस यह है कि शीर्ष छोड़ दिया 100 x 100 उपक्षेत्र परिभाषित करने के लिए जा रहा हूँ और इसलिए हम एक आउटपुट छवि बनाएगा कि केवल प्रतियां इस उपक्षेत्र:

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 

आप पहली विधि का उपयोग करते हैं और जब हम परिणाम बताते हैं, हम पाते हैं:

enter image description here

हम देख सकते हैं कि हम एक आउटपुट छवि जहां शीर्ष छोड़ दिया 100 x 100 पिक्सल उपक्षेत्र 0. इस के बराबर सेट के बाकी के साथ हमारे छवि डेटा नहीं है बनाया मास्क स्थानों के अधीन है जो हैं True पर सेट करें। दूसरे दृष्टिकोण के लिए, हम अन्य छवियों को एक ऐसे आकार के रूप में बनाएंगे जो सभी छवियों के लिए [0, 255] से इनपुट छवि के समान आकार के यादृच्छिक है।

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

एक बार जब हम दूसरे दृष्टिकोण के साथ कोड के माध्यम से चलाने, मैं अब इस छवि को मिलती है:

enter image description here

आप देख सकते हैं, चित्र के ऊपरी-बाएं कोने के रूप में अद्यतन किया गया है मास्क स्थानों के अधीन जो True पर सेट हैं।

+0

धन्यवाद, शानदार स्पष्टीकरण और निश्चित रूप से - यह काम करता है! – mikevanis

+0

बहुत बहुत धन्यवाद! मैं खुशी से मदद कर सकता है। – rayryeng

2

नोट यकीन है कि अगर यह है कि वास्तव में आप क्या चाहते हैं, लेकिन अजगर में मास्क के साथ कॉपी करने के लिए, मैं के साथ cv2.bitwise_

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

ओह, क्षमा करें, मुझे यकीन नहीं था कि – Soltius

+0

कोई समस्या नहीं थी। एफडब्ल्यूआईडब्ल्यू, मैंने डाउनवोट नहीं किया। – rayryeng

+0

दरअसल, दस्तावेज़ीकरण को देखते हुए, 'cv :: Mat :: copyTo' उन पिक्सल को शून्य करता है जो मुखौटा से संबंधित नहीं हैं, इसलिए यह सही है। यदि ओपी मास्क द्वारा प्रभावित नहीं होने वाले पिक्सल पर प्रतिलिपि बनाना चाहता है तो मैं ऊपर अपना उत्तर छोड़ दूंगा। – rayryeng

संबंधित मुद्दे