WebcamのPan, Tilt, Zoom を制御する

Pan は左右の首振り、Tiltは上下の首振りです。これとZoomを合わせてPTZ と呼んだりします。
PTZ camera というのは実際にモーターで旋回することのできるカメラです。
本物のPTZ cameraは10万円以上する高価なものですが、ちょっといいWebcamだとデジタル的にPan, Tilt, Zoomを設定できるものがあります。


## webcamで設定可能な項目を調べる
Ubuntu 18.04 またはRaspbian buster で

```
$ sudo apt install v4l-utils
```

これで `v4l2-ctl` コマンドが使えるようになります。

```
$ v4l2-ctl -d /dev/video0 -l
                     brightness 0x00980900 (int)    : min=-64 max=64 step=1 default=0 value=0
                       contrast 0x00980901 (int)    : min=0 max=95 step=1 default=1 value=1
                     saturation 0x00980902 (int)    : min=0 max=100 step=1 default=60 value=60
                            hue 0x00980903 (int)    : min=-2000 max=2000 step=1 default=0 value=0
 white_balance_temperature_auto 0x0098090c (bool)   : default=1 value=1
                          gamma 0x00980910 (int)    : min=64 max=300 step=1 default=100 value=100
                           gain 0x00980913 (int)    : min=0 max=255 step=1 default=100 value=100
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=1 value=1
      white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=1 default=4600 value=4600 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=7 step=1 default=0 value=0
         backlight_compensation 0x0098091c (int)    : min=0 max=100 step=1 default=64 value=64
                  exposure_auto 0x009a0901 (menu)   : min=0 max=3 default=3 value=3
              exposure_absolute 0x009a0902 (int)    : min=1 max=10000 step=1 default=156 value=156 flags=inactive
                   pan_absolute 0x009a0908 (int)    : min=-648000 max=648000 step=3600 default=0 value=0
                  tilt_absolute 0x009a0909 (int)    : min=-648000 max=648000 step=3600 default=0 value=0
                 focus_absolute 0x009a090a (int)    : min=0 max=1023 step=1 default=0 value=0 flags=inactive
                     focus_auto 0x009a090c (bool)   : default=1 value=1
                  zoom_absolute 0x009a090d (int)    : min=0 max=60 step=1 default=0 value=0
```

どんな項目があるかはwebcamの機種によって異なります。
`pan_absolute`, `tilt_absolute`, `zoom_absolute` の項目があれば、Pan, Tilt, Zoomを制御することができます。
[先日紹介した4K Webcam](https://qiita.com/tetsu_koba/items/8b4921f257a46a15d2a7)はこれらの項目があります。ロジクールだと、Brio, c922にはあります。廉価のwebcamのc270 にはありません。

## webcamの設定値を変更する

`-c` オプションを使います。

```
$ v4l2-ctl -d /dev/video0 -c zoom_absolute=120
```

この変更はカメラから映像をキャプチャーしている最中でも可能で、すぐに反映されます。


## webcam のPan, Tilt, Zoomを変更するサンプル

[Momo](https://github.com/shiguredo/momo)や他の配信ソフトで配信している最中に、このスクリプトを実行してみてください。 疑似PTZ camera になります。

なお、そのカメラの最大解像度で使用しているとPTZは使用できません。4Kのカメラなら720pで、1080pのカメラならば960x540くらいで使うと効果的です。

```shell
#!/bin/sh
DEVICE=/dev/video0
if false; then
　 # For Logicool C922
  ZOOM_MIN=100
  ZOOM_MAX=180
  ZOOM_STEP=4
  PAN_MAX=36000
  PAN_STEP=3600
  TILT_MAX=36000
  TILT_STEP=3600
else
  # For IMX317 webcam
  ZOOM_MIN=0
  ZOOM_MAX=40
  ZOOM_STEP=2
  PAN_MAX=648000
  PAN_STEP=32400
  TILT_MAX=648000
  TILT_STEP=32400
fi

v4l2-ctl -d $DEVICE -c zoom_absolute=$ZOOM_MIN
v4l2-ctl -d $DEVICE -c pan_absolute=0
v4l2-ctl -d $DEVICE -c tilt_absolute=0

for i in `seq $ZOOM_MIN $ZOOM_STEP $ZOOM_MAX`; do
    v4l2-ctl -d $DEVICE -c zoom_absolute=$i
    sleep 0.1
done
sleep 2
for i in `seq 0 $PAN_STEP $PAN_MAX`; do
    v4l2-ctl -d $DEVICE -c pan_absolute=$i
    sleep 0.1
done
sleep 5
while true; do
    for i in `seq $PAN_MAX -$PAN_STEP 0`; do
        v4l2-ctl -d $DEVICE -c pan_absolute=$i
        sleep 0.1
    done
    sleep 2
    for i in `seq $ZOOM_MAX -$ZOOM_STEP $ZOOM_MIN`; do
        v4l2-ctl -d $DEVICE -c zoom_absolute=$i
        sleep 0.1
    done
    sleep 2
    for i in `seq $ZOOM_MIN $ZOOM_STEP $ZOOM_MAX`; do
        v4l2-ctl -d $DEVICE -c zoom_absolute=$i
        sleep 0.1
    done
    sleep 2
    for i in `seq 0 $TILT_STEP $TILT_MAX`; do
        v4l2-ctl -d $DEVICE -c tilt_absolute=$i
        sleep 0.1
    done
    sleep 2
    for i in `seq $TILT_MAX -$TILT_STEP 0`; do
        v4l2-ctl -d $DEVICE -c tilt_absolute=$i
        sleep 0.1
    done
    sleep 2
    for i in `seq 0 -$PAN_STEP -$PAN_MAX`; do
        v4l2-ctl -d $DEVICE -c pan_absolute=$i
        sleep 0.1
    done
    sleep 5
    for i in `seq -$PAN_MAX $PAN_STEP $PAN_MAX`; do
        v4l2-ctl -d $DEVICE -c pan_absolute=$i
        sleep 0.1
    done
    sleep 5
done
```