---
title: 概要
slug: api-guide/ja/XQGkFJw-j1zju2QYyCDqp
docTags: 
createdAt: 2024-12-17T10:27:12.055Z
---

## さまざまな種類のシーン

シーンとは、まとめてアノテーションされるべきセンサーデータ（例：カメラ画像、LiDAR点群）のグループを表します。カメラ解像度、センサー名、データが記録された周波数など、センサーとそれらが取得したデータとの関係を記述するために必要な情報も、シーン内で指定します。

シーンの内容を表すためにどの種類のセンサーを使用するかによって、さまざまなシーンタイプがあります。例えば、カメラセンサーの画像データのみで構成されるシーンを作成する場合は、シーンタイプ`Cameras`を使用します。同様に、LiDARとカメラの両方のセンサーで構成されるシーンを作成する場合は、シーンタイプ`LidarsAndCameras`を使用します。また、シーンは*単一フレーム*タイプまたは*シーケンス*タイプのいずれかになります。

### シーケンシャルシーンと非シーケンシャルシーン

シーケンシャルシーンは時間軸上のフレームの*シーケンス*を表し、非シーケンシャルシーンはセンサーデータのスナップショットを1つだけ含みます。シーケンシャルな関係は**フレーム**のシーケンスによって表現されます。各フレームには、そのフレームを構成するセンサーデータの種類に関する情報（例：どの画像や点群がそのフレームに含まれるか）と、そのフレームが（他のフレームに対して）時間軸上のどこに位置するかを示す*相対タイムスタンプ*が含まれます。

非シーケンシャルシーンには単一のフレームのみが含まれ、相対タイムスタンプ情報は不要です。

シーケンシャルシーンタイプは、タイプ名の末尾に`Seq`が付いていることで識別されます。

現在、以下のシーンタイプをサポートしています：

- `Cameras`
- `LidarsAndCameras`
- `CamerasSeq`
- `LidarsAndCamerasSeq`
- `AggregatedLidarsAndCamerasSeq`

## シーンのフィールド

非シーケンシャルシーンの構造は以下のとおりです：

```python
class Scene(BaseModel):
    external_id: str
    frame: Frame
    sensor_specification: SensorSpecification
    calibration_id: Optional[str] # Required if using lidar sensors
    metadata: Mapping[str, Union[int, float, str, bool]] = field(default_factory=dict)
```

シーケンシャルシーンも同様の構造で表現されますが、単一のフレームの代わりにフレームのリストを含みます：

```python
class SceneSeq(BaseModel):
    external_id: str
    frames: List[Frame]
    sensor_specification: SensorSpecification
    calibration_id: Optional[str] # Required if using lidar sensors
    metadata: Mapping[str, Union[int, float, str, bool]] = field(default_factory=dict)
```

### 外部ID

シーンには作成時に自動的にUUIDが付与されます。このUUIDは、Kognicおよび当社のすべての内部システムで主要な識別子として使用されます。また、特定のシーンについてのやり取りを容易にするため、シーンを作成する際には識別子として外部IDが必要です。

### センサー仕様

センサー仕様には、シーンで使用されるカメラセンサーやLiDARセンサーに関する情報が含まれます。

追加のフィールドはオプションで、Kognicアノテーションアプリで表示する際のカメラ画像の順序や、人が読みやすいセンサー名（例：「FC」の代わりに「Front Camera」）を指定するために使用できます。

例として、自車両に3つのカメラセンサー`R`、`F`、`L`が搭載されているとします。センサー仕様の作成は以下のようになります：

```python
from kognic.io.model import SensorSpecification

sensor_spec = SensorSpecification(
    sensor_to_pretty_name={
        "R": "Right Camera",
        "F": "Front Camera",
        "L": "Left Camera"
    },
    sensor_order=["L", "F", "R"]
)
```

`sensor_order`はカメラ画像の順序を設定し、`sensor_to_pretty_name`はKognicアノテーションアプリで表示される際のラベルに影響します。

### キャリブレーション

LiDARセンサーとカメラセンサーで構成されるシーンには、キャリブレーションが必要です。キャリブレーションは、センサー間の空間的な関係（位置と回転）およびカメラの内部パラメータを指定します。

ただし、LiDARセンサーを含まないシーンにはキャリブレーションは不要です。

キャリブレーションは、Kognicアノテーションアプリでカメラ画像が選択された際に点群内の領域を投影するため、また同様に、点群内で選択されたオブジェクト（例：点、キューボイド）を画像に投影するために使用されます。

キャリブレーションを作成する際、すべてのセンサーはシーンに存在するセンサーと一致している必要があります。一致しない場合、シーンは作成されず、Kognic APIからバリデーションエラーが返されます。

APIを介したキャリブレーションの作成に関する詳細なドキュメントは、[キャリブレーション概要](docId:40uJEbw5cST4e4djxsgty)に記載されています。

### メタデータ

メタデータは`metadata`フィールドを介してシーンに追加できます。フラットなキーと値のペアで構成されており、ネストされたデータ構造は使用できません。メタデータはシーンに関する追加情報を含めるために使用できます。メタデータはアノテーターには表示されませんが、Kognicアノテーションツールの動作を変更できる予約済みキーワードがいくつかあります。予約済みキーワードは、Pythonクライアントの`MetaData`オブジェクトで確認できます。

### フレーム

`Frame`オブジェクトは、アノテーション対象のバイナリデータ（.jpg、.png、.lasなど）と、そのデータの元となったセンサーを指定します。`Frame`オブジェクトは全体的な構造は似ていますが、シーンタイプごとに異なることに注意してください（詳細は以下を参照）。

### 非シーケンシャルフレーム

例として、3つのカメラセンサー`R`、`F`、`L`からの画像で構成されるシーンを作成するとします。対応するバイナリデータはファイル`img_cam_R.jpg`、`img_cam_F.jpg`、`img_cam_L.jpg`に格納されています。これはシーンタイプ`Cameras`に対応します：

```python
from kognic.io.model.scene.resources import Image
from kognic.io.model.scene.cameras import Cameras, Frame

cameras_scene = Cameras(
    ...,
    frame=Frame(
        images=[
            Image("img_cam_R.jpg", sensor_name="R"),
            Image("img_cam_F.jpg", sensor_name="F"),
            Image("img_cam_L.jpg", sensor_name="L"),
        ]
    )
)
```

同様に、センサー`VDL-64`からの関連するLiDAR点群と対応するバイナリファイル`scan_vdl_64.las`もある場合は、代わりにシーンタイプ`LidarsAndCameras`を使用します。`Frame`クラスは、対応するシーンタイプの下からインポートする必要があることに注意してください：

```python
from kognic.io.model.scene.resources import Image, PointCloud
from kognic.io.model.scene.lidars_and_cameras import LidarsAndCameras, Frame

lidars_and_cameras = LidarsAndCameras(
    ...,
    frame=Frame(
        images=[
            Image("img_cam_R.jpg", sensor_name="R"),
            Image("img_cam_F.jpg", sensor_name="F"),
            Image("img_cam_L.jpg", sensor_name="L"),
        ],
        point_clouds=[
            PointCloud("scan_vdl_64.las", sensor_name="VDL-64")
        ]
    )

)
```

### シーケンシャルフレーム

シーケンシャルシーンは、単一の`Frame`の代わりに`Frame`オブジェクトのリストを受け取ります。また、シーケンシャルシーンに関連する`Frame`オブジェクトには、`frame_id`、`relative_timestamp`、`metadata`の3つの追加パラメータがあります。

シーケンシャルな関係は、`Frame`のリストの順序によって表現されます。

異なるフレーム間の経過時間を表すには、各`Frame`の`relative_timestamp`パラメータを使用します。相対タイムスタンプはミリ秒単位で表され、`Frame`とシーンの開始時点との間の相対的な時間を表します。

例えば、センサーデータが2Hzで収集・集約されているとします：

```python
frame_1 = Frame(..., relative_timestamp=0)
frame_2 = Frame(..., relative_timestamp=500)
frame_3 = Frame(..., relative_timestamp=1000)
frames = [frame_1, frame_2, frame_3]
```

`frame_id`は、フレームのリスト内で各フレームを一意に識別する文字列です。

一般的な使用例として、各`frame_id`にUUIDを使用するか、`external_id`と`frame_index`を組み合わせる方法があります。例えば、シーンの`external_id`が`shanghai_20200101`の場合、`frame_id`は最初のフレームを`shanghai_20200101:0`、2番目のフレームを`shanghai_20200101:1`というようにエンコードできます。

シーケンシャルフレームでは、*フレーム*レベルで`metadata`を指定することも可能です。これは*フラット*なキーと値のペアで構成され、アノテーション作業中にアノテーターには表示されません。

例として、2つのセンサー`R`と`L`からのカメラ画像を持つ2フレームで構成される`CamerasSequence`タイプのシーンを作成するとします：

```python
from kognic.io.model.scene.resources import Image
from kognic.io.model.scene.cameras_sequence import CamerasSequence, Frame

frames = [
    Frame(
        frame_id="1",
        relative_timestamp=0,
        images=[
            Image("img_L_1.jpg", sensor_name='L'),
            Image("img_R_1.jpg", sensor_name='R')
        ]),
    Frame(
        frame_id="2",
        relative_timestamp=500,
        images=[
            Image("img_L_2.jpg", sensor_name='L'),
            Image("img_R_2.jpg", sensor_name='R')
        ])
]

cameras_sequence = CamerasSequence(frames=frames, ...)
```

## 画像と点群のリソース

センサーデータを含むすべてのファイルは`Resource`として表現され、`Image`と`PointCloud`がその具体的なサブクラスです。

```python
class Resource(ABC, BaseSerializer):
    filename: str
    resource_id: Optional[str] = None
    sensor_name: str
    file_data: Optional[FileData] = Field(default=None, exclude=True)
```

`Resource`は最終的に、バイナリまたはテキストのセンサーデータを取得する方法を記述するもので、以下のさまざまな方法で実現できます：

1. 間接的に：データを含むローカルファイル名を参照する
2. 直接的に：作成時にバイトライクオブジェクトを提供する
3. 遅延的に：後のプロセスでバイトを提供できるコールバック関数を指定する

`Resource`には常に`filename`を指定する必要があります。方法1の場合、これはアップロードするローカルファイルを指す必要があります。方法2および3の場合、`filename`パラメータの値は識別子として扱われます。アップロードされるファイルの名前付けに使用されますが、ファイルシステム上のパスと一致している必要はありません。

`Resource`には常に`sensor_name`があり、データが取得されたセンサーを識別します。シーケンシャルシーンでは、各`Frame`に各センサーの`Resource`が含まれます。

上記の方法2および3では、`FileData`オブジェクトを`Resource`（`Image`または`PointCloud`）に付加してデータのソースを指定します。`FileData`は`data: UploadableData`または`callback: Callable[[str], UploadableData]`のいずれかと、バイトに含まれるデータの種類を識別する`format`を指定して作成します。以下にその例を示します。`UploadableData`は生データのサポートされるソース（`bytes`、`BinaryIO`、`IOBase`、および`bytes`のジェネレーターと非同期ジェネレーター）に対する型エイリアスです。

以前のAPIクライアントのリリースでは、`gs://bucket/path/file`などの外部URIからのファイル取り込みのサポートが案内されていました。今後この機能が必要な場合は、Kognicにお問い合わせください。

### ローカルファイル

`filename`をローカルファイルのパスに設定し、他の方法（直接またはコールバック）でデータを提供しないでください。コンテンツは`filename`のサフィックスから推定されたコンテンツタイプを使用してアップロードされます。

```python
Image(filename="/path/to/images/img_FC.png", sensor_name="FC")
```

### メモリ内データ

`filename`に加えて、`file_data`属性を介して`FileData`オブジェクトを提供します。`FileData`オブジェクトは`UploadableData`を`data`属性として持ちます。この例では生の`bytes`を使用します：

```python
Image(
    filename="FC-frame15",
    sensor_name="FC",
    file_data=FileData(data=b'some PNG bytes', format=FileData.Format.PNG)
)
```

### コールバックからのデータ

`filename`に加えて、`file_data`属性を介して`FileData`オブジェクトを提供します。`FileData`オブジェクトには`UploadableData`を生成する`callback`関数を指定します。例：

```python
Image(
    filename="FC-frame15",
    sensor_name="FC",
    file_data=FileData(callback=get_png, format=FileData.Format.PNG)
)
```

コールバック関数（`get_png`）は、以下のシグネチャを持つ単項関数です：

```python
def get_png(filename: str) -> UploadableData:
    pass
```

コールバック関数は、単一ファイルのアップロード時に`Resource.filename`を引数として呼び出されます。

コールバックに追加の引数が必要な場合は、以下のように追加の引数をクロージャでラップすることを推奨します：

```python
def get_callback(arg1, arg2, **kwargs):
     def callback(filename) -> bytes:
         # ... use arg1, arg2, filename and kwargs

     return callback

FileData(
    callback=get_callback("foo", "bar", extra1="baz", extra2="qux"),
    format=FileData.Format.JPG
)
```

### 非同期コールバックからのデータ

非同期コールバックを使用すると、特にデータがローカルで利用できない場合に、データのアップロードを高速化できます。同期コールバックと同様に、コールバック関数は単一ファイルのアップロード時に`Resource.filename`を引数として呼び出されます。非同期コールバックは以下のように使用できます：

```python
async def get_png(filename: str) -> UploadableData:
    pass

Image(
    filename="FC-frame15",
    sensor_name="FC",
    file_data=FileData(callback=get_png, format=FileData.Format.PNG)
)
```

### データストリーム

`filename`に加えて、`file_data`属性を介して`FileData`オブジェクトを提供します。`FileData`オブジェクトの`callback`属性にはバイトジェネレーターまたは非同期ジェネレーターを指定します。この例では、非同期ジェネレーターを使用してローカルファイルを小さなチャンクで非常にゆっくりとストリーミングします：

```python
async def slow_stream(filename: str) -> AsyncGenerator[bytes, Any]:
    with open(filename, "rb") as f:
        while chunk := f.read(1024):
            asyncio.sleep(1)
            yield chunk

Image(
    filename="FC-frame15",
    sensor_name="FC",
    file_data=FileData(callback=slow_stream, format=FileData.Format.PNG)
)
```

## IMUデータ

慣性計測装置（IMU）データは、LiDAR点群を含むシーンに対して提供できます。これは複数LiDAR構成でのモーション補償を実行するために使用でき、デフォルトではIMUデータが提供された場合にモーション補償が実行されます。アップロード前にすでにモーション補償が実行済みの場合は、[シーンのフィーチャーフラグ](docId\:R7JjwWZw8kl3luX52WDod)でモーション補償を無効化できます。

複数LiDAR構成でのモーション補償については、[モーション補償](docId:-UnWSC-cucoYH-mU9JOsc)を参照してください。

## シーンのフィーチャーフラグ

シーン作成プロセスのオプション部分は、シーンの作成操作を呼び出す際に渡す`FeatureFlags`で制御できます。詳細は[シーンのフィーチャーフラグ](docId\:R7JjwWZw8kl3luX52WDod)を参照してください。
