자기 상품 (작품) 소개 시스템 (그 1 | 라즈파이와 카메라로 프로토 타입)

자기 상품(작품) 소개 시스템을 하드웨어로서 실장해, 혼자라도 전시품이나 상품의 정보를 손에 넣자



배경 (처음에는 성실했다.)



상품 설명의 최종 목적은 「상품이 팔리는 것」이다. 따라서, 상품을 팔기 위해 필요한 적절한 상품 설명을, 사람의 손을 개입시키지 않고 실시하기 위해, 상품 스스로를 세일 스토크하는 시스템을 구축하는 것을 목적으로 한다.

어깨의 힘을 빼고



이 시스템은 박물관의 전시품이나 동물원의 동물들의 설명에도 응용할 수 있습니다.


  • 혼자서 그런 장소에는 가기 어렵다
  • 알고 싶거나 물어보고 싶은 일이 있어도, 스탭에게는 말하기 어렵다

  • 그런 때에도 유용하다고 생각합니다.
    또, 설명문을 의인화시키거나, 반대로 설명문으로부터, 동물등의 이름을 맞추는 퀴즈로 하거나 해도 좋을지도 모릅니다.

    구성도



    손으로 그려서 알기 어려울지도 모르지만, 이런 구성도입니다.
    데이터베이스는 mySQL을 phpmyadmin으로, 현장의 스탭이 브라우저상에서 관리·편집할 수 있도록 하고 있습니다.
    결국 웹 앱으로 만들고 싶습니다.


    지금까지 기사의 내용을 결합


  • IBM Watson의 Visual Recognition에서 이미지 인식을 위한 사용자 정의 모델 작성
  • IBM Watson의 Visual Recognition을 Python으로 두드려 Raspberry Pi로 이미지 인식 카메라 제작
  • Raspberry Pi를 SQL 서버로 만들고 Python3에서 MySQL 데이터를 검색하고 표시 할 때까지
  • 파이썬에서 docomo 음성 합성 API 활용

  • 이들을 바탕으로

    셔터를 눌러 사진을 찍습니다.

    → 이미지 분석 API에 던지기

    →JSON이 돌아온다

    →JSON에서 인식 결과만 추출

    → 인식 결과에 해당하는 정보를 데이터베이스에서 검색

    →설명문 취득

    → 설명문을 음성 합성(docomoAPI)하여 음성 파일에 저장

    → 파일이 기존이면 거기에서 재생. 없으면 다시 음성 합성

    하도록 프로그램을 작성합니다.
    import RPi.GPIO as GPIO
    from time import sleep, time
    import json
    from watson_developer_cloud import VisualRecognitionV3
    from datetime import datetime
    import subprocess
    import pymysql.cursors
    import os
    import requests
    
    # GPIOポートの設定 --- (*1)
    LED_PORT = 4
    PE_PORT = 18
    SWITCH_PORT = 23
    
    #GPIO.cleanup()
    
    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')
    
    # データベースに接続
    connection = pymysql.connect(host='hoge',
         user='hoge',
         password='hoge',
         db='hoge',
         charset='utf8',
         # Selectの結果をdictionary形式で受け取る
         cursorclass=pymysql.cursors.DictCursor)
    
    # 写真の撮影コマンドを実行
    def take_photo():
        now = datetime.now()
        fname = now.strftime('%Y-%m-%d_%H-%M-%S') + ".jpg"
        cmd = "fswebcam -r 1920x1080 " + 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=["yourmodelID"]).get_result()
            #unicodeで返ってくるので、utf-8に変換する。
            result = json.dumps(classes, indent=2).encode('utf-8').decode('unicode_escape')
            #jsonを辞書型&リスト型にする
            result = json.loads(result)
            #認識結果のclass=認識・特定した物体の名前だけを抽出する。
            result = result['images'][0]['classifiers'][0]['classes'][0]['class']
        return result
    
    # データベースを検索
    def selectsql(name):
        with connection.cursor() as cursor:
            sql = "SELECT * FROM vegetable WHERE class=%s"
            cursor.execute(sql,name)
            #必要なカラムの内容だけ抽出 
            dbdata = cursor.fetchall()
            desc = dbdata[0]['description']
            return desc
    
    #引数で指定した文字列を再生する
    def talk(title, message, path="./"):
    
        if not os.path.isfile(path+title+".wav"): # 既に音声ファイルがあるかどうかを確認する
            url = 'https://api.apigw.smt.docomo.ne.jp/crayon/v1/textToSpeech?APIKEY='+'apikey2'
    
            params = {
                  "Command":"AP_Synth",
                  "SpeakerID":"1",
                  "StyleID":"1",
                  "SpeechRate":"1.15",
                  "AudioFileFormat":"2",
                  "TextData":message
                }
    
            r = requests.post(url, data=json.dumps(params))
            if r.status_code == requests.codes.ok:
                wav = r.content
                with open(path+title+".wav","wb") as fout:
                    fout.write(wav)
    
        if os.path.isfile(path+title+".wav"): # APIでエラーが発生し、音声ファイルが生成されないときのため
            char = "aplay {}{}.wav".format(path, title)
            os.system(char)
    
    # ブザーを鳴らす
    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()
    
                # 写真撮影
                result = take_photo()
                print(result)
                if result == '': continue
    
                #データベースにアクセス
                desc = selectsql(result)
                print(desc)
    
                # 喋らせよう
                talk(result, desc)
    
                if sw != 0: continue # 連続押し防止
                sw = 0
            else:
                sw = 0
                GPIO.output(LED_PORT, GPIO.LOW)
            sleep(0.1)
    
    except KeyboardInterrupt:
        pass
    
    GPIO.cleanup()
    
    

    os도 subprocess도 import하고 있는 점이나, 카메라의 기동 후의 오토 포커스의 시간을 벌기 위해(때문에), 1장째의 fswebcam의 결과를 파기해, 2매째를 해석하는 등, 중복으로 잘 되지 않는 곳 도 있습니다만, 일단 움직이고 있기 때문에 좋다고 합니다.

    실행 결과



    옆으로 스크롤해보세요. 설명문을 읽고 있습니다.
    $ python3 selfintro.py
    captured
    grape
    軸が茶色いものは収穫してから日が経っています。また果皮に白っぽい粉が付着していますが、これは水分の蒸発を防ぐためのブルームというものです。この粉がまんべんなく付いているブドウは鮮度がよい証拠です。また、鮮度を保つ役割も持つため、食べる直前まで洗い流さないこと。なお、ブルームは食べても大丈夫ですよ。
    再生中 WAVE ‘./grape.wav’ : Signed 16 bit Little Endian, レート 22050 Hz, モノラル
    

    좋은 웹페이지 즐겨찾기