> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/workflows/hi/developer-guide/developer-guide/data-representations.md).

# डेटा प्रस्तुतियाँ

Python डेटा प्रकार जिन्हें blocks रनटाइम पर प्राप्त करते हैं: Batch, WorkflowImageData, और VideoMetadata।

कई फ्रेमवर्क डेवलपर्स के काम करने के लिए मानक डेटा प्रकार लागू करते हैं, और Workflows इकोसिस्टम भी इससे अलग नहीं है। जबकि [प्रकार](/workflows/hi/developer-guide/developer-guide/kinds.md) एक Workflow में पास किए जा रहे डेटा के उच्च-स्तरीय अमूर्तीकरण का प्रतिनिधित्व करता है, इसलिए उन विशिष्ट डेटा प्रकारों को समझना महत्वपूर्ण है जो `WorkflowBlock.run(...)` मेथड को Workflow blocks बनाते समय प्रदान किए जाएंगे।

और यहीं आप बिल्कुल यही सीखेंगे।

## `Batch`

जब कोई Workflow block बैच प्रोसेसिंग घोषित करता है, तो वह Batch नामक एक विशेष कंटेनर प्रकार का उपयोग करता है। सभी बैच-उन्मुख पैरामीटर को `Batch[X]`से रैप किया जाता है, जहाँ X डेटा प्रकार है:

```python
from inference.core.workflows.execution_engine.entities.base import Batch
from inference.core.workflows.prototypes.block import BlockResult

# Workflow block का run method
def run(self, x: Batch[int], y: Batch[float]) -> BlockResult:
   pass
```

यह `Batch` प्रकार Python सूची की तरह कार्य करता है, लेकिन एक मुख्य अंतर के साथ: यह **केवल-पढ़ने योग्य**है। आप इसके तत्वों को संशोधित नहीं कर सकते, और न ही तत्व जोड़ या हटा सकते हैं। हालांकि, कई उपयोगी ऑपरेशन उपलब्ध हैं:

### तत्वों के माध्यम से इटरेशन

```python
from inference.core.workflows.execution_engine.entities.base import Batch

def iterate(batch: Batch[int]) -> None:
    for element in batch:
        print(element)
```

### कई बैंचों को ज़िप करना

{% hint style="info" %}
**बैचों के संरेखण की चिंता न करें**

Execution Engine यह सुनिश्चित करता है कि run method को प्रदान किए गए बैच समान आकार के हों, जिससे इटरेशन के दौरान असमान बैच आकारों के कारण किसी भी तत्व की हानि रोकी जाती है।
{% endhint %}

```python
from inference.core.workflows.execution_engine.entities.base import Batch

def zip_batches(batch_1: Batch[int], batch_2: Batch[float]) -> None:
    for element_1, element_2 in zip(batch_1, batch_2):
        print(element_1, element_2)
```

### बैच तत्व सूचकांकों को प्राप्त करना

यह ट्यूपलों की एक सूची लौटाता है, जहाँ प्रत्येक ट्यूपल संभावित रूप से नेस्टेड बैच संरचनाओं में बैच तत्व की स्थिति का प्रतिनिधित्व करता है।

```python
from inference.core.workflows.execution_engine.entities.base import Batch

def discover_indices(batch: Batch[int]) -> None:
    for index in batch.indices:
        print(index)  # जैसे, 1D बैच के लिए (0,), 2D नेस्टेड बैच के लिए (1, 3), आदि।
```

### तत्वों और उनके सूचकांकों दोनों को प्राप्त करते हुए इटरेशन

```python
from inference.core.workflows.execution_engine.entities.base import Batch

def iterate_with_indices(batch: Batch[int]) -> None:
    for index, element in batch.iter_with_indices():
        print(index, element)
```

### के अतिरिक्त मेथड्स `Batch` कंटेनर

Batch इंटरफ़ेस में अन्य मेथड भी हैं, जैसे `remove_by_indices(...)` या `broadcast(...)`, लेकिन इन्हें Workflow blocks के भीतर उपयोग करने के लिए अभिप्रेत नहीं किया गया है। इन मेथड्स का मुख्य रूप से उपयोग **block को डेटा प्रदान करते समय Execution Engine द्वारा किया जाता है।**

## `WorkflowImageData`

`WorkflowImageData` एक dataclass है जो एक image को उसकी metadata के साथ समाहित करती है, और Workflow block के भीतर image representation को manipulate करने के लिए उपयोगी methods प्रदान करती है।

कुछ उपयोगकर्ता यह अपेक्षा कर सकते हैं कि `np.ndarray` जब `image` kind घोषित किया जाता है, तो Execution Engine द्वारा सीधे प्रदान किया जाए। हालांकि यह एक सुविधाजनक और सरल दृष्टिकोण हो सकता है, लेकिन इससे कुछ सीमाएँ आती हैं, जैसे:

* **मेटाडेटा का अभाव:** केवल एक `np.ndarray`के साथ, data lineage या मूल फ़ाइल के भीतर image के स्थान जैसी metadata जोड़ने का कोई तरीका नहीं है (उदाहरण के लिए, cropped images के साथ काम करते समय)।
* **कई representations को cache करने में असमर्थता:** यदि कई blocks को image serialize करके HTTP के माध्यम से भेजनी हो, तो WorkflowImageData अलग-अलग image representations, जैसे base64-encoded versions, के cache की अनुमति देता है, जिससे दक्षता बेहतर होती है।

{% hint style="info" %}
**वीडियो मेटाडेटा**

चूँकि Execution Enginge `v1.2.0`, हमने `video_metadata` को `WorkflowImageData`में जोड़ा है। यह ऑब्जेक्ट वीडियो प्रोसेसिंग के संदर्भ को रखने के लिए है और केवल वीडियो प्रोसेसिंग blocks के लिए प्रासंगिक होगा। अन्य blocks इसके अस्तित्व की अनदेखी कर सकते हैं यदि वे आउटपुट image नहीं बना रहे हों (जिस पर अगले खंड में चर्चा की गई है)।
{% endhint %}

पर कार्य करना `WorkflowImageData` इसके इंटरफ़ेस को समझ लेने के बाद यह काफी सरल है। यहाँ कुछ मुख्य methods और properties हैं:

```python
from inference.core.workflows.execution_engine.entities.base import WorkflowImageData

def operate_on_image(workflow_image: WorkflowImageData) -> None:
    # image का प्रतिनिधित्व करने वाले np.ndarray को प्राप्त करना।
    numpy_image = workflow_image.numpy_image  
    
    # API transmission के लिए आदर्श, image का base64-encoded JPEG प्रतिनिधित्व प्राप्त करना।
    base64_image: str = workflow_image.base64_image  
    
    # image को inference models के अनुकूल format में बदलना।
    inference_format = workflow_image.to_inference_format()  
    
    # parent image से संबंधित metadata तक पहुँचता है
    parent_metadata = workflow_image.parent_metadata
    print(parent_metadata.parent_id)  # parent identifier
    origin_coordinates = parent_metadata.origin_coordinates  # coordinates वाला वैकल्पिक object
    print(
        origin_coordinates.left_top_x, origin_coordinates.left_top_y, 
        origin_coordinates.origin_width, origin_coordinates.origin_height,
    )
    
    # या root metadata के लिए भी यही (image का सबसे पुराना पूर्वज - Workflow input image)
    root_metadata = workflow_image.workflow_root_ancestor_metadata
    
    # `VideoMetadata` object प्राप्त करना - नीचे उपयोग मार्गदर्शिका अनुभाग देखें
    # यदि `workflow_image` के साथ `VideoMetadata` प्रदान नहीं किया गया है - तो डिफ़ॉल्ट metadata object 
    # property तक पहुँचने पर बनाया जाएगा
    video_metadata = workflow_image.video_metadata 
```

नीचे आप एक उदाहरण पा सकते हैं जो image को रूपांतरित करते समय metadata को सुरक्षित रखना दिखाता है

```python
import numpy as np

from inference.core.workflows.execution_engine.entities.base import WorkflowImageData

def transform_image(image: WorkflowImageData) -> WorkflowImageData:
    transformed_image = some_transformation(image.numpy_image)
    # `WorkflowImageData` एक helper method प्रदान करता है जिससे एक नया object लौटाया जा सकता है जिसमें
    # अद्यतन image हो, लेकिन preserved metadata के साथ। Metadata preservation
    # का उपयोग केवल तभी किया जाना चाहिए जब output image डेटा lineage के संदर्भ में संगत हो।
    # data lineage (images के लिए predecessor-successor संबंध)।
    # cropping और merging images (बिना common predecessor के) के लिए lineage संरक्षित नहीं रहती
    # - नीचे आप implementation tips पा सकते हैं।
    return WorkflowImageData.copy_and_replace(
        origin_image_data=image,
        numpy_image=transformed_image,
    )

def some_transformation(image: np.ndarray) -> np.ndarray:
    ...
```

<details>

<summary>छवियों की क्रॉपिंग</summary>

जब आपका block dimensionality बढ़ाता है और output प्रदान करता है जिसमें `image` kind - आमतौर पर इसका मतलब image को crop करना होता है। ऐसे मामलों में input image `video_metadata` को हटाया जाना चाहिए (क्योंकि आमतौर पर उन्हें रखना अर्थपूर्ण नहीं होता, और अंतर्निहित video processing blocks dynamically बनाए गए blocks के लिए सही ढंग से काम नहीं करेंगे)।

नीचे आप उस operation के लिए implementation का एक प्रारूप पा सकते हैं:

```python
from typing import List, Tuple

from dataclasses import replace
from inference.core.workflows.execution_engine.entities.base import WorkflowImageData

def crop_images(
    image: WorkflowImageData, 
    crops: List[Tuple[str, int, int, int, int]],
) -> List[WorkflowImageData]:
    crops = []
    original_image = image.numpy_image
    for crop_id, x_min, y_min, x_max, y_max in crops:
        cropped_image = original_image[y_min:y_max, x_min:x_max]
        if not cropped_image.size:
            # खाली crops को हटाया जा रहा है
            continue
        result_crop = WorkflowImageData.create_crop(
            origin_image_data=image, 
            crop_identifier=crop_id,
            cropped_image=cropped_image,
            offset_x=x_min,
            offset_y=y_min,
        )
        crops.append(result_crop)
    return crops
```

कुछ मामलों में आप संरक्षित रखना चाह सकते हैं `video_metadata`. ऐसी स्थिति का एक उदाहरण तब है जब आपका block स्थिर निर्देशांकों के आधार पर crops बनाता है (जैसे कई स्थिर Regions of Interest वाला video single footage, जिन पर अलग-अलग trackers लागू किए जाने हैं) - तब आप चाहते हैं कि परिणामस्वरूप crops को वीडियो के संदर्भ में संसाधित किया जाए, मानो वे अलग-अलग cameras द्वारा उत्पन्न किए गए हों। व्यवहार को समायोजित करने के लिए `create_crop(...)` मेथड के, बस जोड़ें `preserve_video_metadata=True`:

```python
def crop_images(
    image: WorkflowImageData, 
    crops: List[Tuple[str, int, int, int, int]],
) -> List[WorkflowImageData]:
    # [...]
    result_crop = WorkflowImageData.create_crop(
        origin_image_data=image, 
        crop_identifier=crop_id,
        cropped_image=cropped_image,
        offset_x=x_min,
        offset_y=y_min,
        preserve_video_metadata=True
    )
    # [...]
```

</details>

<details>

<summary>साझा पूर्वज के बिना images का विलय</summary>

यदि साझा `parent_metadata` को उन multiple images के लिए नहीं इंगित किया जा सकता जिन्हें आप merge करने का प्रयास कर रहे हैं, तो आपको यह दर्शाना चाहिए कि Workflow में "एक नई" image प्रकट होती है। ऐसा करने के लिए बस:

```python
from typing import List, Tuple

from dataclasses import replace
from inference.core.workflows.execution_engine.entities.base import \
    WorkflowImageData, ImageParentMetadata

def merge_images(image_1: WorkflowImageData, image_2: WorkflowImageData) -> WorkflowImageData:
    merged_image = some_mergin_operation(
        image_1=image_1.numpy_image,
        image_2=image_2.numpy_image
    )
    new_parent_metadata = ImageParentMetadata(
        # id बनाने के कई विकल्पों में से यह सिर्फ एक है, फिर भी एक उचित विकल्प है
        parent_id=f"{image_1.parent_metadata.parent_id} + {image_2.parent_metadata.parent_id}"
    )
    return WorkflowImageData(
        parent_metadata=new_parent_metadata,
        numpy_image=merged_imagem
    )
```

</details>

## `VideoMetadata`

{% hint style="warning" %}
**अप्रचलन**

[`video_metadata` प्रकार](/workflows/hi/developer-guide/developer-guide/kinds/video-metadata.md) अप्रचलित है - हम नए blocks में उस प्रकार का उपयोग न करने की सलाह देते हैं। `VideoMetadata` data representation का सदस्य बन गया `WorkflowImageData` Execution Engine में `v1.2.0` (`inference` रिलीज़ `v0.23.0`)
{% endhint %}

`VideoMetadata` एक dataclass है जो वीडियो फ्रेम और वीडियो स्रोत के बारे में निम्नलिखित metadata प्रदान करती है:

```python
from inference.core.workflows.execution_engine.entities.base import VideoMetadata

def inspect_vide_metadata(video_metadata: VideoMetadata) -> None:
    # वीडियो के लिए पहचानकर्ता स्ट्रिंग। इसे opaque माना जाना चाहिए।
    print(video_metadata.video_identifier)
    
    # फ्रेम का क्रमिक नंबर
    print(video_metadata.frame_number)
    
    # वीडियो फ्रेम का टाइमस्टैम्प। वीडियो प्रोसेस करते समय सुझाव दिया जाता है कि "
    # "blocks `fps` और `frame_number` पर निर्भर रहें, क्योंकि वास्तविक दुनिया का समय-बीतना "
    # "वीडियो फ़ाइल में समय-बीतने से मेल नहीं खाएगा
    print(video_metadata.frame_timestamp)
    
    # यह फ़ील्ड FPS मान का प्रतिनिधित्व करती है (यदि प्राप्त करना संभव हो) (वैकल्पिक)
    print(video_metadata.fps)
    
    # यह फ़ील्ड लाइव स्ट्रीम के मापे गए FPS का प्रतिनिधित्व करती है (वैकल्पिक)
    print(video_metadata.measured_fps)
    
    # यह फ़ील्ड एक ध्वज है जो बताता है कि फ्रेम वीडियो फ़ाइल से आया है या स्ट्रीम से।
    # यदि निर्धारित करना संभव न हो - None
    print(video_metadata.comes_from_video_file)
```
