3 This module contains an image viewer and drawing routines based on OpenCV.
11 """Check if ROI is fully contained in the image.
16 An ndarray of ndim>=2.
17 roi : (int, int, int, int)
18 Region of interest (x, y, width, height) where (x, y) is the top-left
24 Returns true if the ROI is contain in mat.
27 if roi[0] < 0
or roi[0] + roi[2] >= mat.shape[1]:
29 if roi[1] < 0
or roi[1] + roi[3] >= mat.shape[0]:
37 The ROI must be valid, i.e., fully contained in the image.
42 An ndarray of ndim=2 or ndim=3.
43 roi : (int, int, int, int)
44 Region of interest (x, y, width, height) where (x, y) is the top-left
53 sx, ex = roi[0], roi[0] + roi[2]
54 sy, ey = roi[1], roi[1] + roi[3]
56 return mat[sy:ey, sx:ex]
58 return mat[sy:ey, sx:ex, :]
62 """An image viewer with drawing routines and video capture capabilities.
72 Number of milliseconds between frames (1000 / frames per second).
73 window_shape : (int, int)
74 Shape of the window (width, height).
75 caption : Optional[str]
81 Color image of shape (height, width, 3). You may directly manipulate
82 this image to change the view. Otherwise, you may call any of the
83 drawing routines of this class. Internally, the image is treated as
84 beeing in BGR color space.
86 Note that the image is resized to the the image viewers window_shape
87 just prior to visualization. Therefore, you may pass differently sized
88 images and call drawing routines with the appropriate, original point
90 color : (int, int, int)
91 Current BGR color code that applies to all drawing routines.
92 Values are in range [0-255].
93 text_color : (int, int, int)
94 Current BGR text color code that applies to all text rendering
95 routines. Values are in range [0-255].
97 Stroke width in pixels that applies to all drawing routines.
101 def __init__(self, update_ms, window_shape=(640, 480), caption=
"Figure 1"):
121 raise ValueError(
"color must be tuple of 3")
122 self.
_color = tuple(
int(c)
for c
in value)
130 Top left corner of the rectangle (x-axis).
132 Top let corner of the rectangle (y-axis).
134 Width of the rectangle.
136 Height of the rectangle.
137 label : Optional[str]
138 A text label that is placed at the top left corner of the
143 pt2 =
int(x + w),
int(y + h)
145 if label
is not None:
146 text_size = cv2.getTextSize(
147 label, cv2.FONT_HERSHEY_PLAIN, 1, self.
thickness)
149 center = pt1[0] + 5, pt1[1] + 5 + text_size[0][1]
150 pt2 = pt1[0] + 10 + text_size[0][0], pt1[1] + 10 + \
152 cv2.rectangle(self.
image, pt1, pt2, self.
_color, -1)
153 cv2.putText(self.
image, label, center, cv2.FONT_HERSHEY_PLAIN,
156 def circle(self, x, y, radius, label=None):
162 Center of the circle (x-axis).
164 Center of the circle (y-axis).
166 Radius of the circle in pixels.
167 label : Optional[str]
168 A text label that is placed at the center of the circle.
172 roi =
int(x - image_size),
int(y - image_size), \
173 int(2 * image_size),
int(2 * image_size)
178 center = image.shape[1] // 2, image.shape[0] // 2
181 if label
is not None:
183 self.
image, label, center, cv2.FONT_HERSHEY_PLAIN,
187 """Draw 95% confidence ellipse of a 2-D Gaussian distribution.
192 The mean vector of the Gaussian distribution (ndim=1).
193 covariance : array_like
194 The 2x2 covariance matrix of the Gaussian distribution.
195 label : Optional[str]
196 A text label that is placed at the center of the ellipse.
200 vals, vecs = np.linalg.eigh(5.9915 * covariance)
201 indices = vals.argsort()[::-1]
202 vals, vecs = np.sqrt(vals[indices]), vecs[:, indices]
204 center =
int(mean[0] + .5),
int(mean[1] + .5)
205 axes =
int(vals[0] + .5),
int(vals[1] + .5)
206 angle =
int(180. * np.arctan2(vecs[1, 0], vecs[0, 0]) / np.pi)
208 self.
image, center, axes, angle, 0, 360, self.
_color, 2)
209 if label
is not None:
210 cv2.putText(self.
image, label, center, cv2.FONT_HERSHEY_PLAIN,
214 """Draws a text string at a given location.
219 Bottom-left corner of the text in the image (x-axis).
221 Bottom-left corner of the text in the image (y-axis).
223 The text to be drawn.
226 cv2.putText(self.
image, text, (
int(x),
int(y)), cv2.FONT_HERSHEY_PLAIN,
230 """Draw a collection of points.
232 The point size is fixed to 1.
237 The Nx2 array of image locations, where the first dimension is
238 the x-coordinate and the second dimension is the y-coordinate.
239 colors : Optional[ndarray]
240 The Nx3 array of colors (dtype=np.uint8). If None, the current
241 color attribute is used.
242 skip_index_check : Optional[bool]
243 If True, index range checks are skipped. This is faster, but
244 requires all points to lie within the image dimensions.
247 if not skip_index_check:
248 cond1, cond2 = points[:, 0] >= 0, points[:, 0] < 480
249 cond3, cond4 = points[:, 1] >= 0, points[:, 1] < 640
250 indices = np.logical_and.reduce((cond1, cond2, cond3, cond4))
251 points = points[indices, :]
254 self.
_color, len(points)).reshape(3, len(points)).T
255 indices = (points + .5).astype(np.int)
256 self.
image[indices[:, 1], indices[:, 0], :] = colors
260 """ Write images to video file.
264 output_filename : str
267 The OpenCV FOURCC code that defines the video codec (check OpenCV
268 documentation for more information).
269 fps : Optional[float]
270 Frames per second. If None, configured according to current
274 fourcc = cv2.VideoWriter_fourcc(*fourcc_string)
281 """ Disable writing videos.
285 def run(self, update_fun=None):
286 """Start the image viewer.
288 This method blocks until the user requests to close the window.
292 update_fun : Optional[Callable[] -> None]
293 An optional callable that is invoked at each frame. May be used
294 to play an animation/a video sequence.
297 if update_fun
is not None:
313 key = cv2.waitKey(remaining_time)
317 elif key & 255 == 32:
318 print(
"toggeling pause: " +
str(
not is_paused))
319 is_paused =
not is_paused
320 elif key & 255 == 115:
336 """Stop the control loop.
338 After calling this method, the viewer will stop execution before the
339 next frame and hand over control flow to the user.