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"で判定しながら
繰り返し処理を入れてあります。

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import cv2
  5. import numpy as np
  6. import tkinter
  7.  
  8. cap = cv2.VideoCapture(0)
  9.  
  10. while(cap.get(cv2.CAP_PROP_FPS) == 0):
  11. cap.release()
  12. cap = cv2.VideoCapture(0)
  13.  
  14. cap.set(3, 320)
  15. cap.set(4, 240)
  16. cap.set(5, 15.0)
  17.  
  18. print(cap.get(3))
  19. print(cap.get(4))
  20. print(cap.get(5))
  21.  
  22. grid_x = (25, 115, 205, 295)
  23. grid_y = (45, 95, 145, 195)
  24.  
  25. fourcc = cv2.VideoWriter_fourcc(*"XVID")
  26. out = cv2.VideoWriter('output.avi', fourcc, 15.0, (320,240))
  27.  
  28. while(True):
  29. res_100 = "???"
  30. res_200 = "???"
  31. res_300 = "???"
  32. text ="???"
  33.  
  34. # Capture frame-by-frame
  35. ret, frame = cap.read()
  36. img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  37.  
  38. for temp_num in [100, 200, 300]:
  39. temp = cv2.imread("temp" + str(temp_num) + ".png", 0)
  40. result = cv2.matchTemplate(img, temp, cv2.TM_CCOEFF_NORMED)
  41. min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
  42.  
  43. if max_val > 0.8:
  44. b = 0
  45. g = 0
  46. r = 0
  47. if temp_num == 100:
  48. b = 255
  49. if temp_num == 200:
  50. g = 255
  51. if temp_num == 300:
  52. r = 255
  53.  
  54. top_left = max_loc
  55. w, h = temp.shape[::-1]
  56. bottom_right = (top_left[0] + w, top_left[1] + h)
  57.  
  58. res_x = []
  59. res_y = []
  60.  
  61. for i in [0, 1, 2]:
  62. if top_left[0] >= grid_x[i] and top_left[0] < grid_x[i + 1]:
  63. if (i + 1 in res_x) == False:
  64. res_x.append(i + 1)
  65. for n in [0, 1, 2]:
  66. if top_left[1] >= grid_y[n] and top_left[1] < grid_y[n + 1]:
  67. if (n + 1 in res_y) == False:
  68. res_y.append(n + 1)
  69.  
  70. #print("temp" + str(temp_num) + ".png = " + str(res_x[0]) + "-" + str(res_y[0]))
  71.  
  72. if temp_num == 100:
  73. res_100 = str(res_x[0]) + "-" + str(res_y[0])
  74. if temp_num == 200:
  75. res_200 = str(res_x[0]) + "-" + str(res_y[0])
  76. if temp_num == 300:
  77. res_300 = str(res_x[0]) + "-" + str(res_y[0])
  78.  
  79. text = str(res_x[0]) + "-" + str(res_y[0]) + "(" + str("{:.3}".format(max_val)) + ")"
  80.  
  81. cv2.rectangle(frame, top_left, bottom_right, (b, g, r), 2)
  82. 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)
  83.  
  84. # Display the resulting frame
  85. # write the frame
  86. out.write(frame)
  87.  
  88. cv2.imshow("frame", frame)
  89.  
  90. key = cv2.waitKey(1)&0xff
  91. if key == ord("s"):
  92.  
  93. label = tkinter.Label(None, text = "1 = " + res_100 + "\n2 = " + res_200 + "\n3 = " + res_300, font=("Times", "28"))
  94. label.pack()
  95. label.mainloop()
  96.  
  97. cv2.imwrite("capture.png", frame)
  98. #break
  99.  
  100. if key == ord("q"):
  101. break
  102.  
  103. # When everything done, release the capture
  104. cap.release()
  105. out.release()
  106. cv2.destroyAllWindows()
  107.  

上のコードでは、"s"キーが押された時に"tkinter"を使って検出対象の位置情報を表示させているが、
これは一例なので、検出結果から「ここで何かする」って意味になる。
更に別スレッド、別プロセスにすれば動画(画像)の取得を止めること無く「何かする」
が実行出きるので、実際の運用はそう言った使い方になる筈。

0 件のコメント :

コメントを投稿