工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

SmartThingsのモーションセンサーとしてのコンピュータービジョン

Raspberry Pi 3とPiCamを使用して、このコンピュータービジョン搭載センサーは顔を検出し、LAN経由でプレゼンスデータを送信します–UPNPをSmartThingsに送信します。

まず、カメラが機能し、OpenCVがインストールされたRaspberryPi3があると仮定します。そうでない場合は、このチュートリアルをお勧めします🙂

カスタムSmartThingsデバイスハンドラーの作成

SmartThings IDEで、コンピュータービジョンモーションセンサー用の新しいデバイスハンドラーを作成します。

[マイデバイスハンドラー]セクションに移動し、右上隅にある[+新しいデバイスハンドラーを作成]をクリックします。

この場合、コードから作成します。 2番目のタブ[コードから]をクリックして、添付のコードを貼り付けます「デバイスハンドラー」 「作成」をクリックします。

次のページで[公開]をクリックして、デバイスを利用できるようにします。

SmartThingsアプリの作成

デバイスハンドラーと同様に、[マイSmartApps]セクションに移動し、右上隅にある[+新しいSmartAppsを作成]をクリックします。

また、コードから作成します。 2番目のタブ[コードから]をクリックし、添付のコード「 SmartApp」を貼り付けます 「作成」をクリックします。

次のページで[公開]をクリックします。

RaspberryPiを準備する

次に、カメラから画像を取得し、顔を検出してSmartThingsに報告するPythonスクリプトを追加する必要があります。

最初の d imutilsとtwistedを所有してインストールする

imutilsパッケージをまだインストールしていない場合は、GitHubから取得するか、次の方法でインストールすることをお勧めします:

  pip install imutils  

ツイストの場合:

  sudo apt-get install python-twisted-web  

すべての準備ができたので、 / home / pi に移動します スクリプトを保存するディレクトリを作成します

  mkdir cameracd camera  

スクリプトファイルを作成します:

  sudo nano ssdpcamera.py  

添付のコードを貼り付けます カメラPythonスクリプト」 「control + x」、「y」の順に押して保存します。

python ssdpcamera.pyと入力してスクリプトをテストすると、次のように表示されます。

ラズベリーパイの検出とペアリング

SmartThingsモバイルアプリから、右下のマーケットプレイスに移動し、[SmartApps]タブをクリックして、最後に[+ My Apps]で[ComputerVision(Connect)]を探します。

Raspberry Piがオンになっていて、Pythonスクリプトが実行されていることを確認してください。

SmartAppは検出プロセスを開始し、検出されたら、選択ダイアログをクリックしてデバイスを選択し、[完了]をクリックします。

これにより、アカウントにデバイスが作成され、更新の受信が開始されます。

自動開始

最後に、Raspberry PiをオンにしたときにPythonスクリプトを自動的に実行する場合は、/ etc / rc.localを編集して、次の行を追加できます。

 (sleep 10; python /home/pi/camera/ssdpcamera.py)& 

()は、両方のコマンドをバックグラウンドで実行します。

コード

#!/ usr / bin / python2.7 "" "Computer Vision Camera for SmartThingsCopyright 2016 Juan Pablo Risso <[email protected]>依存関係:python-twisted、cv2、pyimagesearchLicensed under Apacheライセンス、バージョン2.0(「ライセンス」)。ライセンスに準拠している場合を除き、このファイルを使用することはできません。ライセンスのコピーは、http://www.apache.org/licenses/LICENSE-2.0で入手できます。適用法で要求されるか、書面で合意された場合、ライセンスに基づいて配布されるソフトウェアは、明示または黙示を問わず、いかなる種類の保証または条件もなしに、「現状有姿」で配布されます。ライセンスに基づく許可および制限を規定する特定の言語については、ライセンスを参照してください。 "" "import argparseimport loggingimport cv2import urllib2import imutilsfrom time import timefrom picamera.ar​​ray import PiRGBArrayfrom picamera import PiCamerafromtwisted.webインポートサーバー、resourcefromtwisted.internetインポートreactorfromtwisted.internet.deferインポートsucceedfromtwisted.inter net.protocol import DatagramProtocolfromtwisted.web.client import Agentfromtwisted.web.http_headersimportHeadersfromtwisted.web.iweb import IBodyProducerfromtwisted.web._newclient import ResponseFailedfrom zope.interface importimplementsSSDP_PORT =1900SSDP_ADDR ='239.255.255.250' UUID ='d1c -9220-11e4-96fa-123b93f75cba'SEARCH_RESPONSE ='HTTP / 1.1 200 OK \ r \ nCACHE-CONTROL:max-age =30 \ r \ nEXT:\ r \ nLOCATION:%s \ r \ nSERVER:Linux、UPnP / 1.0、Pi_Garage / 1.0 \ r \ nST:%s \ r \ nUSN:uuid:%s ::%s '#カメラを初期化し、生のカメラへの参照を取得します#capturecamera =PiCamera()camera.resolution =(640 、480)camera.framerate =32rawCapture =PiRGBArray(camera、size =(640、480))auxcount =0#顔検出器を構築し、カメラをウォームアップできるようにしますfd =FaceDetector( "cascades / haarcascade_frontalface_default.xml")time.sleep (0.1)defdetermine_ip_for_host(host): "" "特定のホストとの通信に使用されるローカルIPアドレスを決定します" "" test_sock =DatagramProtocol()test_sock_listener =react.lis tenUDP(0、test_sock)#pylint:disable =no-membertest_sock.transport.connect(host、1900)my_ip =test_sock.transport.getHost()。hosttest_sock_listener.stopListening()return my_ipclass StringProducer(object): "" "書き込みツイストリクエストへのメモリ内文字列 "" "implements(IBodyProducer)def __init __(self、body):self.body =bodyself.length =len(body)def startProducing(self、consumer):#pylint:disable =invalid- name "" "指定されたコンシューマーに提供された文字列の生成を開始します" "" consumer.write(self.body)return success(None)def pauseProducing(self):#pylint:disable =invalid-name "" "一時停止生成-noop "" "passdef stopProducing(self):#pylint:disable =invalid-name" "" Stopproduce-no op "" "passclass SSDPServer(DatagramProtocol):" "" SmartThingsハブからのM-SEARCH検出要求の受信と応答 " "" def __init __(self、interface =''、status_port =0、device_target =''):self.interface =interfaceself.device_target =device_targetself.status_port =status_portself.port =react.listenMulticas t(SSDP_PORT、self、listenMultiple =True)#pylint:disable =no-memberself.port.joinGroup(SSDP_ADDR、interface =interface)reactor.addSystemEventTrigger( 'before'、 'shutdown'、self.stop)#pylint:disable =no-memberdef datagramReceived(self、data、(host、port)):try:header、_ =data.split(b '\ r \ n \ r \ n')[:2] ValueError:returnlines =header.splitを除く( '\ r \ n')cmd =lines.pop(0).split( '')lines =[x.replace( ':'、 ':'、1)for x in lines] lines =[x for x in lines if len(x)> 0] headers =[x.split( ':'、1)for x in lines] headers =dict([(x [0] .lower()、x [1])for x in headers])logging.debug( 'SSDP command%s%s --from%s:%d with headers%s'、cmd [0]、cmd [1]、host、port、headers)search_target ='' if ' st'in headers:search_target =headers ['st'] if cmd [0] =='M-SEARCH'and cmd [1] ==' * 'and search_target in self.device_target:logging.info(' Received%s %sから%sの%s:%d '、cmd [0]、cmd [1]、search_target、host、port)url =' http://%s:%d / status '%(determine_ip_for_host(host) 、self.status_port)response =SEARCH_R ESPONSE%(url、search_target、UUID、self.device_target)self.port.write(response、(host、port))else:logging.debug( '無視されたSSDPコマンド%s%s'、cmd [0]、cmd [ 1])def stop(self): "" "マルチキャストグループを終了してリスニングを停止" "" self.port.leaveGroup(SSDP_ADDR、interface =self.interface)self.port.stopListening()class StatusServer(resource.Resource): "" "SmartThingsハブにカメラのステータスを提供するHTTPサーバー" "" isLeaf =Truedef __init __(self、device_target、subscription_list、garage_door_status):self.device_target =device_targetself.subscription_list =Subscription_listself.garage_door_status =garage_door_statusresource.Resource .__ init_ self)def render_SUBSCRIBE(self、request):#pylint:disable =invalid-name "" "STハブからのサブスクライブリクエストを処理します-ハブはガレージドアのステータスの更新を通知されます" "" headers =request.getAllHeaders()logging.debug ( "SUBSCRIBE:%s"、headers)if'callback 'in headers:cb_url =headers [' callback '] [1:-1] if not cb_url in self.subscription_list:self.subs cription_list [cb_url] ={}#reactor.stop()logging.info( '追加されたサブスクリプション%s'、cb_url)self.subscription_list [cb_url] ['expiration'] =time()+ 24 * 3600return "" def render_GET( self、request):#pylint:disable =invalid-name "" "STハブからのポーリングリクエストを処理する" "" if request.path =='/ status':if self.garage_door_status ['last_state'] =='inactive' :cmd ='status-inactive' else:cmd ='status-active' msg =' %s   uuid:%s ::%s   '%(cmd、UUID、self.device_target)logging.info( "%sから%sへのリクエストのポーリング-%sが返されました"、request.getClientIP()、request.path、cmd)return msgelse:logging.info( "%sから%sの偽のリクエストを受信しました"、request.getClientIP()、request.path)return "" class MonitorCamera(object): "" "カメラのステータスを監視し、状態が変化するたびに通知を生成します" "" def __init __( self、device_target、subscription_list、camera_status):#pylint:disable =too-many-argumentsself.device_target =device_targetself.subscription_list =Subscription_listself.camera_stat us =camera_statuscurrent_state ='inactive' reactor.callLater(0、self.check_garage_state、current_state、auxcount)#pylint:disable =no-memberdef check_garage_state(self、current_state、auxcount):self.current_state =current_stateself.auxcount =auxcountcamera.capture( rawCapture、format ="bgr"、use_video_port =True)#imageframe =rawCapture.array#を表す生のNumPy配列を取得し、フレームのサイズを変更して、grayscaleframe =imutils.resize(frame、width =640)gray =cv2.cvtColorに変換します。 (frame、cv2.COLOR_BGR2GRAY)#画像内の顔を検出し、フレーム#を複製して、その上に描画できるようにしますfaceRects =fd.detect(gray、scaleFactor =1.1、minNeighbors =10、minSize =(30、30))frameClone =frame.copy()if faceRects!=():auxcount =0 if current_state =='inactive':current_state ='active' logging.info( '状態が%sから%sに変更されました'、self.camera_status ['last_state ']、current_state)self.camera_status [' last_state '] =current_stateself.notify_hubs()else:auxcount =auxcount + 1if auxcount ==60:current_state ='非アクティブ' logging.info( '状態が%sから%sに変更されました'、self.camera_status ['last_state']、current_state)self.camera_status ['last_state'] =current_stateself.notify_hubs()#ループオーバー面の境界ボックスとそれらをfaceRects:cv2.rectangle(frameClone、(fX、fY)、(fX + fW、fY + fH)、(0、255、0)、2 )#新しいGUIウィンドウにビデオフィードを表示します#cv2.imshow( "Face"、videorotate)rawCapture.truncate(0)#次のcheckreactor.callLater(0、self.check_garage_state、current_state、auxcount)をスケジュールします#pylint:disable =no-memberdef notify_hubs(self): "" "サブスクライブされたSmartThingsハブに状態変更が発生したことを通知します" "" ifself.camera_status ['last_state'] =='inactive':cmd ='status-inactive' else:cmd ='status-active'のサブスクリプションforself.subscription_list:if self.subscription_list [subscription] ['expiration']> time():logging.info( "Notifyinghub%s"、subscription)msg =' %s   uuid:%s ::%s   '%(cmd、UUID、self.device_target)b ody =StringProducer(msg)agent =Agent(reactor)req =agent.request( 'POST'、subscription、Headers({'CONTENT-LENGTH':[len(msg)]})、body)req.addCallback(self。 handle_response)req.addErrback(self.handle_error)def handle_response(self、response):#pylint:disable =no-self-use "" "SmartThingsハブを処理してステータスコードをPOSTに返します。これは実際には予期しないことです。通常は予期しないことです。応答コードを指定せずにPOST / PUTの接続を閉じます。 "" "ifresponse.code ==202:logging.info(" Status update Accepted ")else:logging.error(" Unexpected response code:%s "、response。 code)def handle_error(self、response):#pylint:disable =no-self-use "" "NOTIFYの実行中に生成されるエラーを処理します。 ResponseFailedを回避する方法はないようです-SmartThingsHubはPOSTまたはPUTの適切な応答コードを生成せず、NOTIFYが使用されている場合、本文を無視します。 "" "if isinstance(response.value、ResponseFailed): logging.debug( "Response failed(expected)")else:logging.error( "Unexpected response:%s"、response)def main(): "" "コマンドラインからの使用を処理するメイン関数" "" arg_proc =argparse .ArgumentParser(description ='SmartThingsハブにカメラのアクティブ/非アクティブステータスを提供します')arg_proc.add_argument( '-httpport'、dest ='http_port'、help ='HTTPポート番号'、default =8080、type =int) arg_proc.add_argument( '-deviceindex'、dest ='device_index'、help ='Device index'、default =1、type =int)arg_proc.add_argument( '-pollingfreq'、dest ='polling_freq'、help ='カメラ状態のポーリング間の秒数 '、default =5、type =int)arg_proc.add_argument('-debug '、dest =' debug '、help ='デバッグメッセージを有効にする '、default =False、action =' store_true ' )options =arg_proc.parse_args()device_target ='urn:schema s-upnp-org:device:RPi_Computer_Vision:%d '%(options.device_index)log_level =logging.INFOif options.debug:log_level =logging.DEBUGlogging.basicConfig(format ='%(asctime)-15s%(levelname)- 8s%(message)s '、level =log_level)subscription_list ={} camera_status ={' last_state ':' unknown '} logging.info(' Initializing camera ')#SSDPサーバーがdiscoverySSDPServer(status_port =options.http_port、device_target =device_target)#サブスクリプションを処理するHTTPサイト/ pollingstatus_site =server.Site(StatusServer(device_target、subscription_list、camera_status))reactor.listenTCP(options.http_port、status_site)#pylint:disable =no-memberlogging.info( 'Initialization complete' )#カメラの状態を監視し、状態の変化に関する通知を送信しますSmartThingsのモーションセンサーとしてのビジョン

製造プロセス

  1. ST:高精度でバッテリーに優しいアクティビティ追跡のための機械学習を備えたモーションセンサー
  2. Raspberry PiのHAでのモーションセンサー、アラーム、ビデオ録画
  3. ラズベリーパイ用DIY赤外線モーションセンサーシステム
  4. RaspberryPiを使用したモーションセンサー
  5. ガイガーカウンター– RaspberryPiチュートリアル用の放射線センサーボード
  6. PIRモーションセンサーを備えたRaspberryPi GPIO:最高のチュートリアル
  7. 18世紀の製粉所向けのセンサーネットワークの構築
  8. HC-SR501PIRモーションセンサーとRaspberryPiのインターフェース
  9. Raspberry Piロボットの構築:初心者向けの最高のチュートリアル
  10. コンピュータビジョンの7つのアプリケーション
  11. コンピュータビジョン