テンプレートの検出画面をターゲティングモニタ風にしてみた。
2018年2月17日土曜日
2018年2月11日日曜日
動画でOpenCV(テンプレートマッチング)
WebカメラLogicool c270を買ったので 「OpenCVのテンプレートマッチングを試す 」を
動画でやってみた。
今回は、OpenCVのチュートリアル「動画を扱う」を参考にした。
テンプレート画像として、"temp100.png" "temp200.png" "temp300.png"を用意。
Logicool c270から読み込んだ画像を処理する。
Raspberry Pi 2 Model Bの処理を考えて、サイズを320x240、フレームレート15を設定。
※注意※
自分の環境では1回目の実行は問題ないが、2回目の実行で"cap = cv2.VideoCapture(0)"が
正常に行われないようなので、"cap.get(cv2.CAP_PROP_FPS) == 0"で判定しながら
繰り返し処理を入れてあります。
上のコードでは、"s"キーが押された時に"tkinter"を使って検出対象の位置情報を表示させているが、
これは一例なので、検出結果から「ここで何かする」って意味になる。
更に別スレッド、別プロセスにすれば動画(画像)の取得を止めること無く「何かする」
が実行出きるので、実際の運用はそう言った使い方になる筈。
動画でやってみた。
今回は、OpenCVのチュートリアル「動画を扱う」を参考にした。
テンプレート画像として、"temp100.png" "temp200.png" "temp300.png"を用意。
Logicool c270から読み込んだ画像を処理する。
Raspberry Pi 2 Model Bの処理を考えて、サイズを320x240、フレームレート15を設定。
※注意※
自分の環境では1回目の実行は問題ないが、2回目の実行で"cap = cv2.VideoCapture(0)"が
正常に行われないようなので、"cap.get(cv2.CAP_PROP_FPS) == 0"で判定しながら
繰り返し処理を入れてあります。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import tkinter
cap = cv2.VideoCapture(0)
while(cap.get(cv2.CAP_PROP_FPS) == 0):
cap.release()
cap = cv2.VideoCapture(0)
cap.set(3, 320)
cap.set(4, 240)
cap.set(5, 15.0)
print(cap.get(3))
print(cap.get(4))
print(cap.get(5))
grid_x = (25, 115, 205, 295)
grid_y = (45, 95, 145, 195)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter('output.avi', fourcc, 15.0, (320,240))
while(True):
res_100 = "???"
res_200 = "???"
res_300 = "???"
text ="???"
# Capture frame-by-frame
ret, frame = cap.read()
img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
for temp_num in [100, 200, 300]:
temp = cv2.imread("temp" + str(temp_num) + ".png", 0)
result = cv2.matchTemplate(img, temp, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val > 0.8:
b = 0
g = 0
r = 0
if temp_num == 100:
b = 255
if temp_num == 200:
g = 255
if temp_num == 300:
r = 255
top_left = max_loc
w, h = temp.shape[::-1]
bottom_right = (top_left[0] + w, top_left[1] + h)
res_x = []
res_y = []
for i in [0, 1, 2]:
if top_left[0] >= grid_x[i] and top_left[0] < grid_x[i + 1]:
if (i + 1 in res_x) == False:
res_x.append(i + 1)
for n in [0, 1, 2]:
if top_left[1] >= grid_y[n] and top_left[1] < grid_y[n + 1]:
if (n + 1 in res_y) == False:
res_y.append(n + 1)
#print("temp" + str(temp_num) + ".png = " + str(res_x[0]) + "-" + str(res_y[0]))
if temp_num == 100:
res_100 = str(res_x[0]) + "-" + str(res_y[0])
if temp_num == 200:
res_200 = str(res_x[0]) + "-" + str(res_y[0])
if temp_num == 300:
res_300 = str(res_x[0]) + "-" + str(res_y[0])
text = str(res_x[0]) + "-" + str(res_y[0]) + "(" + str("{:.3}".format(max_val)) + ")"
cv2.rectangle(frame, top_left, bottom_right, (b, g, r), 2)
cv2.putText(frame, text, (top_left[0] - 5, top_left[1] - 5), cv2.FONT_HERSHEY_PLAIN, 0.8, (b, g, r), 1, cv2.LINE_AA)
# Display the resulting frame
# write the frame
out.write(frame)
cv2.imshow("frame", frame)
key = cv2.waitKey(1)&0xff
if key == ord("s"):
label = tkinter.Label(None, text = "1 = " + res_100 + "\n2 = " + res_200 + "\n3 = " + res_300, font=("Times", "28"))
label.pack()
label.mainloop()
cv2.imwrite("capture.png", frame)
#break
if key == ord("q"):
break
# When everything done, release the capture
cap.release()
out.release()
cv2.destroyAllWindows()
上のコードでは、"s"キーが押された時に"tkinter"を使って検出対象の位置情報を表示させているが、
これは一例なので、検出結果から「ここで何かする」って意味になる。
更に別スレッド、別プロセスにすれば動画(画像)の取得を止めること無く「何かする」
が実行出きるので、実際の運用はそう言った使い方になる筈。
ラベル:
linux
,
opencv
,
raspberry pi
2018年1月4日木曜日
OpenCVのテンプレートマッチングを試す
以前にOpenCVを使って顔検出をやってみたが、今回はテンプレートマッチングで、
簡易的に数字を検出してみる。
下のページを参考にさせてもらいました。有り難うございました。
http://www.tech-tech.xyz/archives/3065942.html
本当は画像の中から文字を検出したかったのだが、意外と面倒そうだった。
手書きの文字やフォント不明の文字を認識したいわけではなく、予め用意した数字と
同じものさえ検出できればよかったので、テンプレート画像との一致を見つけることで
良しとした。
先ず、テンプレート画像を用意する。
上の画像から、検出したい数字の部分を切り取ってテンプレート画像を作る。
これら「1」「2」「3」のテンプレートを使って検出を行う。
※追記1(2018/01/04 20:20)※
誤検出を減らすように、テンプレートマッチングの結果から
"max_val"(グレースケールで最も高い輝度の値)が0.8より大きい時だけ
枠表示をするように変更しました。
何回か試したところ、正常に検出できた場合の"max_val"は、ほぼ0.9以上。
誤検出の場合は、0.7以下でした。
そこで「エイヤッ」と、0.8を設定しました。
今回は検出する画像がjpg、テンプレート画像がpngという変則コードになってしまったが
実行できれば問題ない(本当かよ?)
実際のカードを作って、それらを並べ替えてやってみた。
元画像を印刷した後、切り取って数字カードを作る。
それらのカードを適当に並べ替えて検出してみた。
更に、枠を外してやってみた。
<結果>
・影があったり、余分な物が写っている画像でも、正常に検出ができた。
<問題点>
・検出する画像の数字部分とテンプレート画像のサイズが(大体)合っていないと、
以下のようになる。
・検出する画像が大きいと時間が掛かる。
簡易的に数字を検出してみる。
下のページを参考にさせてもらいました。有り難うございました。
http://www.tech-tech.xyz/archives/3065942.html
本当は画像の中から文字を検出したかったのだが、意外と面倒そうだった。
手書きの文字やフォント不明の文字を認識したいわけではなく、予め用意した数字と
同じものさえ検出できればよかったので、テンプレート画像との一致を見つけることで
良しとした。
先ず、テンプレート画像を用意する。
上の画像から、検出したい数字の部分を切り取ってテンプレート画像を作る。
これら「1」「2」「3」のテンプレートを使って検出を行う。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import shutil
shutil.copyfile("test.jpg","result.jpg")
img = cv2.imread("result.jpg", 0)
for temp_num in [1, 2, 3]:
temp = cv2.imread("temp" + str(temp_num) + ".png", 0)
result = cv2.matchTemplate(img, temp, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val > 0.8:
top_left = max_loc
w, h = temp.shape[::-1]
bottom_right = (top_left[0] + w, top_left[1] + h)
result = cv2.imread("result.jpg")
cv2.rectangle(result,top_left, bottom_right, (255, 0, 0), 2)
cv2.imwrite("result.jpg", result)
※追記1(2018/01/04 20:20)※
誤検出を減らすように、テンプレートマッチングの結果から
"max_val"(
枠表示をするように変更しました。
何回か試したところ、正常に検出できた場合の"max_val"は、ほぼ0.9以上。
誤検出の場合は、0.7以下でした。
そこで「エイヤッ」と、0.8を設定しました。
今回は検出する画像がjpg、テンプレート画像がpngという変則コードになってしまったが
実行できれば問題ない(本当かよ?)
実際のカードを作って、それらを並べ替えてやってみた。
元画像を印刷した後、切り取って数字カードを作る。
それらのカードを適当に並べ替えて検出してみた。
<結果>
・影があったり、余分な物が写っている画像でも、正常に検出ができた。
<問題点>
・検出する画像の数字部分とテンプレート画像のサイズが(大体)合っていないと、
以下のようになる。
![]() |
| 間違った検出。画像の数字に対してテンプレートが小さい |
ラベル:
arch
,
linux
,
opencv
,
raspberry pi
2017年5月14日日曜日
Raspberry Pi Arch Linux ARMにOpenCV入れてみた
Arch Linux ARMにOpenCVとやらを入れてみた。
インストール自体は至極簡単。pacman(yaourt)任せでOK。
これだけで、OpenCVが使えるようになる。
このようなBGR値を、操作することで画像処理を行っていく(らしい)。
ついでなので、画像での顔検出をやってみる。
下のページを参考にさせてもらいました。有り難うございます。
http://peaceandhilightandpython.hatenablog.com/entry/2016/02/18/194303
(自分の環境で動くように、パスの指定等は変更しています。)
検出用には、OpenCVをインストールすると標準で入っている、
"/usr/share/opencv/haarcascades/haarcascade_frontface_default.xml"
を使用する。
元の画像(お馴染みの)
検出結果
試しに、180度回転して上下逆にした画像で実行してみた。
これは、"no face"となり、検出できなかった。
インストール自体は至極簡単。pacman(yaourt)任せでOK。
sudo pacman -S opencvPythonで使いたいので、"numpy"もインストールする。
sudo pacman -S python-numpy"numpy"は、Pythonで数値計算を効率良く(高速に?)行う為のライブラリらしい。
これだけで、OpenCVが使えるようになる。
このようなBGR値を、操作することで画像処理を行っていく(らしい)。
ついでなので、画像での顔検出をやってみる。
下のページを参考にさせてもらいました。有り難うございます。
http://peaceandhilightandpython.hatenablog.com/entry/2016/02/18/194303
(自分の環境で動くように、パスの指定等は変更しています。)
検出用には、OpenCVをインストールすると標準で入っている、
"/usr/share/opencv/haarcascades/haarcascade_frontface_default.xml"
を使用する。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import cv2
import numpy as np
faceCascade = cv2.CascadeClassifier('/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml')
img = cv2.imread('./face.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face = faceCascade.detectMultiScale(gray, 1.1, 3)
if len(face) > 0:
for rect in face:
cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (255, 255,255), thickness=2)
else:
print("no face")
cv2.imwrite('detected.jpg', img)元の画像(お馴染みの)
検出結果
試しに、180度回転して上下逆にした画像で実行してみた。
これは、"no face"となり、検出できなかった。
ラベル:
arch
,
linux
,
opencv
,
raspberry pi
登録:
投稿
(
Atom
)















