Python में MediaPipe फ़्रेमवर्क

MediaPipe Python फ़्रेमवर्क, इसके मुख्य कॉम्पोनेंट को सीधे तौर पर ऐक्सेस देता है MediaPipe C++ फ़्रेमवर्क, जैसे कि टाइमस्टैंप, पैकेट, और कैलकुलेटरग्राफ़, वहीं, इस्तेमाल के लिए तैयार Python समाधान छिप जाते हैं तकनीकी जानकारी पढ़ें और आसानी से पढ़ा जा सकने वाला मॉडल दिखाएं कॉलर को दिखाता है.

MediaPipe फ़्रेमवर्क, सबसे ऊपर pybind11 लाइब्रेरी. C++ कोर फ़्रेमवर्क, C++/Python लैंग्वेज बाइंडिंग के ज़रिए Python में दिखाया जाता है. नीचे दिए गए कॉन्टेंट में यह माना गया है कि पाठक को पहले से ही MediaPipe C++ फ़्रेमवर्क के लिए उपलब्ध है. या फिर, आपको यहां उपयोगी जानकारी मिल सकती है फ़्रेमवर्क कॉन्सेप्ट.

पैकेट

पैकेट, MediaPipe में बेसिक डेटा फ़्लो यूनिट है. एक पैकेट में संख्या वाला टाइमस्टैंप और ऐसे पेलोड के लिए शेयर किया गया पॉइंटर. Python में, MediaPipe पैकेट को, पैकेट बनाने वाले किसी एक तरीके को कॉल करके बनाया जा सकता है यह mp.packet_creator मॉड्यूल का इस्तेमाल नहीं किया जाएगा. साथ ही, पैकेट पेलोड को इनमें से किसी एक का इस्तेमाल करके वापस लाया जा सकता है पैकेट गैटर मेथड mp.packet_getter मॉड्यूल का इस्तेमाल नहीं किया जाएगा. ध्यान दें कि पैकेट पेलोड के बाद, पैकेट पेलोड नहीं बदला जा सकता हो जाता है बनाना. इसलिए, वापस मिले पैकेट के कॉन्टेंट में किए गए बदलाव से, पैकेट का असल पेलोड होता है. MediaPipe फ़्रेमवर्क Python API, MediaPipe का सबसे ज़्यादा इस्तेमाल किया जाने वाला डेटा टाइप (उदाहरण के लिए, ImageFrame, मैट्रिक्स, प्रोटोकॉल कोर बाइंडिंग में बफ़र, और प्रिमिटिव डेटा टाइप) शामिल हैं. व्यापक नीचे दी गई टेबल में, Python और C++ डेटा टाइप के बीच टाइप मैपिंग दिखाई गई हैं साथ ही, हर तरह के डेटा के लिए पैकेट क्रिएटर और कॉन्टेंट गैटर तरीके की जानकारी भी MediaPipe Python फ़्रेमवर्क API द्वारा समर्थित.

Python डेटा टाइप C++ डेटा टाइप पैकेट क्रिएटर कॉन्टेंट पाने वाला
बूल बूल create_bool(True) get_bool(packet)
int या np.intc int_t create_int(1) get_int(packet)
int या np.int8 int8_t create_int8(2**7-1) get_int(packet)
int या np.int16 पूर्णांक16_t create_int16(2**15-1) get_int(packet)
int या np.int32 पूर्णांक32_t create_int32(2**31-1) get_int(packet)
int या np.int64 int64_t create_int64(2**63-1) get_int(packet)
int या np.uint8 uint8_t create_uint8(2**8-1) get_uint(packet)
int या np.uint16 uint16_t create_uint16(2**16-1) get_uint(packet)
int या np.uint32 uint32_t create_uint32(2**32-1) get_uint(packet)
int या np.uint64 uint64_t create_uint64(2**64-1) get_uint(packet)
float या np.float32 फ़्लोट create_float(1.1) get_float(packet)
फ़्लोट या np.DoubleClick दोगुनी create_double(1.1) get_float(packet)
str (UTF-8) std::स्ट्रिंग create_string('abc') get_str(packet)
बाइट std::स्ट्रिंग create_string(b'\xd0\xd0\xd0') get_bytes(packet)
mp.Packet mp::Packet create_packet(p) get_packet(packet)
सूची[बूल] std::वेक्टर<bul> create_bool_vector([सही, गलत]) get_bool_list(packet)
सूची[int] या सूची[np.intc] पूर्णांक[] create_int_array([1, 2, 3]) get_int_list(पैकेट, साइज़=10)
सूची[int] या सूची[np.intc] std::वेक्टर<int> create_int_vector([1, 2, 3]) get_int_list(packet)
सूची[float] या List[np.float] float[] create_float_arrary([0.1, 0.2]) get_float_list(पैकेट, आकार=10)
सूची[float] या List[np.float] std::vector&lt;float&gt; create_float_वेक्टर([0.1, 0.2]) get_float_list(पैकेट, आकार=10)
सूची[str] std::वेक्टर<std::स्ट्रिंग> create_string_vector(['a']) get_str_list(packet)
सूची[mp.Packet] std::vector&lt;mp::Packet&gt; create_packet_vector(
[packet1, पैकेट2])
get_packet_list(p)
मैपिंग[str, Packet] std::map<std::string, पैकेट=""></std::स्ट्रिंग,> create_string_to_packet_map(
        {&#39;a&#39;: packet1, &#39;b&#39;: packet2})
get_str_to_packet_dict(packet)
np.ndarray
(cv.mat और PIL.Image)
mp::ImageFrame create_image_frame(
format=ImageFormat.SRGB,
data=mat)
get_image_frame(packet)
np.ndarray mp::Matrix create_matrix(data) get_matrix(packet)
Google प्रोटो मैसेज Google प्रोटो मैसेज create_proto(proto) get_proto(packet)
सूची[Proto] एसटीडी::वेक्टर<प्रोटो> लागू नहीं get_proto_list(packet)

यह आम बात है कि उपयोगकर्ता, अपनी ज़रूरत के हिसाब से C++ क्लास बनाते हैं और उन्हें ग्राफ़ और कैलकुलेटर देख सकते हैं. Python में कस्टम क्लास इस्तेमाल करने की अनुमति देने के लिए अगर आपको MediaPipe Framework के साथ काम करना है, तो नए डेटा टाइप के लिए Packet API को, इसके लिए, नीचे दिया गया तरीका अपनाएं:

  1. pybind11 लिखें क्लास बाइंडिंग कोड या कस्टम टाइप का कोस्टर डालें.

    #include "path/to/my_type/header/file.h"
    #include "pybind11/pybind11.h"
    
    namespace py = pybind11;
    
    PYBIND11_MODULE(my_type_binding, m) {
      // Write binding code or a custom type caster for MyType.
      py::class_<MyType>(m, "MyType")
          .def(py::init<>())
          .def(...);
    }
    
  2. इसमें अपनी पसंद के हिसाब से पैकेट क्रिएटर और गैटर मेथड बनाएं अलग से कॉपी फ़ाइल में रखें.

    #include "path/to/my_type/header/file.h"
    #include "mediapipe/framework/packet.h"
    #include "pybind11/pybind11.h"
    
    namespace mediapipe {
    namespace py = pybind11;
    
    PYBIND11_MODULE(my_packet_methods, m) {
      m.def(
          "create_my_type",
          [](const MyType& my_type) { return MakePacket<MyType>(my_type); });
    
      m.def(
          "get_my_type",
          [](const Packet& packet) {
            if(!packet.ValidateAsType<MyType>().ok()) {
              PyErr_SetString(PyExc_ValueError, "Packet data type mismatch.");
              return py::error_already_set();
            }
            return packet.Get<MyType>();
          });
    }
    }  // namespace mediapipe
    
  3. कस्टम टाइप बाइंडिंग और नए पैकेट के लिए, दो बेज़ल बिल्ड नियम जोड़ें तरीकों का इस्तेमाल करना होगा.

    load("@pybind11_bazel//:build_defs.bzl", "pybind_extension")
    
    pybind_extension(
        name = "my_type_binding",
        srcs = ["my_type_binding.cc"],
        deps = [":my_type"],
    )
    
    pybind_extension(
        name = "my_packet_methods",
        srcs = ["my_packet_methods.cc"],
        deps = [
            ":my_type",
            "//mediapipe/framework:packet"
        ],
    )
    
  4. Bazz का इस्तेमाल करके, pybind एक्सटेंशन टारगेट (.so के साथ सफ़िक्स के साथ) बनाएं और जनरेट की गई डाइनैमिक लाइब्रेरी को $LD_LIBRARY_PATH में से किसी एक में ले जाएं.

  5. Python में बाइंडिंग मॉड्यूल का इस्तेमाल करें.

    import my_type_binding
    import my_packet_methods
    
    packet = my_packet_methods.create_my_type(my_type_binding.MyType())
    my_type = my_packet_methods.get_my_type(packet)
    

टाइमस्टैंप

हर पैकेट में एक टाइमस्टैंप होता है, जो माइक्रोसेकंड की यूनिट में होता है. Python में, पैकेट एपीआई, न्यूमेरिक (संख्या वाला) को तय करने के लिए एक सुविधा तरीका packet.at() देता है पैकेट का टाइमस्टैंप. आम तौर पर, packet.timestamp एक पैकेट क्लास होती है मौजूदा टाइमस्टैंप ऐक्सेस करने के लिए प्रॉपर्टी. Unix epoch को किसी MediaPipe टाइमस्टैंप, timestamp API इस काम के लिए, एक तरीका mp.Timestamp.from_seconds() उपलब्ध कराता है.

ImageFrame

ImageFrame एक कंटेनर है जिससे किसी इमेज या वीडियो फ़्रेम को सेव किया जाता है. फ़ॉर्मैट ImageFrame द्वारा समर्थित सूची में ये दी गई हैं ImageFormat enum को सबमिट कर सकते हैं. पिक्सल, इंटरलीव्ड कलर कॉम्पोनेंट और ImageFrame के साथ एन्कोड किए गए पंक्ति के मेजर uint8, uint16, और float को इसके डेटा टाइप के तौर पर इस्तेमाल किया जा सकता है. MediaPipe देता है ImageFrame Python API ImageFrame C++ क्लास को ऐक्सेस करने के लिए. Python में, यह फ़ाइल पाने का सबसे आसान तरीका है पिक्सल डेटा की मदद से, image_frame.numpy_view() को कॉल किया जा सकता है. नोट जोड़ें मान लिया गया है कि आंतरिक पिक्सेल डेटा का संदर्भ, numpy ndarray से मिला है लिखा नहीं जा सकता. अगर कॉल करने वालों (कॉलर) को संख्यात्मक विधि में बदलाव करना है, तो यह ज़रूरी है कॉपी प्राप्त करने के लिए स्पष्ट रूप से कॉपी कार्रवाई को कॉल करें. जब MediaPipe स्नैपी लेता है ndarray का इस्तेमाल किया जाता है, तो यह मानता है कि डेटा लगातार सेव किया जाता है. साथ ही, ImageFrame का पिक्सल डेटा इस तरह अलाइन किया जाएगा कि Python साइड में वापस लौटने पर, कॉन्सट्यूट.

ग्राफ़

MediaPipe Framework में, सभी प्रोसेसिंग, कैलकुलेटरग्राफ़. CalculatorGraph Python एपीआई C++ CalculatorGraph क्लास की सीधे तौर पर बाइंडिंग है. मुख्य अंतर यह है CalculatorGraph Python API, गड़बड़ी होने पर, 'ठीक नहीं है' स्थिति. इसलिए, Python उपयोगकर्ता के तौर पर, आपके पास अपवाद हैं, जैसा आप आमतौर पर करते हैं. CalculatorGraph के लाइफ़ साइकल में होता है तीन चरण: शुरू करना और सेटअप करना, ग्राफ़ चलाना, और ग्राफ़ शटडाउन करना.

  1. CalculatorGraphConfig प्रोटोबफ़ या बाइनरी से CalculatorGraph शुरू करें Protobuf फ़ाइल को अपलोड किया और आउटपुट देखने के लिए कॉलबैक के तरीके(तरीकों) का इस्तेमाल किया स्ट्रीम.

    विकल्प 1. CalculatorGraphConfig प्रोटोबफ़ के साथ CalculatorGraph शुरू करें और आउटपुट स्ट्रीम देखें:

    import mediapipe as mp
    
    config_text = """
      input_stream: 'in_stream'
      output_stream: 'out_stream'
      node {
        calculator: 'PassThroughCalculator'
        input_stream: 'in_stream'
        output_stream: 'out_stream'
      }
    """
    graph = mp.CalculatorGraph(graph_config=config_text)
    output_packets = []
    graph.observe_output_stream(
        'out_stream',
        lambda stream_name, packet:
            output_packets.append(mp.packet_getter.get_str(packet)))
    

    विकल्प 2. बाइनरी प्रोटोबफ़ फ़ाइल से CalculatorGraph शुरू करें आउटपुट स्ट्रीम देखें.

    import mediapipe as mp
    # resources dependency
    
    graph = mp.CalculatorGraph(
        binary_graph=os.path.join(
            resources.GetRunfilesDir(), 'path/to/your/graph.binarypb'))
    graph.observe_output_stream(
        'out_stream',
        lambda stream_name, packet: print(f'Get {packet} from {stream_name}'))
    
  2. ग्राफ़ चलाना शुरू करें और ग्राफ़ में फ़ीड पैकेट दें.

    graph.start_run()
    
    graph.add_packet_to_input_stream(
        'in_stream', mp.packet_creator.create_string('abc').at(0))
    
    rgb_img = cv2.cvtColor(cv2.imread('/path/to/your/image.png'), cv2.COLOR_BGR2RGB)
    graph.add_packet_to_input_stream(
        'in_stream',
        mp.packet_creator.create_image_frame(image_format=mp.ImageFormat.SRGB,
                                             data=rgb_img).at(1))
    
  3. खत्म होने के बाद ग्राफ़ बंद कर दें. किसी अन्य ग्राफ़ के लिए ग्राफ़ को रीस्टार्ट किया जा सकता है close() को कॉल करने के बाद चलाया जाता है.

    graph.close()
    

Python स्क्रिप्ट को आपके लोकल Python रनटाइम से चलाया जा सकता है.