メモ > 技術 > 開発: RaspberryPi > OpenCV
OpenCV
Raspberry Pi + Python 3 に OpenCV 3 をなるべく簡単にインストールする - Qiita
https://qiita.com/masaru/items/658b24b0806144cfeb1c
以下でライブラリをインストール。(それぞれ、すぐに完了した。)
$ sudo apt-get install -y libhdf5-dev libhdf5-serial-dev
$ sudo apt-get install -y libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5
$ sudo apt-get install -y libatlas-base-dev
$ sudo apt-get install -y libjasper-dev
以下でOpenCVをインストール。(1時間15分ほどかかった。)
$ sudo pip3 --default-timeout=1000 install opencv-python
この時点で、拡張モジュール群である opencv-contrib-python も一緒にインストールしておくといい。(これはすぐにインストールできる。)
opencv-contrib-python をインストールして「import cv2」でエラーになる場合、後述の「opencv-contrib-python をインストールするとエラーになる」を参照。
$ sudo pip3 --default-timeout=1000 install opencv-contrib-python
以下で動作確認。
あらかじめ test.jpg は配置しておく。
canny.jpg に加工済みの画像が書き出される。
$ python3
Python 3.7.3 (default, Apr 3 2019, 05:39:12)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'3.4.3'
>>> bgr = cv2.imread('./test.jpg', cv2.IMREAD_COLOR)
>>> gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
>>> canny = cv2.Canny(gray, 200, 50)
>>> cv2.imwrite('./canny.jpg', canny)
True
>>> exit()
2019年9月に試すと、上記のとおり3.4.3がインストールされた。
2020年9月に試すと、4.4.0がインストールされた。
■ライブラリインストール時のエラー
「ライブラリをインストール」で参考URLと同じコマンドを実行すると、以下のエラーになった。
単純に、エラーになった libhdf5-100 を省くとインストールできたが、正しい方法かどうかは不明。
$ sudo apt-get install libhdf5-dev libhdf5-serial-dev libhdf5-100
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
注意、'libhdf5-serial-dev' の代わりに 'libhdf5-dev' を選択します
パッケージ libhdf5-100 は使用できませんが、別のパッケージから参照されます。
これは、パッケージが欠落しているか、廃止されたか、または別のソース
からのみ利用可能であることを意味します。
しかし、以下のパッケージが置き換えます:
libhdf5-103
E: パッケージ 'libhdf5-100' にはインストール候補がありません
■opencv-contrib-python をインストールするとエラーになる
ラズパイでpython3にopencvを入れたらエラーが出た【対処法】 - Qiita
https://qiita.com/XM03/items/48463fd910470b226f22
必要なライブラリをインストール。
$ sudo pip3 --default-timeout=1000 install opencv-contrib-python
インストールすると、「import cv2」でエラーになるようになった。
>>> import cv2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.7/dist-packages/cv2/__init__.py", line 3, in <module>
from .cv2 import *
ImportError: /usr/local/lib/python3.7/dist-packages/cv2/cv2.cpython-37m-arm-linux-gnueabihf.so: undefined symbol: __atomic_fetch_add_8
以下で対処する。
$ LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1
$ vim.tiny .bashrc
■プログラムを作成して実行
export LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1 … 最終行に追加。
$ source .bashrc
$ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.1.1'
>>> exit()
$ vi test.py
■画像をウインドウに表示
opencv - Python で cv2.imshow としても画像が表示されない - スタック・オーバーフロー
https://ja.stackoverflow.com/questions/31537/python-%E3%81%A7-cv2-imshow-%E3%81%A8%E3%81%97%E3%81%A6...
import cv2
bgr = cv2.imread('./camera/test.jpg', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 200, 50)
cv2.imwrite('./camera/test_canny.jpg', canny)
$ python3 test.py
import cv2
img = cv2.imread('lena.png', 0)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
SSH経由で実行しても以下のエラーになる。(Raspberry Pi 内のターミナルからなら表示できる。)
Unable to init server: Could not connect: 接続を拒否されました
(image:9950): Gtk-WARNING **: 00:46:48.398: cannot open display:
■カメラの映像をリアルタイムに表示
Python, OpenCVで動画を読み込み(ファイル・カメラ映像) | note.nkmk.me
https://note.nkmk.me/python-opencv-videocapture-file-camera/
import sys
import cv2
# カメラ
camera_id = 0
# ウインドウ名
window_name = 'frame'
# カメラの映像を取得
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
sys.exit()
# リアルタイムにウインドウへ表示
while True:
ret, frame = cap.read()
cv2.imshow(window_name, frame)
# 「q」が入力されたら終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ウインドウを閉じる
cv2.destroyWindow(window_name)
白黒化とぼかしを適用。
import cv2
import sys
# カメラ
camera_id = 0
# ウインドウ名
window_name = 'frame'
# カメラの映像を取得
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
sys.exit()
# リアルタイムにウインドウへ表示
while True:
ret, frame = cap.read()
# 白黒化とぼかしを適用
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (0, 0), 5)
cv2.imshow(window_name, blur)
# 「q」が入力されたら終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ウインドウを閉じる
cv2.destroyWindow(window_name)
ffmpegで配信する方法もあるみたい。
リモートの環境のPythonからOpenCVを使い、手元のWebカメラの映像を読みたい - Qiita
https://qiita.com/fukasawah/items/32ebef9cd646a1eb3e3a
引き続き、リアルタイムでの顔認識なども試したい。
Pythonで画像処理: Pillow, NumPy, OpenCVの違いと使い分け | note.nkmk.me
https://note.nkmk.me/python-image-processing-pillow-numpy-opencv/
画像処理をマスターしよう!PythonでOpenCVを使う方法を紹介! | TechTeacher Blog
https://www.tech-teacher.jp/blog/python-opencv/
■画像の変化を確認
※動いているようだが、それぞれの意味は要勉強。
※定点カメラでの変化を検知できるかは要懸賞。
カメラの僅かなブレなどで差分を検知してしまうか。画像を縮小してから差分を取れば、僅かな差は吸収できるか。
python - Pythonを使ったOpenCVでの背景差分の数値化の方法 - スタック・オーバーフロー
https://ja.stackoverflow.com/questions/48019/python%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9Fopencv%E3%81%...
画像処理入門講座 : OpenCVとPythonで始める画像処理 | POSTD
https://postd.cc/image-processing-101/
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 画像を読み込み
img_src1 = cv2.imread("./test/test1.jpg", cv2.IMREAD_GRAYSCALE)
img_src2 = cv2.imread("./test/test2.jpg", cv2.IMREAD_GRAYSCALE)
# 画像の差分を算出
img_diff = cv2.absdiff(img_src1, img_src2)
# 画像の差分を二極化
img_diffm = cv2.threshold(img_diff, 20, 255, cv2.THRESH_BINARY)[1]
# グレースケール画像をRGB化
img_diff = cv2.cvtColor(img_diff, cv2.COLOR_GRAY2RGB)
img_diffm = cv2.cvtColor(img_diffm, cv2.COLOR_GRAY2RGB)
# 画像の差分を数値化
diff_sum = np.sum(img_diffm)
print(diff_sum)
# 以降は結果表示
plt.subplot(1, 2, 1) # 1行に分割、2列に分割、そのうちの1つめに描画
plt.title("Diff image")
plt.imshow(img_diff)
plt.subplot(1, 2, 2) # 1行に分割、2列に分割、そのうちの2つめに描画
plt.title("Mask image")
plt.imshow(img_diffm)
plt.show()
以下も確認したい。
subplot | Python で一枚のプロットに複数グラフを描く方法
https://stats.biopapyrus.jp/python/subplot.html
ラズパイ4 動体検知する(PYTHON+OPENCV) | KatsEye
https://kats-eye.net/info/2020/06/09/motion-detect/
Python/OpenCVで動体検知!動画の動いている部分を検出 | WATLAB -Python, 信号処理, AI-
https://watlab-blog.com/2019/09/26/motion-detection/
OpenCV-Pythonで似たような画像の差分を検出する - Qiita
https://qiita.com/kikuyan8540/items/0c92a8ab47e84ec79652
Python+OpenCVとWebカメラを使って動体検知する話 - EnsekiTT Blog
https://ensekitt.hatenablog.com/entry/2018/06/11/200000
OpenCVを利用して動画(カメラ)から動体検知をする方法について | CyberAgent Developers Blog
https://developers.cyberagent.co.jp/blog/archives/12666/
画像処理入門講座 : OpenCVとPythonで始める画像処理 | POSTD
https://postd.cc/image-processing-101/
■画像の変化をリアルタイムに確認(動体検知)
import cv2
import numpy as np
import sys
# カメラ
camera_id = 0
# ウインドウ名
window_name = 'frame'
# カメラの映像を取得
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
sys.exit()
# リアルタイムにウインドウへ表示
buf_img = None
while True:
# 画像を取得
ret, cap_img = cap.read()
# 画像をグレースケール化
gray_img = cv2.cvtColor(cap_img, cv2.COLOR_BGR2GRAY)
# 初回はバッファがないので作成
if buf_img is None:
buf_img = gray_img
# 画像の差分を算出
img_diff = cv2.absdiff(gray_img, buf_img)
# 画像の差分を二極化
img_diffm = cv2.threshold(img_diff, 20, 255, cv2.THRESH_BINARY)[1]
# 画像の輪郭を抽出
contours, hierarchy = cv2.findContours(img_diffm, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# グレースケール画像をRGB化
img_diff = cv2.cvtColor(img_diff, cv2.COLOR_GRAY2RGB)
img_diffm = cv2.cvtColor(img_diffm, cv2.COLOR_GRAY2RGB)
# 画像の差分を数値化
diff_sum = np.sum(img_diffm)
#print(diff_sum)
# 画像データを保持
buf_img = gray_img
# 矩形検出された数(デフォルトで0を指定)
detect_count = 0
# 各輪郭に対する処理
for i in range(0, len(contours)):
# 輪郭の領域を計算
area = cv2.contourArea(contours[i])
# ノイズ(小さすぎる領域)と全体の輪郭(大きすぎる領域)を除外
if area < 100 or 10000 < area:
continue
# 外接矩形
if len(contours[i]) > 0:
rect = contours[i]
x, y, w, h = cv2.boundingRect(rect)
cv2.rectangle(cap_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 外接矩形毎に画像を保存
#cv2.imwrite('test/' + str(detect_count) + '.jpg', src[y:y + h, x:x + w])
detect_count = detect_count + 1
#print(detect_count)
# テキストを描画
cv2.putText(
cap_img, # 描画対象
'Detected: ' + str(detect_count), # テキスト
(20, 50), # 座標
cv2.FONT_HERSHEY_SIMPLEX, # フォント
1, # フォントサイズ
(255,255,255), # フォントカラー
2, # フォントウェイト
cv2.LINE_AA # 線の種類
)
# 画像を表示
cv2.imshow(window_name, cap_img)
# 「q」が入力されたら終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ウインドウを閉じる
cv2.destroyWindow(window_name)
以下のようにして通常実行できる。
$ python3 camera_detection.py
以下のようにすれば、バックグラウンドで実行し続けることができる。
この場合、処理の停止は kill を使用する。
$ nohup python3 camera_detection.py &
[1] 4078
$ ps aux | grep python3
$ kill 4078
Raspberry Piで室内カメラを作る? - Qiita
https://qiita.com/henjiganai/items/b491e498d7d367306cd5
Raspberry Piで最強の防犯カメラを作ってみる(動画記録・配信、動体検知・Line通知、顔検知・顔認証、Alexa搭載)[1/6] | 育児×家事×IoT
https://dream-soft.mydns.jp/blog/developper/smarthome/2020/01/649/
Raspberry Piで最強の防犯カメラを作ってみる(動画記録・配信、動体検知・Line通知、顔検知・顔認証、Alexa搭載)[3/6] | 育児×家事×IoT
https://dream-soft.mydns.jp/blog/developper/smarthome/2020/02/678/
RasPiCamera/Camera.py at master - naka-kazz/RasPiCamera
https://github.com/naka-kazz/RasPiCamera/blob/master/camera_step3/Camera.py
RaspberryPi4にYOLOv3-Tinyを実装してリアルタイム画像認識をしながら物体を自動追尾するカメラを作ってみた - Qiita
https://qiita.com/daiarg/items/3da30c93b05496522acb
カラー図解 Raspberry Piではじめる機械学習 補足情報: Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみよう
https://mlbb1.blogspot.com/2019/12/raspberry-pi-yolo-v3-tiny-yolo-v3.html
RaspberryPiでWEBカメラを使ってOpenCVで動体検知な監視カメラをつくってみた - Qiita
https://qiita.com/hasekou_tech/items/acd0d9159a9001ebfbd3
■画像の変化を確認(動かない)
※謎エラーのため実行できていない。
$ vi test.py
以下なら何かしらの結果を得られているようだが、詳細は要勉強。
import cv2
beforeImage = cv2.imread('./test/test.png', cv2.IMREAD_COLOR)
beforeImage = cv2.cvtColor(beforeImage, cv2.COLOR_BGR2GRAY)
grayImage = cv2.imread('./test/test.png', cv2.IMREAD_COLOR)
grayImage = cv2.cvtColor(grayImage, cv2.COLOR_BGR2GRAY)
cv2.accumulateWeighted(grayImage, beforeImage, 0.00001)
$ python3 test.py
Traceback (most recent call last):
File "test.py", line 33, in <module>
cv2.accumulateWeighted(grayImage, beforeImage, 0.00001)
cv2.error: OpenCV(4.4.0) /tmp/pip-wheel-frffvd08/opencv-python/opencv/modules/imgproc/src/accum.cpp:635: error: (-215:Assertion failed) func != 0 in function 'accumulateWeighted'
$ vi test.py
ただし、findContours は引数が間違っているのかエラーになる。
グレースケール画像を読み込む必要がある?
import cv2
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
test1 = cv2.imread('./test/test1.jpg', cv2.IMREAD_COLOR)
test1 = cv2.cvtColor(test1, cv2.COLOR_BGR2GRAY)
test1= test1.astype(np.float32)
test2 = cv2.imread('./test/test2.jpg', cv2.IMREAD_COLOR)
test2 = cv2.cvtColor(test2, cv2.COLOR_BGR2GRAY)
test2 = test2.astype(np.float32)
cv2.accumulateWeighted(test1, test2, 0.01)
delta = cv2.absdiff(test1, test2)
thresh = cv2.threshold(delta, 50, 255, cv2.THRESH_BINARY)[1]
#image, contours, h = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#print(test1.dtype)
#print(test2.dtype)
#print(delta)
plt.figure(figsize=(4, 4), dpi=72)
plt.plot(delta)
plt.savefig('test/graph.png')
Traceback (most recent call last):
File "diff.py", line 18, in <module>
image, contours, h = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.error: OpenCV(4.4.0) /tmp/pip-wheel-frffvd08/opencv-python/opencv/modules/imgproc/src/contours.cpp:197: error: (-210:Unsupported format or combination of formats) [Start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function 'cvStartFindContours_Impl'
[Q&A] 二値化画像の輪郭抽出について - Qiita
https://qiita.com/yutapuu/questions/c1981051051c76cede08
以降はその他メモ。
OpenCVで手っ取り早く動体検知してみた - Qiita
https://qiita.com/K_M95/items/4eed79a7da6b3dafa96d
Raspberry Piで最強の防犯カメラを作ってみる(動画記録・配信、動体検知・Line通知、顔検知・顔認証、Alexa搭載)[3/6] | 育児×家事×IoT
https://dream-soft.mydns.jp/blog/developper/smarthome/2020/02/678/
動体検知とトラッキングを組み合わせて動いてた物体を見失わないようにする話 - EnsekiTT Blog
https://ensekitt.hatenablog.com/entry/2018/06/13/200000
c++ - Assertion failed with accumulateWeighted in OpenCV - Stack Overflow
https://stackoverflow.com/questions/7059817/assertion-failed-with-accumulateweighted-in-opencv
opencv/accum.cpp at master - opencv/opencv
https://github.com/opencv/opencv/blob/master/modules/imgproc/src/accum.cpp
OpenCVのチャンネルエラー対処: (-215:Assertion failed) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function 'binary_op' | 404 motivation not found
https://tech-blog.s-yoshiki.com/entry/75
■カメラの画像を取得して加工して保存
import picamera
import picamera.array
import cv2
camera = picamera.PiCamera()
camera.resolution = (640, 480)
stream = picamera.array.PiRGBArray(camera)
camera.capture(stream, 'bgr', use_video_port=True)
gray = cv2.cvtColor(stream.array, cv2.COLOR_BGR2GRAY)
cv2.imwrite('./camera/stream.jpg', gray)
■画像の差分を抽出
背景差分で物体抽出(画像比較) - Qiita
https://qiita.com/goodboy_max/items/71a3b804d14f961c0d91
以下で test1.jpg と test2.jpg の差分が diff.jpg に出力される。
import cv2
# 画像の読み込み
img_src1 = cv2.imread("test/test1.jpg", 1)
img_src2 = cv2.imread("test/test2.jpg", 1)
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
fgmask = fgbg.apply(img_src1)
fgmask = fgbg.apply(img_src2)
# 検出画像
bg_diff_path = 'test/diff.jpg'
cv2.imwrite(bg_diff_path,fgmask)
cv2.waitKey(0)
■画像を認識する
Raspberry PiとOpenCVによる画像認識で人の顔を判別する | パソコン工房 NEXMAG
https://www.pc-koubou.jp/magazine/19205
■顔を検出するプログラム
【入門者向け解説】openCV顔検出の仕組と実践(detectMultiScale) - Qiita
https://qiita.com/FukuharaYohei/items/ec6dce7cc5ea21a51a82
import cv2
# 分類器ディレクトリ(以下から取得)
# https://github.com/opencv/opencv/blob/master/data/haarcascades/
# モデルファイル
cascade_path = "haarcascade_frontalface_default.xml"
# 使用ファイルと入出力ディレクトリ
image_file = "face.jpg"
output_file = "face_output.jpg"
# ディレクトリ確認用(うまく行かなかった時用)
#import os
#print(os.path.exists(image_file))
#ファイル読み込み
image = cv2.imread(image_file)
#グレースケール変換
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)
#物体認識(顔認識)の実行
#image - CV_8U 型の行列.ここに格納されている画像中から物体が検出されます
#objects - 矩形を要素とするベクトル.それぞれの矩形は,検出した物体を含みます
#scaleFactor - 各画像スケールにおける縮小量を表します
#minNeighbors - 物体候補となる矩形は,最低でもこの数だけの近傍矩形を含む必要があります
#flags - このパラメータは,新しいカスケードでは利用されません.古いカスケードに対しては,cvHaarDetectObjects 関数の場合と同じ意味を持ちます
#minSize - 物体が取り得る最小サイズ.これよりも小さい物体は無視されます
facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
#print(facerect)
color = (255, 255, 255) #白
# 検出した場合
if len(facerect) > 0:
#検出した顔を囲む矩形の作成
for rect in facerect:
cv2.rectangle(image, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), color, thickness=2)
#認識結果の保存
cv2.imwrite(output_file, image)
■顔を検出するプログラム(調整+CGI版)
#!/Users/refirio/Anaconda3/python
# coding: utf-8
# -*- coding: utf-8 -*-
import sys
import io
import cv2
# 使用ファイルと入出力ディレクトリ
IMAGE_FILE = "daughter.png"
INPUT_PATH = "./inputs/" + IMAGE_FILE
OUTPUT_PATH = "./outputs/" + IMAGE_FILE
# ラインの色
COLOR_WHITE = (255, 255, 255)
COLOR_RED = (0, 0, 255)
# 画像ファイル読み込み
image = cv2.imread(INPUT_PATH)
# 画像をグレースケール変換
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# カスケード分類器の特徴量を取得
face_cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_alt.xml")
eye_cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_eye.xml")
# 画像の中から顔を検出
faces = face_cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=2, minSize=(50, 50))
if len(faces) > 0:
# 検出した顔の座標を取得
for (face_x,face_y,face_w,face_h) in faces:
# 検出した顔を囲む矩形の作成
cv2.rectangle(image, (face_x,face_y),(face_x + face_w,face_y + face_h), COLOR_WHITE, 2)
# 検出した顔画像を取得
face_image = image[face_y : face_y + face_h, face_x : face_x + face_w]
# 検出した顔画像をグレースケール変換
face_image_gray = image_gray[face_y : face_y + face_h, face_x : face_x + face_w]
# 顔画像の中から目を検出
eyes = eye_cascade.detectMultiScale(face_image_gray, scaleFactor=1.1, minNeighbors=2, minSize=(20, 20))
if len(faces) > 0:
# 検出した目の座標を取得
for (eye_x,eye_y,eye_w,eye_h) in eyes:
# 検出した目を囲む矩形の作成
cv2.rectangle(face_image,(eye_x, eye_y),(eye_x + eye_w,eye_y + eye_h), COLOR_RED, 2)
# 認識結果の保存
cv2.imwrite(OUTPUT_PATH, image)
# 結果画面を表示
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print("Content-Type: text/html; charset=UTF-8\n")
print("<!DOCTYPE html>")
print("<html>")
print("<head>")
print("<meta charset=\"utf-8\">")
print("<title>Python</title>")
print("</head>")
print("<body>")
print("<h1>Python</h1>")
print("<img src=\"" + OUTPUT_PATH + "\" style=\"max-width: 500px; max-height: 500px;\">")
print("</body>")
print("</html>")
■リアルタイムに顔認識
import cv2
import numpy as np
import sys
# カメラ
camera_id = 0
# ウインドウ名
window_name = 'frame'
# 画像の上下左右反転
flip_image = 1
# モデルファイル
cascade_path = "haarcascade_frontalface_default.xml"
#カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)
# カメラの映像を取得
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
sys.exit()
# リアルタイムにウインドウへ表示
buf_img = None
while True:
# 画像を取得
ret, cap_img = cap.read()
if flip_image == 1:
cap_img = cv2.flip(cap_img, -1)
# 画像をグレースケール化
gray_img = cv2.cvtColor(cap_img, cv2.COLOR_BGR2GRAY)
# 初回はバッファがないので作成
if buf_img is None:
buf_img = gray_img
# 画像の差分を算出
img_diff = cv2.absdiff(gray_img, buf_img)
# 画像の差分を二極化
img_diffm = cv2.threshold(img_diff, 20, 255, cv2.THRESH_BINARY)[1]
# 画像の輪郭を抽出
contours, hierarchy = cv2.findContours(img_diffm, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# グレースケール画像をRGB化
img_diff = cv2.cvtColor(img_diff, cv2.COLOR_GRAY2RGB)
img_diffm = cv2.cvtColor(img_diffm, cv2.COLOR_GRAY2RGB)
# 画像の差分を数値化
diff_sum = np.sum(img_diffm)
#print(diff_sum)
# 画像データを保持
buf_img = gray_img
# 矩形検出された数(デフォルトで0を指定)
detect_count = 0
# 各輪郭に対する処理
for i in range(0, len(contours)):
# 輪郭の領域を計算
area = cv2.contourArea(contours[i])
# ノイズ(小さすぎる領域)と全体の輪郭(大きすぎる領域)を除外
if area < 100 or 10000 < area:
continue
# 外接矩形
if len(contours[i]) > 0:
rect = contours[i]
x, y, w, h = cv2.boundingRect(rect)
cv2.rectangle(cap_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 外接矩形毎に画像を保存
#cv2.imwrite('test/' + str(detect_count) + '.jpg', src[y:y + h, x:x + w])
detect_count = detect_count + 1
#print(detect_count)
# テキストを描画
cv2.putText(
cap_img, # 描画対象
'Detected: ' + str(detect_count), # テキスト
(20, 50), # 座標
cv2.FONT_HERSHEY_SIMPLEX, # フォント
1, # フォントサイズ
(255,255,255), # フォントカラー
2, # フォントウェイト
cv2.LINE_AA # 線の種類
)
# 顔を検出
facerect = cascade.detectMultiScale(gray_img, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
if len(facerect) > 0:
#検出した顔を囲む矩形の作成
for rect in facerect:
cv2.rectangle(cap_img, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), (0, 0, 255), thickness=2)
# 画像を表示
cv2.imshow(window_name, cap_img)
# 「q」が入力されたら終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ウインドウを閉じる
cv2.destroyWindow(window_name)
■分類器
OpenCVで顔認識とそれ以外の物体認識(カスケード分類機まとめ)
https://www.tech-tech.xyz/haar-cascade.html
https://github.com/opencv/opencv/blob/master/data/haarcascades/ 内のファイルメモ
haarcascade_eye.xml … 人の目 Stump-based 20x20 frontal eye detector.
haarcascade_eye_tree_eyeglasses.xml … めがねを付けた目 Tree-based 20x20 frontal eye detector with better handling of eyeglasses.
haarcascade_frontalcatface.xml … 猫の顔(正面) A frontal cat face detector using the basic set of Haar features,
haarcascade_frontalcatface_extended.xml … 猫の顔(正面) A frontal cat face detector using the full set of Haar features,
haarcascade_frontalface_alt.xml … 顔検出(正面) Stump-based 20x20 gentle adaboost frontal face detector.
haarcascade_frontalface_alt2.xml … 顔検出(正面) Tree-based 20x20 gentle adaboost frontal face detector.
haarcascade_frontalface_alt_tree.xml … 顔検出(正面) Stump-based 20x20 gentle adaboost frontal face detector.
haarcascade_frontalface_default.xml … 顔検出(正面) Stump-based 24x24 discrete(?) adaboost frontal face detector.
haarcascade_profileface.xml … 証明写真の顔 20x20 profile face detector.
haarcascade_smile.xml … 笑顔 Smile detector.
haarcascade_lefteye_2splits.xml … 左目 Tree-based 20x20 left eye detector.
haarcascade_righteye_2splits.xml … 右目 Tree-based 20x20 right eye detector.
haarcascade_fullbody.xml … 全身 14x28 fullbody detector.
haarcascade_upperbody.xml … 上半身 22x18 upperbody detector.
haarcascade_lowerbody.xml … 下半身 19x23 lowerbody detector.
haarcascade_licence_plate_rus_16stages.xml … ロシアの車ナンバープレート(全体)
haarcascade_russian_plate_number.xml … ロシアの車ナンバープレート(数字部分)
■scaleFactor
物体検出(detectMultiScale)をパラメータを変えて試してみる(scaleFactor編) | Workpiles
http://workpiles.com/2015/04/opencv-detectmultiscale-scalefactor/