複数カメラのカメラポート番号の確認


###はじめに
複数のカメラをつないでいるとき、カメラがどのポート番号になっているかを知りたいことがあります。
そこで、カメラが映している画像を確認しながらポート番号を確認するプログラムを参考までに記載します。

###環境
windows 10
Anacond
opencv 4.0　(conda-forgeからインストール)

###参考
(1)[[OpenCV] 複数のWebカメラを使用する場合、USBポートの番号からデバイスを識別するクラスを作ってみました](https://dev.classmethod.jp/articles/opencv-device-id-by-port-number/)
Linux(raspi)でのコード
(2)[Pythonでカメラを制御する【研究用】](https://qiita.com/opto-line/items/7ade854c26a50a485159)
ここに記載されているコードをベースに作成しています。
(3)[複数のUSBカメラの論理番号の固定化について](https://teratail.com/questions/81542)
デバイスを作らないといけないので断念。

###コード

```python
import cv2
import time

#　参考にしたコード
def check_camera_connection():
    """
    Check the connection between the camera numbers and the computer. 

    """
    true_camera_is = []  

    # check the camera number from 0 to 9
    for camera_number in range(0, 10):
        cap = cv2.VideoCapture(camera_number)
        ret, frame = cap.read()

        if ret is True:
            true_camera_is.append(camera_number)
            print("port number", camera_number, "Find!")

        else:
            print("port number", camera_number,"None")
    print("Connected camera", len(true_camera_is))


# 画像を表示させて実際に確かめるコード
def check_camera_connection_display(save_flag=False):
    """
    Display the image and check the camera number 

    """
    true_camera_is = [] 

    for camera_number in range(0, 5):
        #  for windows -> cv2.CAP_DSHOW
        cap = cv2.VideoCapture(camera_number,cv2.CAP_DSHOW)
        # other
        # cap = cv2.VideoCapture(camera_number)

        ret, frame = cap.read()

        if ret is True:
            start = time.time()
            
            while True:
                elasped_time = time.time() - start
                ret2, frame = cap.read()
                gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

                if elasped_time > 3.0:
                    if save_flag :
                        # save data file
                        save_data_name = f'N_{camera_number}.png'
                        cv2.imwrite(save_data_name, gray)

                    break
                    
                cv2.imshow(f'Camera Number: {camera_number}',gray)

                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break


            cap.release()
            cv2.destroyAllWindows()

            true_camera_is.append(camera_number)
            print("port number", camera_number, "Find!")

        else:
            print("port number", camera_number,"None")
            
    print(f"Number of connected camera: {len(true_camera_is)}")

if __name__ == '__main__':
    # check_camera_connection()
    check_camera_connection_display(save_flag=False)
```

###コード説明

カメラが撮影している画像を３秒間表示して、カメラがどのポート番号に対応しているか確認します。画像表示のフレームのタイトルにカメラポート番号が表示されます。
引数の`save_flag = True` にすると画像が保存されます（その際ポート番号がファイル名になります。）
USBカメラは、つなぐたびにポート番号がずれることがあり、毎回確認しなければなりません。例えばカメラが固定されているならば、撮影する画像にQRコードやARコードを置いておいて、その認識IDとカメラポート番号を紐づける方法もよいかもしれません。

### その他
装置制御を行うときには、カメラの他にSerial通信も使うこととが多いので、Serial portの接続を知らべる方法についても記載します。
pyserialのインストールが必要です。

参考：[Pythonでシリアル通信する方法：計測器等から数値を取得](https://from-age35.com/1144.html)


```python
import serial.tools.list_ports

def serial_find():
    ports =[]
    ports = list(serial.tools.list_ports.comports())
    print('----')
    for p in ports:
        print(p)
        print(p.device)
        print(p.name)
    print(f"Number of connected serial: {len(ports)}")    
    
    # for p in ports:
    #     print(p)
    #     print(p.device)
    #     print(p.name)
    #     print(p.description)
    #     print(p.hwid)
    #     print(p.vid)
    #     print(p.pid)
    #     print(p.serial_number)
    #     print(p.location)
    #     print(p.manufacturer)
    #     print(p.product)
    #     print(p.interface)

if __name__ == '__main__':
    serial_find()

```