PythonでBASLERカメラのエミュレーターを設定する
Source of photo: https://github.com/basler/pypylon As of Sep 22, 2021
概要
システム環境変数に"PYLON_CAMEMU=1"と設定してあげると、カメラエミュレーションが有効になり、実際にカメラがPCに接続されていなくてもpypylon
で作ったスクリプトを動かくすことができる。
Camera Emulation | Basler Product Documentation
しかし、システム環境変数をその都度書き換えるのは面倒だし、誤って他の変数を書き換えてしまう恐れもある。もっと手軽にカメラエミュレーションを有効にする方法がある。
その方法は、次の1行をスクリプトに入れるだけ。
os.environ["PYLON_CAMEMU"] = "1"
サンプルプログラム
結果
エミュレーションが有効になっていると、おなじみの縞々が表示される。
ソースコード
1行目と8行目以外は、GitHubから引用している。
Source of script: https://github.com/basler/pypylon/blob/master/samples/guiimagewindow.py As of Sep 22, 2021
import os import time from pypylon import pylon from pypylon import genicam os.environ["PYLON_CAMEMU"] = "1" try: imageWindow = pylon.PylonImageWindow() imageWindow.Create(1) # Create an instant camera object with the camera device found first. camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice()) # Print the model name of the camera. print("Using device ", camera.GetDeviceInfo().GetModelName()) # Start the grabbing of c_countOfImagesToGrab images. # The camera device is parameterized with a default configuration which # sets up free-running continuous acquisition. camera.StartGrabbingMax(10000, pylon.GrabStrategy_LatestImageOnly) while camera.IsGrabbing(): # Wait for an image and then retrieve it. A timeout of 5000 ms is used. grabResult = camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException) # Image grabbed successfully? if grabResult.GrabSucceeded(): imageWindow.SetImage(grabResult) imageWindow.Show() else: print("Error: ", grabResult.ErrorCode) # grabResult.ErrorDescription does not work properly in python could throw UnicodeDecodeError grabResult.Release() time.sleep(0.05) if not imageWindow.IsVisible(): camera.StopGrabbing() # camera has to be closed manually camera.Close() # imageWindow has to be closed manually imageWindow.Close() except genicam.GenericException as e: # Error handling. print("An exception occurred.") print(e.GetDescription())
PythonでUSBカメラのスナップショットを大量に取得する!
USBカメラから自動で大量に画像を取得するプログラムを作った。
用途
機械学習用に大量に画像データを取得するときなど。
プログラムの概要
- 実行すると、フォルダダイアログが立ち上がるので保存先を指定する。保存先に自動的に新規フォルダが作成される。名前にその時の時刻が含まれる。
- そのまま指定した枚数の撮像&保存が始まる。
- 枚数の指定は以下の"10"の部分。上限を1000にしてある。
acquire_save(10, specify_destination())
- While文の中のSleepを調整することで、撮像の間隔を変えられる。
ソースコード
#python 3.8.1 #opencv-contrib-python 4.2.0.32 """ This script acquires and saves a large amount of images from a camera. """ import sys import os from time import sleep from datetime import datetime import tkinter as tk from tkinter import filedialog import cv2 class MyException(Exception): pass def specify_destination(): #Define name of a folder where images will be stored. now = datetime.now() new_folder_name = 'Images_{:%Y%m%d%H%M%S}'.format(now) try: print("Specify a directory to make a new folder to store images.") #Let users specify a directory where a new folder will be made. idir = os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + "\\Desktop" dst = filedialog.askdirectory(initialdir = idir) #If users canceled when specifying the directory, raise MyException. if dst == "": raise MyException("Cancel clicked!") #Then, make the folder for storing images. dst_path = os.path.join(dst, new_folder_name) os.mkdir(dst_path) except MyException as e: print(e) sys.exit() except Exception: print("Unexpected error occurred.") sys.exit() else: print("The folder was successfully created.") return dst_path def acquire_save(num_acquisition, save_path): try: #Make a camera instance. cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) #Check if the camera instance is sure to be opened. if not cap.isOpened(): raise MyException("Camera Not Found!") #Check if num_acquisition is integer. if not isinstance(num_acquisition, int): raise MyException("Num of acquisitoin is wrong.") #Check if num_acquisition is less than 1000. if num_acquisition > 1000: raise MyException("Too much number you requested!") #Check if save_path is sure to exist. if not os.path.isdir(save_path): raise MyException("The directory does not exist.") print("Start to acquire and save images repeatedly.") num = num_acquisition while num > 0: print(num) sleep(0.1) _, frame = cap.read() #Define name of images including sequential number. file_name = "sample_{:04}.jpg".format(num) cv2.imwrite(os.path.join(save_path, file_name), frame) num -= 1 except MyException as e: print(e) sys.exit() except Exception: print("Unexpected error occurred.") sys.exit() else: print("Successfully completed!") finally: cv2.destroyAllWindows() cap.release() if __name__ == '__main__': root = tk.Tk() root.withdraw() acquire_save(10, specify_destination())
参考サイト
Pythonで自動化!複数画像から輝度値を取得してテキストに出力する - Python独習!
python - WARN:0 terminating async callback error in cv2 - Stack Overflow
Tkinterのfiledialogでキャンセルするとエラーになる対策 - Qiita
Pythonでディレクトリ(フォルダ)を作成するmkdir, makedirs | note.nkmk.me
OpenCV - カメラで撮影した画像を連番ファイルで保存したい|teratail
ちょっとした気づき
except句にsys.exit()が含まれていても、ちゃんとfinally句は実行されるようだ。
Pythonでスクリプト実行中に対話モードに入りたい
概要
スクリプトはひとたび実行すると終わるまで手出しできない。手出しというのは、変数の値を見たり、中間結果を使って検算したり。初めて使うモジュールを利用するときはこの「手出し」をしたい場面が多々ある、と思う。
そこで見つけたのが、次の一行をスクリプトの止めたいところに書いておくだけ、というもの。この行が実行されると変数が保持されたままの状態でPython Shellがつかるようになる。
#Python3.8.1 import code code.InteractiveConsole(globals()).interact()
参考サイト
まんま同じ内容だが、Python3.8でも使えますよ、というアップデートの意味を込めて自分の記事に使わせていただいた。
sucrose.hatenablog.com
ラズパイ4でスライドショーを自動起動させる!
Raspberry PiにかまけてPython学習が進んでいませんが、今回もハマったことの忘備録として残しておきます。
やりたいこと
流行りのデジタルサイネージをやってみる。壁掛けモニターにラズパイを指すだけの簡単な構成で実現したい。
実現方法はおおまかに、表示する内容を予めPDF形式で用意しておき、ラズパイに移す。そして、PDFをスライドショーとして流すためにOkular
を使う。あとラズパイが起動したのと同時にスライドショーが流れるように自動起動の設定をする。
以下でそれぞれ詳細に説明していく。
※パーミッション関係はまだよく分かっていないので記載を割愛する。とりあえず『すべて許可』にしておけば動く。
環境
デバイスバージョン : Raspberry Pi 4 Model B Rev
Raspbianのバージョン : 10.7
PDFファイルをラズパイに送る
詳細は↓↓の記事を参考に。
greenhornprofessional.hatenablog.com
スライドショー表示できるようにする
Okularのインストール
Okularは数あるPDFビューワーソフトの内の一つ。
以下のコマンドでインストールする。
sudo apt-get update sudo apt-get install okular
Okularの設定
PDFの1ページ目から5秒おきにページ進めていき、最終ページの次はまた1ページ目に戻るというようにループさせる。
- >設定 >Okularを設定 >全般 >外観 >"ヒントと情報メッセージを表示する" ⇒ OFF
- >設定 >Okularを設定 >全般 >外観 >"Display document title in titlebar if available" ⇒ OFF
- >設定 >Okularを設定 >プレゼンテーション >ナビゲーション >"一定時間ごとに進む" ⇒ 5秒
- >設定 >Okularを設定 >プレゼンテーション >ナビゲーション >"最後まで行ったら最初のページに戻る" ⇒ ON
- >設定 >Okularを設定 >プレゼンテーション >外観 >"進捗インジケータを表示する" ⇒ OFF
XScreenSaverのインストール
XScreenSaverはディスプレイをコントロールするソフト。ディスプレイが省エネモードに入って消えないようにする。
以下のコマンドでインストールする。
sudo apt-get update sudo apt-get install xscreensaver
XScreenSaverの設定
ラズパイのスタートメニュー >設定 >スクリーンセイバー >表示モード >モード >"セーバーを無効にする" を選択
スライドショーが自動起動するようにする
ラズパイが起動するのと同時にスライドショーも自動で起動されるようにする。
シェルスクリプトの作成
Okularの起動からスライドショー実行までをスクリプトで記述する。スクリプトファイルの保存場所は /opt が良い、らしい。
以下のコマンドでスクリプトファイルを新規作成する。
sudo touch /opt/slideshow.sh
テキストエディタで開く。
sudo mousepad /opt/slideshow.sh
スクリプトを以下の通り記述して保存する。
※/home/pi/share に対象となるPDFファイル(ここではslide.pdf)が置かれているものとする。
#!/bin/bash export DISPLAY=:0.0 export XAUTHORITY="/home/pi/.Xauthority" okular --presentation /home/pi/share/slide.pdf
サービス設定ファイルの作成
上記のスクリプトファイルを自動実行させるための設定ファイルを作成する。同じく、これの保存場所は /opt が良い、らしい。
以下のコマンドで設定ファイルを新規作成する。
sudo touch /opt/autoslideshow.service
テキストエディタで開く。
sudo mousepad /opt/autoslideshow.service
設定ファイルを以下の通り記述して保存する。
[Unit] Description=run slideshow.sh [Service] ExecStart=/opt/slideshow.sh Type=simple [Install] WantedBy=multi-user.target
自動実行サービスとして登録
以下のコマンドで登録する。
sudo systemctl enable /opt/autoslideshow.service
登録を解除したい時は以下のコマンドで。
sudo systemctl disable /opt/autoslideshow.service
動作確認
ラズパイを再起動して、スライドショーが自動実行されれば成功!
上手く行かないときは以下のサイトを参考のこと。
Raspberry PiでプログラムをOS起動時に実行させる [Systemd] - チカラの技術
Python - raspiでsystemdを使っての自動実行ができない|teratail
QXcbConnection: Could not connect to display | Qt Forum
ラズパイ4とWin10パソコンでフォルダを共有する!
Raspberry Pi上でPythonを使って色んなことをしてみたい。そのためにちょっとずつRaspberry Piの環境を整えています。その中で、Windowsパソコンに保管されているデータをどうやったらRaspberry Piに送ることができるか?ちょっとハマったので忘備録を残しておきます。
やりたいこと
パソコン(Windows10)で作成したOpencvのカスケード分類器(.xmlファイル)をRaspberry Piに移したい。
OpenCVのカスケード分類器を自作して画像認識
さらっと調べたところ、LANケーブルで接続してフォルダ共有するのが簡単そう。以下のイラストはその全容のイメージ。
環境
デバイスバージョン : Raspberry Pi 4 Model B Rev
Raspbianのバージョン : 10.7
手順
共有フォルダを作成
パソコンと共有するディレクトリを作成する。ここではpiの直下にshareという名前のディレクトリを作成し、そこを共有すべく次のステップから色々設定していく。
sudo mkdir /home/pi/share
Sambaをインストール
SambaとはLinux系OSをWindows Networkに参加させるためのソフトのこと。これをインストールする。
Samba | Linux技術者認定 LinuC | LPI-Japan
sudo apt-get update sudo apt-get install samba
ディレクトリのパーミッション設定
正直なところパーミッションのスコープを理解できていない。とりあえず動かしたかったので「全員にフル開放」で設定した。あとでちゃんと理解して修正する。
- etcに移動してから、
sudo chmod 777 samba
- piに移動してから、
sudo chmod 777 share
共有設定
ここも同じくpublicやguestのスコープを理解できていない。とりあえず動かしたかったので「全員にフル開放」で設定した。あとでちゃんと理解して修正する。
/etc/samba/cmb.confを開き、末尾に以下を追記する。
[share] comment = share path = /home/pi/share public = yes read only = no browsable = yes force user = pi writable = yes guest ok = yes guest only = yes
ipアドレス設定
- クロスLANケーブルでパソコンとRaspberry Piを接続する。
- Raspberry Piのipアドレス(eth0のアドレスとマスク)を調べる
ifconfig
⇒ (例) アドレス : 192.168.0.1 マスク : 255.255.0.0
- パソコンのネットワークアダプタにipアドレスを設定する
(例) アドレス : 192.168.0.2 マスク : 255.255.0.0
PythonでWebカメラの映像から円(硬貨)をリアルタイム検出する!
- 画像から円形の物体を検出したい
- opencvの
HoughCircles
を使うと良い。ただし、公式ドキュメントが「半径が安定しない」と注意事項を挙げている。半径の測定には向かない。
解説
HoughCircles
については色んなサイトで解説されている。
サンプルプログラム
Webカメラで複数の硬貨を撮影し、円検出する。撮像→検出のサイクルを繰り返すことでリアルタイム処理っぽくなっている。
Webカメラ
Baffalo製のBSW32KM01Hという10年も前のUSBカメラを使用した。最近のUSBカメラならもっときれいに映るかも。
結果
すべての硬貨を検出(緑色枠で囲うことが)できた。硬貨の置き方を変えても検出が追従できているし、それに伴い照明の当たり方が変わっても問題がない。ただし、HoughCircles
のパラメーターの合わせ込みが難しいのが難点。また、撮影する距離や角度が変わると劇的に検出しなくなるため、安定した撮像システムにしか馴染まない手法だと思う。
ソースコード
import sys #from time import sleep import cv2 #Webカメラのインスタンス作成 #引数はカメラ番号。0番はラップトップ内蔵カメラ。 cap = cv2.VideoCapture(1) #Webカメラのインスタンス作成に失敗したらプログラム終了 if not cap.isOpened(): print("Camera Not Found") sys.exit() #キャプチャと円検出を繰り返す while True: # sleep(1) #キャプチャ取得 _, frame = cap.read() img = frame.copy() #前処理 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.medianBlur(gray ,7) gray = cv2.equalizeHist(gray) #円検出 circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=4, minDist=50, param1=400, param2=100, minRadius=30, maxRadius=50) #円の検出に成功したらオリジナルのimgに円を描画 if circles is not None: for i in circles[0].astype('uint16'): cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2) cv2.imshow('Detect', img) k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows() cap.release()
VS Codeの Module 'cv2' has no 'imshow' member の解消
Pythonの開発環境として Visual Studio Code を使っていると、opencv
に関する警告が出る。
無視しても問題ないが煩わしいので解消したい。その方法を忘備録として残しておく。
環境
Python 3.8.1
opencv-python 4.1.2.30
Pylint 2.6.0
Visual Studio Code 1.54.2