सामग्री पर जाएं

पृथक विभाजन वस्तुएं

सेगमेंट कार्य करने के बाद, कभी-कभी अनुमान परिणामों से पृथक वस्तुओं को निकालना वांछनीय होता है। यह मार्गदर्शिका इसका उपयोग करके इसे पूरा करने के तरीके पर एक सामान्य नुस्खा प्रदान करती हैUltralytics भविष्यवाणी मोड

उदाहरण पृथक वस्तु विभाजन

पकाने की विधि के माध्यम से चलना

  1. आवश्यक आयात से शुरू करें

    from pathlib import Path
    
    import cv2 as cv
    import numpy as np
    from ultralytics import YOLO
    
    Ultralytics पदासीन करना

    देखें Ultralytics क्विकस्टार्ट आवश्यक पुस्तकालयों को स्थापित करने पर त्वरित पूर्वाभ्यास के लिए स्थापना अनुभाग।


  2. एक मॉडल लोड करें और चलाएं predict() एक स्रोत पर विधि।

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO('yolov8n-seg.pt')
    
    # Run inference
    result = model.predict()
    
    कोई भविष्यवाणी तर्क नहीं?

    स्रोत निर्दिष्ट किए बिना, पुस्तकालय से उदाहरण छवियों का उपयोग किया जाएगा:

    'ultralytics/assets/bus.jpg'
    'ultralytics/assets/zidane.jpg'
    

    यह तेजी से परीक्षण के लिए सहायक है predict() विधि।

    विभाजन मॉडल के बारे में अतिरिक्त जानकारी के लिए, पर जाएँ सेगमेंट कार्य पृष्ठ। इसके बारे में अधिक जानने के लिए predict() विधि, देखें भविष्यवाणी मोड दस्तावेज़ीकरण का अनुभाग।


  3. अब परिणामों और आकृति पर पुनरावृति करें। उन वर्कफ़्लोज़ के लिए जो किसी छवि को फ़ाइल में सहेजना चाहते हैं, स्रोत छवि base-name और पता लगाना class-label बाद में उपयोग के लिए पुनर्प्राप्त किए जाते हैं (वैकल्पिक)।

    # (2) Iterate detection results (helpful for multiple images)
    for r in res:
        img = np.copy(r.orig_img)
        img_name = Path(r.path).stem # source image base-name
    
        # Iterate each object contour (multiple detections)
        for ci,c in enumerate(r):
            # (1) Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()]
    
    1. डिटेक्शन परिणामों के साथ कार्य करने के बारे में अधिक जानने के लिए, पूर्वानुमान मोड के लिए बॉक्सेज़ अनुभाग देखें.
    2. इसके बारे में अधिक जानने के लिए predict() परिणाम देखें भविष्यवाणी मोड के लिए परिणामों के साथ कार्य करना
    फॉर-लूप

    एक एकल छवि केवल एक बार पहले लूप को पुनरावृति करेगी। केवल एक ही पहचान के साथ एक एकल छवि प्रत्येक लूप को केवल एक बार पुनरावृति करेगी।


  4. स्रोत छवि से एक बाइनरी मास्क उत्पन्न करने के साथ शुरू करें और फिर मास्क पर एक भरा हुआ समोच्च खींचें। यह ऑब्जेक्ट को छवि के अन्य भागों से अलग करने की अनुमति देगा। से एक उदाहरण bus.jpg पता चला में से एक के लिए person क्लास ऑब्जेक्ट्स को दाईं ओर दिखाया गया है।

    बाइनरी मास्क छवि

    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    # (1) Extract contour result
    contour = c.masks.xy.pop()
    # (2) Changing the type
    contour = contour.astype(np.int32)
    # (3) Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    
    # Draw contour onto mask
    _ = cv.drawContours(b_mask,
                        [contour],
                        -1,
                        (255, 255, 255),
                        cv.FILLED)
    
    1. अधिक जानकारी के लिए c.masks.xy देखना भविष्यवाणी मोड से मास्क अनुभाग.

    2. यहाँ, मानों को np.int32 के साथ संगतता के लिए drawContours() ओपनसीवी से फ़ंक्शन।

    3. ओपनसीवी drawContours() फ़ंक्शन अपेक्षा करता है कि आकृति का आकार होगा [N, 1, 2] अधिक जानकारी के लिए नीचे अनुभाग का विस्तार करें।

    यह समझने के लिए विस्तार करें कि परिभाषित करते समय क्या हो रहा है contour चर।

    • c.masks.xy :: प्रारूप में मुखौटा समोच्च बिंदुओं के निर्देशांक प्रदान करता है (x, y). अधिक जानकारी के लिए, देखें भविष्यवाणी मोड से मास्क अनुभाग.

    • .pop() ::जैसा masks.xy एक सूची है जिसमें एक एकल तत्व है, इस तत्व को pop() विधि।

    • .astype(np.int32) ::का उपयोग करके masks.xy के डेटा प्रकार के साथ वापस आ जाएगा float32, लेकिन यह ओपनसीवी के साथ संगत नहीं होगा drawContours() फ़ंक्शन, इसलिए यह डेटा प्रकार को int32 अनुकूलता के लिए।

    • .reshape(-1, 1, 2) :: डेटा को आवश्यक आकार में पुन: स्वरूपित करता है [N, 1, 2] कहां N समोच्च बिंदुओं की संख्या है, जिसमें प्रत्येक बिंदु एक एकल प्रविष्टि द्वारा दर्शाया गया है 1, और प्रविष्टि से बना है 2 मान। वही -1 यह दर्शाता है कि इस आयाम के साथ मानों की संख्या लचीली है।

    के स्पष्टीकरण के लिए विस्तृत करें drawContours() संरूपण।

    • एनकैप्सुलेट करना contour वर्ग कोष्ठक के भीतर चर, [contour], परीक्षण के दौरान वांछित समोच्च मुखौटा को प्रभावी ढंग से उत्पन्न करने के लिए पाया गया था।

    • मूल्य -1 के लिए निर्दिष्ट drawContours() पैरामीटर फ़ंक्शन को छवि में मौजूद सभी आकृति को आकर्षित करने का निर्देश देता है।

    • वही tuple (255, 255, 255) सफेद रंग का प्रतिनिधित्व करता है, जो इस बाइनरी मास्क में समोच्च खींचने के लिए वांछित रंग है।

    • के जोड़ cv.FILLED समोच्च सीमा से घिरे सभी पिक्सेल को समान रंग देगा, इस मामले में, सभी संलग्न पिक्सेल सफेद होंगे।

    • देखना OpenCV प्रलेखन पर drawContours() अधिक जानकारी के लिए।


  5. इसके बाद, इस बिंदु से छवि के साथ आगे बढ़ने के लिए 2 विकल्प हैं और प्रत्येक के लिए एक बाद का विकल्प है।

    ऑब्जेक्ट अलगाव विकल्प

    # Create 3-channel mask
    mask3ch = cv.cvtColor(b_mask, cv.COLOR_GRAY2BGR)
    
    # Isolate object with binary mask
    isolated = cv.bitwise_and(mask3ch, img)
    
    यह कैसे काम करता है?
    • सबसे पहले, बाइनरी मास्क को पहले सिंगल-चैनल इमेज से थ्री-चैनल इमेज में बदला जाता है। यह रूपांतरण बाद के चरण के लिए आवश्यक है जहां मुखौटा और मूल छवि संयुक्त हैं। सम्मिश्रण ऑपरेशन के साथ संगत होने के लिए दोनों छवियों में समान संख्या में चैनल होने चाहिए।

    • मूल छवि और तीन-चैनल बाइनरी मास्क को OpenCV फ़ंक्शन का उपयोग करके मर्ज कर दिया जाता है bitwise_and(). यह ऑपरेशन बरकरार रखता है केवल पिक्सेल मान जो शून्य से अधिक हैं (> 0) दोनों तस्वीरों से। चूंकि मास्क पिक्सल शून्य से अधिक हैं (> 0) केवल समोच्च क्षेत्र के भीतर, मूल छवि से शेष पिक्सेल वे हैं जो समोच्च के साथ ओवरलैप करते हैं।

    ब्लैक पिक्सल के साथ अलग: उप-विकल्प

    पूर्ण आकार की छवि

    पूर्ण आकार की छवि रखने पर किसी अतिरिक्त कदम की आवश्यकता नहीं है।

    उदाहरण: पूर्ण आकार: पृथक वस्तु छवि, काली पृष्ठभूमि
    उदाहरण पूर्ण आकार का आउटपुट

    क्रॉप की गई वस्तु छवि

    छवि को क्रॉप करने के लिए आवश्यक अतिरिक्त चरणों में केवल ऑब्जेक्ट क्षेत्र शामिल है।

    उदाहरण फसल पृथक वस्तु छवि काली पृष्ठभूमि

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. बाउंडिंग बॉक्स परिणामों के बारे में अधिक जानकारी के लिए, भविष्यवाणी मोड से बॉक्स अनुभाग देखें
    यह कोड क्या करता है?
    • वही c.boxes.xyxy.cpu().numpy() कॉल बाउंडिंग बॉक्स को NumPy सरणी के रूप में पुनः प्राप्त करता है xyxy प्रारूप, जहां xmin, ymin, xmaxऔर ymax बाउंडिंग बॉक्स आयत के निर्देशांक का प्रतिनिधित्व करते हैं। देखना भविष्यवाणी मोड से बक्से अनुभाग अधिक जानकारी के लिए।

    • वही squeeze() ऑपरेशन NumPy सरणी से किसी भी अनावश्यक आयाम को हटा देता है, यह सुनिश्चित करता है कि इसका अपेक्षित आकार है।

    • का उपयोग कर समन्वय मूल्यों को परिवर्तित करना .astype(np.int32) बॉक्स को इससे डेटा प्रकार का समन्वय करता है float32 तक int32, उन्हें इंडेक्स स्लाइस का उपयोग करके छवि क्रॉपिंग के लिए संगत बनाना।

    • अंत में, बाउंडिंग बॉक्स क्षेत्र को इंडेक्स स्लाइसिंग का उपयोग करके छवि से क्रॉप किया जाता है। सीमाओं को [ymin:ymax, xmin:xmax] डिटेक्शन बाउंडिंग बॉक्स के निर्देशांक।

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    यह कैसे काम करता है?
    • NumPy का उपयोग करना dstack() फ़ंक्शन (गहराई-अक्ष के साथ सरणी स्टैकिंग) उत्पन्न बाइनरी मास्क के संयोजन के साथ, चार चैनलों के साथ एक छवि बनाएगा। यह ऑब्जेक्ट समोच्च के बाहर के सभी पिक्सेल को पारदर्शी होने की अनुमति देता है जब एक के रूप में सहेजना PNG रेती।

    पारदर्शी पिक्सेल के साथ अलग: उप-विकल्प

    पूर्ण आकार की छवि

    पूर्ण आकार की छवि रखने पर किसी अतिरिक्त कदम की आवश्यकता नहीं है।

    उदाहरण: पूर्ण आकार: पृथक वस्तु छवि, कोई पृष्ठभूमि नहीं
    उदाहरण पूर्ण आकार का आउटपुट + पारदर्शी पृष्ठभूमि

    क्रॉप की गई वस्तु छवि

    छवि को क्रॉप करने के लिए आवश्यक अतिरिक्त चरणों में केवल ऑब्जेक्ट क्षेत्र शामिल है।

    उदाहरण: फसल पृथक वस्तु छवि, कोई पृष्ठभूमि नहीं

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. बाउंडिंग बॉक्स परिणामों के बारे में अधिक जानकारी के लिए, भविष्यवाणी मोड से बॉक्स अनुभाग देखें
    यह कोड क्या करता है?
    • उपयोग करते समय c.boxes.xyxy.cpu().numpy(), बाउंडिंग बॉक्स को NumPy सरणी के रूप में लौटाया जाता है, xyxy बॉक्स निर्देशांक प्रारूप, जो बिंदुओं के अनुरूप है xmin, ymin, xmax, ymax बाउंडिंग बॉक्स (आयत) के लिए, देखें भविष्यवाणी मोड से बक्से अनुभाग अधिक जानकारी के लिए।

    • जोड़ने squeeze() सुनिश्चित करता है कि किसी भी बाहरी आयाम को NumPy सरणी से हटा दिया गया है।

    • का उपयोग कर समन्वय मूल्यों को परिवर्तित करना .astype(np.int32) बॉक्स को इससे डेटा प्रकार का समन्वय करता है float32 तक int32 जो इंडेक्स स्लाइस का उपयोग करके छवि को क्रॉप करते समय संगत होगा।

    • अंत में बाउंडिंग बॉक्स के लिए छवि क्षेत्र को इंडेक्स स्लाइसिंग का उपयोग करके क्रॉप किया जाता है, जहां सीमा का उपयोग करके सेट किया जाता है [ymin:ymax, xmin:xmax] डिटेक्शन बाउंडिंग बॉक्स के निर्देशांक।

    क्या होगा यदि मैं पृष्ठभूमि सहित फसली वस्तु चाहता हूं?

    यह के लिए एक अंतर्निहित सुविधा है Ultralytics पुस्तकालय। देखें save_crop के लिए तर्क मोड अनुमान तर्कों की भविष्यवाणी करें विवरण के लिए।


  6. आगे क्या करना है यह पूरी तरह से डेवलपर के रूप में आपके ऊपर छोड़ दिया गया है। एक संभावित अगले चरण का एक मूल उदाहरण (भविष्य में उपयोग के लिए फ़ाइल में छवि को सहेजना) दिखाया गया है।

    • नोट: यह चरण वैकल्पिक है और यदि आपके विशिष्ट उपयोग के मामले के लिए आवश्यक नहीं है तो इसे छोड़ दिया जा सकता है।
    उदाहरण अंतिम चरण
    # Save isolated object to file
    _ = cv.imwrite(f'{img_name}_{label}-{ci}.png', iso_crop)
    
    • इस उदाहरण में, img_name स्रोत छवि फ़ाइल का आधार-नाम है, label पता चला वर्ग-नाम है, और ci ऑब्जेक्ट डिटेक्शन का सूचकांक है (एक ही वर्ग के नाम के साथ कई उदाहरणों के मामले में)।

पूर्ण उदाहरण कोड

यहां, पिछले अनुभाग के सभी चरणों को कोड के एकल ब्लॉक में जोड़ा जाता है। बार-बार उपयोग के लिए, इसमें निहित कुछ या सभी कमांड करने के लिए फ़ंक्शन को परिभाषित करना इष्टतम होगा for-लूप, लेकिन यह पाठक के लिए एक अभ्यास है।

from pathlib import Path

import cv2 as cv
import numpy as np
from ultralytics import YOLO

m = YOLO('yolov8n-seg.pt')#(4)!
res = m.predict()#(3)!

# iterate detection results (5)
for r in res:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem

    # iterate each object contour (6)
    for ci,c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]

        b_mask = np.zeros(img.shape[:2], np.uint8)

        # Create contour mask (1)
        contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
        _ = cv.drawContours(b_mask, [contour], -1, (255, 255, 255), cv.FILLED)

        # Choose one:

        # OPTION-1: Isolate object with black background
        mask3ch = cv.cvtColor(b_mask, cv.COLOR_GRAY2BGR)
        isolated = cv.bitwise_and(mask3ch, img)

        # OPTION-2: Isolate object with transparent background (when saved as PNG)
        isolated = np.dstack([img, b_mask])

        # OPTIONAL: detection crop (from either OPT1 or OPT2)
        x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
        iso_crop = isolated[y1:y2, x1:x2]

        # TODO your actions go here (2)
  1. आबाद हो रही रेखा contour यहां एक लाइन में जोड़ा गया है, जहां इसे मल्टीपल अप में विभाजित किया गया था।
  2. यहाँ क्या जाता है आप पर निर्भर है!
  3. अतिरिक्त जानकारी के लिए भविष्यवाणी मोड देखें।
  4. अधिक जानकारी के लिए सेगमेंट कार्य देखें.
  5. परिणामों के साथ कार्य करना के बारे में अधिक जानें
  6. सेगमेंटेशन मास्क परिणामों के बारे में अधिक जानें


2023-11-27 बनाया गया, अपडेट किया गया 2024-01-14
लेखक: ग्लेन-जोचर (4), रिजवानमुनव्वर (1), बुरहान-क्यू (1)

टिप्पणियाँ