---
title: LiDARとカメラシーケンス
slug: api-guide/ja/Czk0-lidar
docTags: 
createdAt: 2024-12-16T14:19:04.063Z
---

:::hint{type="info"}
kognic-io 2.5.0以降、シーンタイプ（`LidarsAndCamerasSequence`）を公開せず、単一のモデルからあらゆるシーンを簡単に作成できる新しいシーンモデルを推奨しています。
:::

`LidarsAndCamerasSequence`は、カメラ画像とLiDAR点群のシーケンスで構成され、各フレームには1〜20枚のカメラ画像と1〜20個の点群が含まれます。`LidarsAndCamerasSequence`オブジェクトの各フィールドの詳細については、シーンの[概要](docId\:M9gJ_7GE3M0jf7hvLohJ2)の関連セクションをご覧ください。

```python
from __future__ import absolute_import

from datetime import datetime
from typing import Optional
from uuid import uuid4

import kognic.io.model.scene.lidars_and_cameras_sequence as LCSM
from examples.calibration.calibration import create_sensor_calibration
from kognic.io.client import KognicIOClient
from kognic.io.logger import setup_logging
from kognic.io.model import CreateSceneResponse, Image, PointCloud


def run(client: KognicIOClient, dryrun: bool = True, **kwargs) -> Optional[CreateSceneResponse]:
    print("Creating Lidar and Camera Sequence Scene...")

    lidar_sensor1 = "lidar"
    cam_sensor1 = "RFC01"
    cam_sensor2 = "RFC02"
    metadata = {"location-lat": 27.986065, "location-long": 86.922623, "vehicle_id": "abg"}

    # Create calibration
    # (Please refer to the API documentation about calibration for more details)
    calibration_spec = create_sensor_calibration(
        f"Collection {datetime.now()}",
        [lidar_sensor1],
        [cam_sensor1, cam_sensor2],
    )
    created_calibration = client.calibration.create_calibration(calibration_spec)

    scene = LCSM.LidarsAndCamerasSequence(
        external_id=f"LCS-example-{uuid4()}",
        frames=[
            LCSM.Frame(
                frame_id="1",
                relative_timestamp=0,
                point_clouds=[
                    PointCloud(
                        filename="./examples/resources/point_cloud_RFL01.las",
                        sensor_name=lidar_sensor1,
                    ),
                ],
                images=[
                    Image(
                        filename="./examples/resources/img_RFC01.jpg",
                        sensor_name=cam_sensor1,
                    ),
                    Image(
                        filename="./examples/resources/img_RFC02.jpg",
                        sensor_name=cam_sensor2,
                    ),
                ],
                metadata={"dut_status": "active"},
            ),
            LCSM.Frame(
                frame_id="2",
                relative_timestamp=100,
                point_clouds=[
                    PointCloud(
                        filename="./examples/resources/point_cloud_RFL02.las",
                        sensor_name=lidar_sensor1,
                    ),
                ],
                images=[
                    Image(
                        filename="./examples/resources/img_RFC11.jpg",
                        sensor_name=cam_sensor1,
                    ),
                    Image(
                        filename="./examples/resources/img_RFC12.jpg",
                        sensor_name=cam_sensor2,
                    ),
                ],
                metadata={"dut_status": "active"},
            ),
        ],
        calibration_id=created_calibration.id,
        metadata=metadata,
    )
    # Create scene
    return client.lidars_and_cameras_sequence.create(scene, dryrun=dryrun, **kwargs)


if __name__ == "__main__":
    setup_logging(level="INFO")
    client = KognicIOClient()

    # Project - Available via `client.project.get_projects()`
    project = "<project-identifier>"

    run(client, project)
```

:::hint{type="success"}
### dryrunを使用してシーンを検証する

メソッド呼び出しで`dryrun`パラメータをtrueに設定すると、APIを使用してシーンが検証されますが、実際には作成されません。
:::

:::hint{type="success"}
### キャリブレーションの再利用

可能であれば、同じキャリブレーションを複数のシーンで再利用でき、また再利用すべきです。
:::

## 自車両モーション情報を提供する

自車両モーション（すなわち、自車両の位置と回転）は、`LidarsAndCamerasSeq`を作成する際に提供できるオプション情報です。この情報により、静的オブジェクトのアノテーションにかかる時間を大幅に短縮できます。自車両モーション情報は、シーン内の**各**`Frame`に`EgoVehicleMotion`オブジェクトを渡すことで提供します。

```python
from __future__ import absolute_import

from datetime import datetime
from typing import Optional
from uuid import uuid4

import kognic.io.model.scene.lidars_and_cameras_sequence as LCSM
from examples.calibration.calibration import create_sensor_calibration
from kognic.io.client import KognicIOClient
from kognic.io.logger import setup_logging
from kognic.io.model import CreateSceneResponse, EgoVehiclePose, Image, PointCloud, Position, RotationQuaternion


def run(client: KognicIOClient, dryrun: bool = True, **kwargs) -> Optional[CreateSceneResponse]:
    print("Creating Lidar and Camera Sequence Scene...")

    lidar_sensor1 = "lidar"
    cam_sensor1 = "RFC01"
    cam_sensor2 = "RFC02"
    cam_sensor3 = "RFC03"
    metadata = {"location-lat": 27.986065, "location-long": 86.922623, "vehicle_id": "abg"}

    # Create calibration
    calibration_spec = create_sensor_calibration(f"Collection {datetime.now()}", [lidar_sensor1], [cam_sensor1, cam_sensor2, cam_sensor3])
    created_calibration = client.calibration.create_calibration(calibration_spec)

    scene = LCSM.LidarsAndCamerasSequence(
        external_id=f"LCS-full-example-{uuid4()}",
        frames=[
            LCSM.Frame(
                frame_id="1",
                relative_timestamp=0,
                point_clouds=[
                    PointCloud(filename="./examples/resources/point_cloud_RFL01.las", sensor_name=lidar_sensor1),
                ],
                images=[
                    Image(filename="./examples/resources/img_RFC01.jpg", sensor_name=cam_sensor1),
                    Image(filename="./examples/resources/img_RFC02.jpg", sensor_name=cam_sensor2),
                ],
                metadata={"dut_status": "active"},
                ego_vehicle_pose=EgoVehiclePose(
                    position=Position(x=1.0, y=1.0, z=1.0), rotation=RotationQuaternion(w=0.01, x=1.01, y=1.01, z=1.01)
                ),
            ),
            LCSM.Frame(
                frame_id="2",
                relative_timestamp=500,
                point_clouds=[
                    PointCloud(filename="./examples/resources/point_cloud_RFL02.las", sensor_name=lidar_sensor1),
                ],
                images=[
                    Image(filename="./examples/resources/img_RFC11.jpg", sensor_name=cam_sensor1),
                    Image(filename="./examples/resources/img_RFC12.jpg", sensor_name=cam_sensor2),
                ],
                ego_vehicle_pose=EgoVehiclePose(
                    position=Position(x=2.0, y=2.0, z=2.0), rotation=RotationQuaternion(w=0.01, x=2.01, y=2.01, z=2.01)
                ),
            ),
        ],
        calibration_id=created_calibration.id,
        metadata=metadata,
    )
    # Create scene
    return client.lidars_and_cameras_sequence.create(scene, dryrun=dryrun, **kwargs)


if __name__ == "__main__":
    setup_logging(level="INFO")
    client = KognicIOClient()

    # Project - Available via `client.project.get_projects()`
    project = "<project-identifier>"

    run(client, project=project)
```

:::hint{type="info"}
### 座標系

自車両ポーズの`position`と`rotation`は、いずれも*ローカル*座標系を基準とすることにご注意ください。
:::

## シャッタータイミング

シャッタータイミングは、`Frame`内の`Image`に指定できます。

シャッタータイミングは、ナノ秒単位のUnixタイムスタンプ値のペア（シャッター開始時刻と終了時刻）で、両方を指定する必要があります。各フレームの各画像に対して指定します。

```python
from __future__ import absolute_import

import os.path
from datetime import datetime
from typing import Optional
from uuid import uuid4

import kognic.io.model.scene.lidars_and_cameras_sequence as LCSM
from examples.calibration.calibration import create_sensor_calibration
from examples.imu_data.create_imu_data import create_dummy_imu_data
from kognic.io.client import KognicIOClient
from kognic.io.logger import setup_logging
from kognic.io.model import CreateSceneResponse, Image, ImageMetadata, PointCloud


def run(client: KognicIOClient, dryrun: bool = True, **kwargs) -> Optional[CreateSceneResponse]:
    print("Creating Lidar and Camera Sequence Scene...")

    lidar_sensor1 = "RFL01"
    lidar_sensor2 = "RFL02"
    cam_sensor1 = "RFC01"
    cam_sensor2 = "RFC02"
    metadata = {"location-lat": 27.986065, "location-long": 86.922623, "vehicleId": "abg"}
    examples_path = os.path.dirname(__file__)

    # Create calibration
    calibration_spec = create_sensor_calibration(f"Collection {datetime.now()}", [lidar_sensor1, lidar_sensor2], [cam_sensor1, cam_sensor2])
    created_calibration = client.calibration.create_calibration(calibration_spec)

    # Generate IMU data
    ONE_MILLISECOND = 1000000  # one millisecond, expressed in nanos
    start_ts = 1648200140000000000
    end_ts = start_ts + 10 * ONE_MILLISECOND
    imu_data = create_dummy_imu_data(start_timestamp=start_ts, end_timestamp=end_ts, samples_per_sec=1000)

    scene = LCSM.LidarsAndCamerasSequence(
        external_id=f"LCS-full-with-imu-and-shutter-example-{uuid4()}",
        frames=[
            LCSM.Frame(
                frame_id="1",
                unix_timestamp=start_ts + ONE_MILLISECOND,
                relative_timestamp=0,
                point_clouds=[
                    PointCloud(filename=examples_path + "/resources/point_cloud_RFL01.csv", sensor_name=lidar_sensor1),
                    PointCloud(filename=examples_path + "/resources/point_cloud_RFL02.csv", sensor_name=lidar_sensor2),
                ],
                images=[
                    Image(
                        filename=examples_path + "/resources/img_RFC01.jpg",
                        sensor_name=cam_sensor1,
                        metadata=ImageMetadata(
                            shutter_time_start_ns=start_ts + 0.5 * ONE_MILLISECOND, shutter_time_end_ns=start_ts + 1.5 * ONE_MILLISECOND
                        ),
                    ),
                    Image(
                        filename=examples_path + "/resources/img_RFC02.jpg",
                        sensor_name=cam_sensor2,
                        metadata=ImageMetadata(
                            shutter_time_start_ns=start_ts + 0.5 * ONE_MILLISECOND, shutter_time_end_ns=start_ts + 1.5 * ONE_MILLISECOND
                        ),
                    ),
                ],
            ),
            LCSM.Frame(
                frame_id="2",
                unix_timestamp=start_ts + 5 * ONE_MILLISECOND,
                relative_timestamp=4,
                point_clouds=[
                    PointCloud(filename=examples_path + "/resources/point_cloud_RFL11.csv", sensor_name=lidar_sensor1),
                    PointCloud(filename=examples_path + "/resources/point_cloud_RFL12.csv", sensor_name=lidar_sensor2),
                ],
                images=[
                    Image(
                        filename=examples_path + "/resources/img_RFC11.jpg",
                        sensor_name=cam_sensor1,
                        metadata=ImageMetadata(
                            shutter_time_start_ns=start_ts + 4.5 * ONE_MILLISECOND, shutter_time_end_ns=start_ts + 5.5 * ONE_MILLISECOND
                        ),
                    ),
                    Image(
                        filename=examples_path + "/resources/img_RFC12.jpg",
                        sensor_name=cam_sensor2,
                        metadata=ImageMetadata(
                            shutter_time_start_ns=start_ts + 4.5 * ONE_MILLISECOND, shutter_time_end_ns=start_ts + 5.5 * ONE_MILLISECOND
                        ),
                    ),
                ],
            ),
        ],
        calibration_id=created_calibration.id,
        metadata=metadata,
        imu_data=imu_data,
    )
    # Create scene
    return client.lidars_and_cameras_sequence.create(scene, dryrun=dryrun, **kwargs)


if __name__ == "__main__":
    setup_logging(level="INFO")
    client = KognicIOClient()

    # Project - Available via `client.project.get_projects()`
    project = "<project-id>"

    run(client, project=project)
```

### リバースローリングシャッター

:::hint{type="info"}
Kognic IO 2.17.0以降で利用できます。
:::

シャッタータイミングが設定されている場合、カメラのローリングシャッターが下から上に走査されるケースでは、`Images`の`reversed_shutter`フラグを`True`に設定できます。例えば、カメラが上下逆に取り付けられている場合、回転後の画像の最上行のピクセルは最下行のピクセルよりも後に撮像されます。アノテーションツールで最高品質の投影を得るには、アノテーションツールがこの違いを把握していることが重要です。

```python
ImageMetadata(
   shutter_time_start_ns=1775128684200000000,
   shutter_time_end_ns=1775128685000000000,
   reversed_shutter=True
 )
```
