Grafikler

Grafik

CalculatorGraphConfig protokolü, bir öğenin topolojisini ve işlevselliğini MediaPipe grafiği. Grafikteki her node belirli bir hesap makinesini temsil eder veya alt grafiği içerir ve kayıtlı olanlar gibi gerekli yapılandırmaları hesap makinesi/alt grafik türü, girişler, çıkışlar ve düğüme özgü seçenekler, giriş politikası ve yürütücü Senkronizasyon.

CalculatorGraphConfig, genel grafik düzeyini yapılandırmak için birkaç alana daha sahiptir ayarlar, ör. grafik yürütücü yapılandırmaları, iş parçacığı sayısı ve maksimum sıra boyutu sayısı. Grafik düzeyindeki birçok ayar, Grafiğin farklı platformlardaki (ör. masaüstü ve mobil) performansı. Örneğin, mobilde, büyük bir model çıkarım hesaplayıcıyı ayrı bir yürütücü, gerçek zamanlı bir uygulamanın performansını artırabilir çünkü iş parçacığı yerelliğini etkinleştirir.

Aşağıda, örnek olarak CalculatorGraphConfig için geçiş hesaplayıcılar :

# This graph named main_pass_throughcals_nosubgraph.pbtxt contains 4
# passthrough calculators.
input_stream: "in"
output_stream: "out"
node {
    calculator: "PassThroughCalculator"
    input_stream: "in"
    output_stream: "out1"
}
node {
    calculator: "PassThroughCalculator"
    input_stream: "out1"
    output_stream: "out2"
}
node {
    calculator: "PassThroughCalculator"
    input_stream: "out2"
    output_stream: "out3"
}
node {
    calculator: "PassThroughCalculator"
    input_stream: "out3"
    output_stream: "out"
}

MediaPipe karmaşık grafikler (ör. makine öğrenimi ardışık düzenleri, model meta verilerini işleme, isteğe bağlı düğümler vb.) için alternatif bir C++ temsili sunar. Yukarıdaki grafik aşağıdaki gibi görünebilir:

CalculatorGraphConfig BuildGraphConfig() {
  Graph graph;

  // Graph inputs
  Stream<AnyType> in = graph.In(0).SetName("in");

  auto pass_through_fn = [](Stream<AnyType> in,
                            Graph& graph) -> Stream<AnyType> {
    auto& node = graph.AddNode("PassThroughCalculator");
    in.ConnectTo(node.In(0));
    return node.Out(0);
  };

  Stream<AnyType> out1 = pass_through_fn(in, graph);
  Stream<AnyType> out2 = pass_through_fn(out1, graph);
  Stream<AnyType> out3 = pass_through_fn(out2, graph);
  Stream<AnyType> out4 = pass_through_fn(out3, graph);

  // Graph outputs
  out4.SetName("out").ConnectTo(graph.Out(0));

  return graph.GetConfig();
}

Daha ayrıntılı bilgi için C++'ta Grafik Oluşturma başlıklı makaleyi inceleyin.

Alt grafik

Bir CalculatorGraphConfig öğesini alt modüllere ayırmak ve yeniden kullanıma yardımcı olmak için bir MediaPipe grafiği, Subgraph olarak tanımlanabilir. İlgili içeriği oluşturmak için kullanılan bir alt grafiğin herkese açık arayüzü, bir dizi giriş ve çıkış akışından oluşur. herkese açık arayüze benzer. Alt grafik daha sonra CalculatorGraphConfig düğmesini sanki hesap makinesi gibi düşünebilirsiniz. Bir MediaPipe grafiği CalculatorGraphConfig etiketinden yüklendiğinde, her bir alt grafik düğümü karşılık gelen hesap makinesi grafiğidir. Sonuç olarak, anlam ve performans, şekli, karşılık gelen hesap makineleri grafiğiyle aynıdır.

Aşağıda, TwoPassThroughSubgraph adlı bir alt grafiğin nasıl oluşturulacağına ilişkin bir örnek verilmiştir.

  1. Alt grafiği tanımlama.

    # This subgraph is defined in two_pass_through_subgraph.pbtxt
    # and is registered as "TwoPassThroughSubgraph"
    
    type: "TwoPassThroughSubgraph"
    input_stream: "out1"
    output_stream: "out3"
    
    node {
        calculator: "PassThroughCalculator"
        input_stream: "out1"
        output_stream: "out2"
    }
    node {
        calculator: "PassThroughCalculator"
        input_stream: "out2"
        output_stream: "out3"
    }
    

    Alt grafiğin herkese açık arayüzü şunlardan oluşur:

    • Giriş akışları grafiğini çizme
    • Çıkış akışlarının grafiğini çizme
    • Giriş tarafı paketlerinin grafiğini çizme
    • Çıkış tarafı paketlerinin grafiğini çizme
  2. mediapipe_simple_subgraph DERLEME kuralını kullanarak alt grafiği kaydedin. İlgili içeriği oluşturmak için kullanılan register_as parametresi yeni alt grafiğin bileşen adını tanımlar.

    # Small section of BUILD file for registering the "TwoPassThroughSubgraph"
    # subgraph for use by main graph main_pass_throughcals.pbtxt
    
    mediapipe_simple_subgraph(
        name = "twopassthrough_subgraph",
        graph = "twopassthrough_subgraph.pbtxt",
        register_as = "TwoPassThroughSubgraph",
        deps = [
                "//mediapipe/calculators/core:pass_through_calculator",
                "//mediapipe/framework:calculator_graph",
        ],
    )
    
  3. Ana grafikteki alt grafiği kullanın.

    # This main graph is defined in main_pass_throughcals.pbtxt
    # using subgraph called "TwoPassThroughSubgraph"
    
    input_stream: "in"
    node {
        calculator: "PassThroughCalculator"
        input_stream: "in"
        output_stream: "out1"
    }
    node {
        calculator: "TwoPassThroughSubgraph"
        input_stream: "out1"
        output_stream: "out3"
    }
    node {
        calculator: "PassThroughCalculator"
        input_stream: "out3"
        output_stream: "out4"
    }
    

Grafik Seçenekleri

"Grafik seçenekleri" belirlenebilir MediaPipe grafiği için protokol Calculator Options ile benzer MediaPipe hesap makinesi için belirtilen protobuf. Bu "grafik seçenekleri" olabilir bir grafik çağrıldığında belirtilir ve hesap makinesi seçeneklerini doldurmak için kullanılır ve alt grafik seçeneklerini de kullanabilirsiniz.

CalculatorGraphConfig öğesinde, bir alt grafik için grafik seçenekleri belirtilebilir aşağıda gösterildiği gibi hesap makinesi seçeneklerinden tam olarak benzerdir:

node {
  calculator: "FlowLimiterCalculator"
  input_stream: "image"
  output_stream: "throttled_image"
  node_options: {
    [type.googleapis.com/mediapipe.FlowLimiterCalculatorOptions] {
      max_in_flight: 1
    }
  }
}

node {
  calculator: "FaceDetectionSubgraph"
  input_stream: "IMAGE:throttled_image"
  node_options: {
    [type.googleapis.com/mediapipe.FaceDetectionOptions] {
      tensor_width: 192
      tensor_height: 192
    }
  }
}

CalculatorGraphConfig sisteminde, grafik seçenekleri kabul edilebilir ve doldurmak için kullanılabilir hesap makinesi seçenekleri için aşağıdaki gibidir:

graph_options: {
  [type.googleapis.com/mediapipe.FaceDetectionOptions] {}
}

node: {
  calculator: "ImageToTensorCalculator"
  input_stream: "IMAGE:image"
  node_options: {
    [type.googleapis.com/mediapipe.ImageToTensorCalculatorOptions] {
        keep_aspect_ratio: true
        border_mode: BORDER_ZERO
    }
  }
  option_value: "output_tensor_width:options/tensor_width"
  option_value: "output_tensor_height:options/tensor_height"
}

node {
  calculator: "InferenceCalculator"
  node_options: {
    [type.googleapis.com/mediapipe.InferenceCalculatorOptions] {}
  }
  option_value: "delegate:options/delegate"
  option_value: "model_path:options/model_path"
}

Bu örnekte FaceDetectionSubgraph, grafik seçeneği protobuf'u kabul eder FaceDetectionOptions. FaceDetectionOptions, bazı alanları tanımlamak için kullanılır hesap makinesi seçeneklerindeki ImageToTensorCalculatorOptions ve bazı alanlardaki değerler değerleri (InferenceCalculatorOptions) alt grafik seçeneklerinde gösterilir. Alan değerleri option_value: söz dizimi kullanılarak tanımlanır.

CalculatorGraphConfig::Node protokolünde node_options: ve option_value: birlikte, hesap makinesi için seçenek değerlerini tanımlar: ImageToTensorCalculator. node_options: alanı bir değişmez değer kümesini tanımlar sabit değerlere ayarlayabilirsiniz. Her bir option_value: alanı kapanıştaki bilgileri kullanarak bir protobuf alanının değerini tanımlar grafik, özellikle de kapanıştaki grafik seçeneklerinin alan değerlerinden grafiğe dönüştürülebilir. Yukarıdaki örnekte, option_value: "output_tensor_width:options/tensor_width", alanı tanımlar ImageToTensorCalculatorOptions.output_tensor_width değeri için FaceDetectionOptions.tensor_width.

option_value: söz dizimi, input_stream: söz dizimine benzer. İlgili içeriği oluşturmak için kullanılan söz dizimi option_value: "LHS:RHS" şeklindedir. LHS, bir hesap makinesi seçeneği belirler. RHS, bir grafik seçenek alanını tanımlar. Daha ayrıntılı belirtmek gerekirse, ve RHS'nin her biri, iç içe geçmiş verileri tanımlayan bir dizi protobuf alan adından oluşur Protobuf mesajları ve alanları "/" ile ayrılır. Bu, "ProtoPath" olarak bilinir. söz dizimine uygun olmalıdır. LHS veya RHS'de referans verilen iç içe yerleştirilmiş mesajlar zaten kullanılarak geçilmesi için ekteki protobuf'ta tanımlanmış olmalıdır. option_value:

Hayat Döngüleri

MediaPipe, varsayılan olarak hesap makinesi grafiklerinin simetrik olmasını gerektirir ve döngüleri ele alır. gösterir. Bir grafiğin döngüleri içermesi amaçlanıyorsa, döngülerin grafik yapılandırmasında ek açıklama yer almalıdır. Bu sayfada, bunun nasıl yapılacağı açıklanmaktadır.

NOT: Mevcut yaklaşım deneyseldir ve değişebilir. Rica ederim geri bildiriminizi paylaşın.

Lütfen CalculatorGraphTest.Cycle birim testini şurada kullanın: Örnek kod olarak mediapipe/framework/calculator_graph_test.cc. Aşağıda gösterilen: döngü grafiğidir. Toplayıcının sum çıkışı, Kaynak hesap makinesi tarafından oluşturulan tam sayılar.

bir tam sayı akışı ekleyen döngüsel grafik

Bu basit grafikte, döngüsel grafikleri desteklemeyle ilgili tüm sorunlar gösterilmiştir.

Arka Kenar Ek Açıklaması

Her döngüdeki bir kenara arka kenar olarak açıklama eklenmesi gerekir. Bu da Tüm arka kenarları kaldırdıktan sonra MediaPipe'in topolojik sıralaması çalışır.

Genellikle arka kenarları seçmenin birden çok yolu vardır. Hangi kenarlar işaretlenir? olarak değerlendirileceğinden, arka kenarların hangi düğümlerin yukarı akış olarak kabul edileceğini ve hangi aşağı akış olarak kabul edilir; bu da MediaPipe'in .

Örneğin, CalculatorGraphTest.Cycle testi old_sum kenarını Bu nedenle, Gecikme düğümü, toplayıcının aşağı akış düğümü olarak kabul edilir. verilir ve kullanıcıya daha yüksek bir öncelik verilir. Alternatif olarak, sum gecikme düğümüne arka kenar olarak giriş yapabilirsiniz. Bu durumda, gecikme düğümü toplayıcı düğümün bir yukarı akış düğümü olarak kabul edilir ve kendisine daha düşük bir öncelik verilir.

İlk paket

Tamsayıdaki ilk tam sayı, toplayıcı hesap makinesinin çalıştırılabilir olması için geldiğinde, değeri 0 olan ve değeri aynı olan bir zaman damgasını (old_sum giriş akışında) ekler. Bu ilk paket Open() yöntemindeki gecikme hesaplayıcı ile çıktı alınmalıdır.

Döngüdeki Gecikme

Her döngüde önceki sum çıkışının sonrakiyle hizalanması için bir gecikme gerekir tam sayı girişi. Bu işlem, gecikme düğümü tarafından da yapılır. Bu nedenle, gecikme düğümünün tamsayı kaynak hesaplayıcının zaman damgaları hakkında aşağıdakileri öğrenin:

  • İlk çıkışın zaman damgası.

  • Ardışık çıkışlar arasındaki zaman damgası deltasıdır.

Yalnızca paketlerle ilgilenen alternatif bir planlama politikası eklemeyi planlıyoruz vardır ve paket zaman damgalarını yok sayar. Böylece bu sıkıntılar ortadan kalkar.

Bir Giriş Akışı Tamamlandığında Hesap Makinesinin Erken Sonlandırılması

Varsayılan olarak MediaPipe, aşağıdaki durumlarda kaynak olmayan bir hesap makinesinin Close() yöntemini çağırır: giriş akışlarının tamamlanmış olması gerekir. Örnek grafikte, tam sayı kaynağı tamamlandığı zaman toplayıcı düğümünü kullanabilirsiniz. Bu, toplayıcı düğümünü alternatif bir giriş akışı işleyiciyle yapılandırarak EarlyCloseInputStreamHandler

İlgili Kaynak Kodu

Gecikme Hesaplayıcı

Open() içindeki kodu, ilk paketi ve Giriş paketlerine (birim) gecikme ekleyen Process(). Yukarıda belirtildiği gibi, bu gecikme düğümü, çıkış akışının doğru bir giriş akışı olan bir giriş akışıyla birlikte kullanıldığını paket zaman damgaları 0, 1, 2, 3, ...

class UnitDelayCalculator : public Calculator {
 public:
  static absl::Status FillExpectations(
      const CalculatorOptions& extendable_options, PacketTypeSet* inputs,
      PacketTypeSet* outputs, PacketTypeSet* input_side_packets) {
    inputs->Index(0)->Set<int>("An integer.");
    outputs->Index(0)->Set<int>("The input delayed by one time unit.");
    return absl::OkStatus();
  }

  absl::Status Open() final {
    Output()->Add(new int(0), Timestamp(0));
    return absl::OkStatus();
  }

  absl::Status Process() final {
    const Packet& packet = Input()->Value();
    Output()->AddPacket(packet.At(packet.Timestamp().NextAllowedInStream()));
    return absl::OkStatus();
  }
};

Grafik Yapılandırması

back_edge ek açıklamasını ve input_stream_handler alternatifini not edin.

node {
  calculator: 'GlobalCountSourceCalculator'
  input_side_packet: 'global_counter'
  output_stream: 'integers'
}
node {
  calculator: 'IntAdderCalculator'
  input_stream: 'integers'
  input_stream: 'old_sum'
  input_stream_info: {
    tag_index: ':1'  # 'old_sum'
    back_edge: true
  }
  output_stream: 'sum'
  input_stream_handler {
    input_stream_handler: 'EarlyCloseInputStreamHandler'
  }
}
node {
  calculator: 'UnitDelayCalculator'
  input_stream: 'sum'
  output_stream: 'old_sum'
}