IBM Watson의 Visual Recognition을 Python으로 두드려 Raspberry Pi로 이미지 인식 카메라 제작

소개



화상 인식 API도 여러 가지 있습니다만, IBM Watson의 화상 인식 API인 Visual Recognition은, 50장 정도 학습시키면 일단 어느 정도의 판별을 할 수 있어 간편했으므로, 라즈파이로 카메라를 만들어 화상 인식시켜 보자 라고 생각합니다.
처음에는 Node-RED를 사용해 Web상에서 움직이려고 했습니다만, 추가하고 싶은 기능의 편의상, Python을 사용하고 싶었으므로, 이 형태가 되었습니다.

watson-deveroper-cloud 넣기


  • IBM Cloud에서 Visal Rcognition 서비스를 작성하여 API 키를 가져옵니다.
  • 사용자 정의 모델을 만들고 ID를 삼가
  • pip installl에서 watson-developer-cloud를 설치합니다.
  • $ pip install watson-developer-cloud
    

    참고문헌



    Python에서 IBM Cloud의 Watson API Visual Recognition 사용하기 - Qiita
    python-sdk/visual_recognition_v3.py at master · watson-developer-cloud/python-sdk · GitHub

    웹캠 연결/인식



    usb 카메라를 라즈파이에 연결한 상태에서 드라이버 로드
    $ sudo apt update
    $ sudo apt upgrade
    $ sudo nano /etc/modules
    

    nano 편집기가 열리면 아무 곳에나 다음 행을 삽입
    bcm2835-v4l2
    

    raspi-config로 Camera를 Enable로 재부팅. 이하의 커멘드를 실행했을 때에, 이런 느낌의 출력이 나오면, 올바르게 드라이버를 인식할 수 있습니다.
    $ ls /dev/video*
    /dev/video0
    
    $ lsusb
    Bus 001 Device 004: ID 0411:0260 BUFFALLO.INC
    - - -
    

    이어서 이미지 촬영을 위한 소프트웨어를 도입하여 시험해 봅시다.
    $ sudo apt install fswebcam
    $ fswebcam test.jpg
    

    회로 작성



    스위치가 셔터 대신되어 있고, 누르면 부저가 울리고 LED가 빛납니다. 메모 쓰기는 걱정하지 마십시오.



    프로그램



    셔터를 누르면 사진을 찍어 이미지 인식 결과를 반환합니다.

    vrtest.py
    import RPi.GPIO as GPIO
    from time import sleep, time
    import json
    from watson_developer_cloud import VisualRecognitionV3
    from datetime import datetime
    import subprocess
    
    
    # GPIOポートの設定 --- (*1)
    LED_PORT = 4
    PE_PORT = 18
    SWITCH_PORT = 23
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LED_PORT, GPIO.OUT)
    GPIO.setup(PE_PORT, GPIO.OUT)
    GPIO.setup(SWITCH_PORT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    
    # APIの設定
    visual_recognition = VisualRecognitionV3(
        #The release date of the version of the API you want to use.
        '2018-03-19',
        iam_apikey='apikey')
    
    
    # 写真の撮影コマンドを実行
    def take_photo():
        now = datetime.now()
        fname = now.strftime('%Y-%m-%d_%H-%M-%S') + ".jpg"
        cmd = "fswebcam -r 1260x720 " + fname
        #撮影コマンドを要求
        subprocess.check_output("fswebcam", shell=True)
        subprocess.check_output(cmd, shell=True)
        print("captured")
        # 画像認識
        with open(fname, 'rb') as images_file:
            classes = visual_recognition.classify(
            images_file,
            threshold='0.6',
            classifier_ids=["yourID"]).get_result()
            #unicodeで返ってくるので、utf-8に変換する。
            result = json.dumps(classes, indent=2).encode('utf-8').decode('unicode_escape')
            #jsonを辞書型にする
            result = json.loads(result)
            #認識結果のclass(=認識・特定した物体の名前)だけを抽出する。
            print(result['images'][0]['classifiers'][0]['classes'][0]['class'])
    
    # ブザーを鳴らす --- (*4)
    def beep():
        pwm = GPIO.PWM(PE_PORT, 330)
        pwm.start(50)
        sleep(0.1)
        pwm.ChangeFrequency(440)
        sleep(0.1)
        pwm.stop()
    
    
    try:
        sw = 0
        while True:
            if GPIO.input(SWITCH_PORT) == GPIO.HIGH:
                sw = 1
                GPIO.output(LED_PORT, GPIO.HIGH)
                beep()
                # 写真撮影
                take_photo()        
                if sw != 0: continue # 連続押し防止
                sw = 0
            else:
                sw = 0
                GPIO.output(LED_PORT, GPIO.LOW)
            sleep(0.1)
    
    except KeyboardInterrupt:
        pass
    
    GPIO.cleanup()
    

    출력 결과



    이번에는, 동물원에 있을 것 같은 동물을 바탕으로 커스텀 모델을 작성해 보았습니다. 사진을 찍으면 어떤 동물인지를 판정합니다. 이 외에는 야채의 학습 모델에서도 마찬가지로 동작을 확인할 수 있었습니다.
    $ python3 vrtest.py
    --- Opening /dev/video0...
    Trying source module v4l2...
    /dev/video0 opened.
    No input was specified, using the first.
    Adjusting resolution from 384x288 to 352x288.
    --- Capturing frame...
    Captured frame in 0.00 seconds.
    --- Processing captured image...
    There are unsaved changes to the image.
    --- Opening /dev/video0...
    Trying source module v4l2...
    /dev/video0 opened.
    No input was specified, using the first.
    Adjusting resolution from 1260x720 to 1280x720.
    --- Capturing frame...
    Captured frame in 0.00 seconds.
    --- Processing captured image...
    Writing JPEG image to ‘2018-12-13_15-56-22.jpg’.
    captured
    コアラ
    

    또한 출력 결과가 길기 때문에 이러한 방식으로 외부 파일에 결과를 내보낼 수 있습니다.
    with open(image_path, 'rb') as images_file:
        classes = visual_recognition.classify(
        images_file,
        threshold='0.6',
        classifier_ids=['yourCustomModelID']).get_result()
        #出力結果が長いため、外部ファイルに結果を書き出しています
        f=open('result.json', 'w')
        f.write(json.dumps(classes, indent=2))
        f.close()
        print(json.dumps(classes, indent=2).encode('utf-8').decode('unicode_escape'))
    

    브로콜리로 시도해보기




    이 사진의 인식 결과를 외부 파일에서 긁어 낸 곳은 다음과 같습니다.

    result.json
    {
     "custom_classes": 5,
     "images": [
       {
         "classifiers": [
           {
             "name": "Default Custom Model",
             "classifier_id": "DefaultCustomModel_49867514",
             "classes": [
               {
                 "class": "ブロッコリー",
                 "score": 0.718
               }
             ]
           }
         ],
         "image": "2018-12-12_17-36-53.jpg"
       }
     ],
     "images_processed": 1
    }
    

    파일로 확인

    요약



    비교적 적은 매수로 커스텀 모델을 작성할 수 있었던 적도 있어, 단시간에 여기까지 만들 수 있었습니다. 또, 출력을 궁리해 그것 같은 시스템으로 완성해 가면 좋겠다고 생각했습니다.

    좋은 웹페이지 즐겨찾기