開発経緯
画像解析で前のフレームと今のフレームを比較して、2Dカメラ一つで立体的な空間データを取るための下準備として今回のプログラムを開発しました。OpenCVを勉強し始めてまだ1ヶ月程度なのでプログラムが非効率かもしれません。有志の方、ぜひ改善プログラムをコメントでご指摘いただけると幸いです。Python使用歴は2022/4から始めたので今で6ヶ月です。
開発環境
- Ubuntu 20.04 LTS
- Python 3.8.10
- Opencv-python 4.6.0
必要モジュール
- Opencv-python
- numpy
プログラムを書く:カメラの下準備編
今回はプログラムは一つのファイルで完結するので適当に好きなディレクトリに main.pyを作ってください。
まずモジュールをインポートします。
import cv2
import numpy as np
次にカメラからの映像をPythonを使って扱っていきます。Pythonでカメラの映像を取得する下準備をします。
# 続けて書く
~~~
WIDTH = 800
HEIGHT = 600
FPS = 30
VIDEO_TARGET = 1 #カメラID
VIDEO_TARGETという変数について
この変数の数字はパソコンの環境によって変わります。私の場合はDellのパソコンで1を設定することで内蔵カメラを指定することができました。友達のパソコンでは0を指定することで内蔵カメラを指定することができていたので、ご自身のパソコンに応じて柔軟に対応してください。
スマートフォンのカメラを使いたい場合は、Iriunを使うことをおすすめします。私もつかっています。
Iriunダウンロードページ
Iriunをスマホにもダウンロードして正常に接続できたらVIDEO_TARGETの変数の数字を2や3に変えてみてください。
プログラムを書く:カメラの映像を加工しよう編
cap_file = cv2.VideoCapture(VIDEO_TARGET)
count = 1
cap_file.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('H','2','6','4'))
cap_file.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
cap_file.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
cap_file.set(cv2.CAP_PROP_FPS, FPS)
上のプログラムはカメラのデータをOpencvで処理しやすいように、さっき書いた変数をもとに解像度やフレームレートを変えます。
フレームごとに処理させる
#前のフレーム
previous_frame = []
#繰り返しのためのwhile文
while True:
print('あの一瞬(とき)は戻ってこない...',count)
#カメラからの画像取得
ret, frame = cap_file.read()
orb = cv2.ORB_create()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
canny = cv2.Canny(gray,5,50)
height = canny.shape[0]
width = canny.shape[1]
center = (int(width/2),int(height/2))
angle = 0
scale = 1.0
trans = cv2.getRotationMatrix2D(center,angle,scale)
image2 = cv2.warpAffine(frame,trans,(width,height))
previous_frame.append(image2)
img_src1 = image2
img_src2 = previous_frame[count - 1]
img_dst = img_src1
keypoint1,descript1 = orb.detectAndCompute(img_src1,None) #現在のフレームの写真
keypoint2,descript2 = orb.detectAndCompute(img_src2,None) #前のフレームの写真をゲット
bf = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)
matches = bf.match(descript1,descript2)
matches = sorted(matches,key=lambda x:x.distance)
img3 = cv2.drawMatches(img_src1, keypoint1, img_src2, keypoint2, matches, img_dst, flags=2)
#カメラの画像の出力
cv2.imshow('camera' , img3)
#繰り返し分から抜けるためのif文
cv2.waitKey(1)
cv2.destroyAllWindows()
count +=1
#メモリを解放して終了するためのコマンド
cap.release()
cv2.destroyAllWindows()
まず、orb = cv2.ORB_create()でORB抽出器を初期化します。
cannyでエッジ検出をしています。
BFMatcherやdrawMatchesで特徴点を線で結びます。
ちょっと小ネタ:類似点検知で的確な角度とは
今、私が書いたプログラムではAKAZEというものを利用しました。実はこれ前バージョンKAZEの高速版なんですね。
てことは2つ兄弟関係という捉え方でいいのかな..?
とても興味深い記事を発見しました。
この画像は論文資料の一部です。論文の内容は写真一枚に対する類似点検出についてですが、本記事のように写真2枚を扱うときでも同様のことが言えるかもしれないと思いました。
つまり、一つのカメラだけ30度向かせて、もう一つのカメラは角度を変えないという方法です。
精度がぐんと上がるかもしれません。
ちなみに下の画像は両カメラ45度内側に傾けて実験して見た結果です。
回転角90度となるわけですが、全く類似点検出をしていません。(あえてここでは類似点の本数を2本に限定しています)
普通にパソコンの画面にTwitterうつってたからモザイク処理をしたら逆になんかね、ちょっと(苦笑)
パソコン周り汚いですが、耐えてください!
結論 30度にせよ!!!
サンプル映像
以上で今回の記事はおしまいです。お疲れ様でした。