diff --git a/.gitignore b/.gitignore
index a528a28..f4b73f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
*~
~*
exp_*
+.DS_Store
diff --git a/presentation/ball_tracking.xml b/presentation/ball_tracking.xml
new file mode 100644
index 0000000..2bf4531
--- /dev/null
+++ b/presentation/ball_tracking.xml
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/presentation/striker_flowchart.xml b/presentation/striker_flowchart.xml
new file mode 100644
index 0000000..76b17a0
--- /dev/null
+++ b/presentation/striker_flowchart.xml
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/pykick/colorpicker.py b/pykick/colorpicker.py
index 7b40da6..92a6633 100644
--- a/pykick/colorpicker.py
+++ b/pykick/colorpicker.py
@@ -5,6 +5,7 @@ import json
import argparse
import cv2
+import numpy as np
from .imagereaders import VideoReader, NaoImageReader, PictureReader
from .finders import GoalFinder, BallFinder, FieldFinder
@@ -99,9 +100,12 @@ class Colorpicker(object):
tuple(map(self.settings.get, ('high_h', 'high_s', 'high_v')))
)
- cv2.imshow(self.WINDOW_CAPTURE_NAME, frame)
- cv2.imshow(self.WINDOW_DETECTION_NAME, thr)
- return cv2.waitKey(0 if manual else 1)
+ thr = cv2.cvtColor(thr, cv2.COLOR_GRAY2BGR)
+ resulting = np.concatenate((frame, thr), axis=1)
+
+ cv2.imshow(self.WINDOW_CAPTURE_NAME, resulting)
+ # cv2.imshow(self.WINDOW_DETECTION_NAME, thr)
+ return cv2.waitKey(0 if manual else 50)
def save(self, filename, color):
try:
diff --git a/pykick/detection_demo.py b/pykick/detection_demo.py
index e68ba38..28844ae 100644
--- a/pykick/detection_demo.py
+++ b/pykick/detection_demo.py
@@ -4,6 +4,7 @@ from __future__ import division
import argparse
import cv2
+import numpy as np
from .utils import read_config, imresize
from .imagereaders import NaoImageReader, VideoReader, PictureReader
@@ -118,9 +119,10 @@ if __name__ == '__main__':
ball_frame = ball_finder.draw(ball_frame, ball)
goal_frame = goal_finder.draw(goal_frame, goal)
+ combined = np.concatenate((ball_frame, goal_frame), axis=1)
- cv2.imshow(ball_window, ball_frame)
- cv2.imshow(goal_window, goal_frame)
+ cv2.imshow(ball_window, combined)
+ # cv2.imshow(goal_window, goal_frame)
key = cv2.waitKey(0 if args.manual else 1)
if key == ord('q') or key == 27:
diff --git a/pykick/finders.py b/pykick/finders.py
index 36fe4e4..c7ddf32 100644
--- a/pykick/finders.py
+++ b/pykick/finders.py
@@ -6,7 +6,7 @@ from collections import deque
import cv2
import numpy as np
-from .utils import hsv_mask
+from .utils import hsv_mask, contour_center
class FieldFinder(object):
@@ -51,9 +51,11 @@ class FieldFinder(object):
class GoalFinder(object):
- def __init__(self, hsv_lower, hsv_upper):
+ def __init__(self, hsv_lower, hsv_upper, goal_thr=0.45):
self.hsv_lower = tuple(hsv_lower)
self.hsv_upper = tuple(hsv_upper)
+ self.goal_thr = goal_thr
+ self.last_detection = []
def primary_mask(self, frame):
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
@@ -86,6 +88,7 @@ class GoalFinder(object):
return final_score
def find(self, frame):
+ self.last_detection = []
thr = self.primary_mask(frame)
cnts, _ = cv2.findContours(thr, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
@@ -108,10 +111,11 @@ class GoalFinder(object):
return None
similarities = [self.goal_similarity(cnt) for cnt in good_cnts]
+ self.last_detection = list(zip(good_cnts, similarities))
best = min(similarities)
print('Final goal score:', best)
print()
- if best > 0.45:
+ if best > self.goal_thr:
return None
# Find the contour with the shape closest to that of the goal
goal = good_cnts[similarities.index(best)]
@@ -127,9 +131,27 @@ class GoalFinder(object):
return (l + r) / 2
def draw(self, frame, goal):
+ frame = frame.copy()
+ cv2.putText(frame,
+ 'Upper threshold: ' + '%.2f' % self.goal_thr, (10, 50),
+ cv2.FONT_HERSHEY_DUPLEX, 1, (0, 255, 0))
+ if self.last_detection:
+ cnts = sorted(self.last_detection,
+ key=lambda x: x[1])
+ if cnts[0][1] < self.goal_thr:
+ goal, score = cnts[0]
+ cnts = cnts[1:]
+ for cnt, sim in cnts[1:]:
+ print(sim)
+ cv2.drawContours(frame, (cnt,), -1, (0, 0, 255), 1)
+ cv2.putText(frame, '%.2f' % sim, contour_center(cnt),
+ cv2.FONT_HERSHEY_DUPLEX, 1, (0, 0, 255))
+
if goal is not None:
- frame = frame.copy()
+ print(goal)
cv2.drawContours(frame, (goal,), -1, (0, 255, 0), 2)
+ cv2.putText(frame, '%.2f' % score, contour_center(goal),
+ cv2.FONT_HERSHEY_DUPLEX, 1, (0, 255, 0))
return frame
@@ -179,8 +201,15 @@ class BallFinder(object):
return center, int(radius)
def draw(self, frame, ball):
+ frame = frame.copy()
if ball is not None:
- frame = frame.copy()
center, radius = ball
- cv2.circle(frame, center, radius, (255, 255, 0), 1)
+ cv2.circle(frame, center, radius, (255, 255, 0), 2)
+ for i in range(1, len(self.history)):
+ if self.history[i - 1] is None or self.history[i] is None:
+ continue
+ center_now = self.history[i - 1][0]
+ center_prev = self.history[i][0]
+ thickness = int((64 / (i + 1))**0.5 * 1.25)
+ cv2.line(frame, center_now, center_prev, (0, 0, 255), thickness)
return frame
diff --git a/pykick/nao_defaults.json b/pykick/nao_defaults.json
index d0a12f6..6e4598e 100644
--- a/pykick/nao_defaults.json
+++ b/pykick/nao_defaults.json
@@ -11,25 +11,25 @@
255
]
],
+ "cam": 1,
"goal": [
[
0,
0,
- 89
+ 159
],
[
180,
- 73,
+ 62,
255
]
],
- "fps": 10,
"res": 2,
"ball_min_radius": 0.01,
"field": [
[
- 31,
- 60,
+ 17,
+ 57,
60
],
[
@@ -38,7 +38,7 @@
255
]
],
- "cam": 1,
+ "fps": 10,
"ip": "192.168.0.11",
"port": 9559
}
\ No newline at end of file
diff --git a/pykick/utils.py b/pykick/utils.py
index 5dee47e..73ceb54 100644
--- a/pykick/utils.py
+++ b/pykick/utils.py
@@ -41,6 +41,11 @@ def hsv_mask(hsv, hsv_lower, hsv_upper):
else:
return cv2.inRange(hsv, tuple(hsv_lower), tuple(hsv_upper))
+
+def contour_center(contour):
+ M = cv2.moments(contour)
+ return int(M['m10'] / M['m00']) - 30, int(M['m01'] / M['m00']) + 30
+
class InterruptDelayed(object):
def __enter__(self):