robotpy-cscore 2027.0.0a3__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of robotpy-cscore might be problematic. Click here for more details.

Files changed (42) hide show
  1. cscore/__init__.py +59 -0
  2. cscore/__main__.py +152 -0
  3. cscore/_cscore.cpython-314-darwin.so +0 -0
  4. cscore/_cscore.pyi +1615 -0
  5. cscore/_init__cscore.py +6 -0
  6. cscore/_logging.py +12 -0
  7. cscore/cscore-casters.pc +8 -0
  8. cscore/cscore-casters.pybind11.json +1 -0
  9. cscore/cscore.pc +10 -0
  10. cscore/cvnp/README.md +11 -0
  11. cscore/cvnp/cvnp.cpp +242 -0
  12. cscore/cvnp/cvnp.h +434 -0
  13. cscore/cvnp/cvnp_synonyms.cpp +70 -0
  14. cscore/cvnp/cvnp_synonyms.h +25 -0
  15. cscore/grip.py +41 -0
  16. cscore/imagewriter.py +146 -0
  17. cscore/py.typed +0 -0
  18. cscore/src/main.cpp +19 -0
  19. cscore/trampolines/cs__AxisCamera.hpp +9 -0
  20. cscore/trampolines/cs__CvSink.hpp +13 -0
  21. cscore/trampolines/cs__CvSource.hpp +13 -0
  22. cscore/trampolines/cs__HttpCamera.hpp +9 -0
  23. cscore/trampolines/cs__ImageSink.hpp +9 -0
  24. cscore/trampolines/cs__ImageSource.hpp +9 -0
  25. cscore/trampolines/cs__MjpegServer.hpp +9 -0
  26. cscore/trampolines/cs__RawEvent.hpp +9 -0
  27. cscore/trampolines/cs__UsbCamera.hpp +9 -0
  28. cscore/trampolines/cs__UsbCameraInfo.hpp +9 -0
  29. cscore/trampolines/cs__VideoCamera.hpp +9 -0
  30. cscore/trampolines/cs__VideoEvent.hpp +9 -0
  31. cscore/trampolines/cs__VideoListener.hpp +9 -0
  32. cscore/trampolines/cs__VideoMode.hpp +9 -0
  33. cscore/trampolines/cs__VideoProperty.hpp +9 -0
  34. cscore/trampolines/cs__VideoSink.hpp +9 -0
  35. cscore/trampolines/cs__VideoSource.hpp +9 -0
  36. cscore/trampolines/frc__CameraServer.hpp +12 -0
  37. cscore/version.py +3 -0
  38. robotpy_cscore-2027.0.0a3.dist-info/METADATA +11 -0
  39. robotpy_cscore-2027.0.0a3.dist-info/RECORD +42 -0
  40. robotpy_cscore-2027.0.0a3.dist-info/WHEEL +4 -0
  41. robotpy_cscore-2027.0.0a3.dist-info/entry_points.txt +3 -0
  42. robotpy_cscore-2027.0.0a3.dist-info/licenses/LICENSE +51 -0
cscore/cvnp/cvnp.h ADDED
@@ -0,0 +1,434 @@
1
+ #pragma once
2
+ #include "cvnp/cvnp_synonyms.h"
3
+
4
+ #include <opencv2/core/core.hpp>
5
+ #include <pybind11/numpy.h>
6
+
7
+ #include <iostream>
8
+ #include <stdexcept>
9
+ #include <vector>
10
+ #include <stdlib.h>
11
+ //
12
+ // Explicit transformers between cv::Mat / cv::Matx and numpy.ndarray, with *possibly*/ shared memory
13
+ // Also see automatic casters in the namespace pybind11:detail below
14
+ //
15
+ namespace cvnp
16
+ {
17
+ //
18
+ // Public interface
19
+ //
20
+
21
+ // For cv::Mat (*with* shared memory)
22
+ pybind11::array mat_to_nparray(const cv::Mat& m);
23
+ cv::Mat nparray_to_mat(pybind11::array& a);
24
+
25
+ // For cv::Matx (*without* shared memory)
26
+ template<typename _Tp, int _rows, int _cols>
27
+ pybind11::array matx_to_nparray(const cv::Matx<_Tp, _rows, _cols>& m);
28
+ template<typename _Tp, int _rows, int _cols>
29
+ void nparray_to_matx(pybind11::array &a, cv::Matx<_Tp, _rows, _cols>& out_matrix);
30
+
31
+
32
+ //
33
+ // Private details and implementations below
34
+ //
35
+ namespace detail
36
+ {
37
+ template<typename _Tp, int _rows, int _cols>
38
+ pybind11::capsule make_capsule_matx(const cv::Matx<_Tp, _rows, _cols>& m)
39
+ {
40
+ return pybind11::capsule(new cv::Matx<_Tp, _rows, _cols>(m)
41
+ , [](void *v) { delete reinterpret_cast<cv::Matx<_Tp, _rows, _cols>*>(v); }
42
+ );
43
+ }
44
+ } // namespace detail
45
+
46
+ template<typename _Tp, int _rows, int _cols>
47
+ pybind11::array matx_to_nparray(const cv::Matx<_Tp, _rows, _cols>& m)
48
+ {
49
+ return pybind11::array(
50
+ pybind11::dtype::of<_Tp>()
51
+ , std::vector<std::size_t> {_rows, _cols}
52
+ , std::vector<std::size_t>{_cols * sizeof(_Tp), sizeof(_Tp)} // Strides
53
+ , m.val
54
+ );
55
+ }
56
+
57
+ template<typename _Tp, int _rows, int _cols>
58
+ void nparray_to_matx(pybind11::array &a, cv::Matx<_Tp, _rows, _cols>& out_matrix)
59
+ {
60
+ size_t mat_size = (size_t)(_rows * _cols);
61
+ if (a.size() != mat_size)
62
+ throw std::runtime_error("Bad size");
63
+
64
+ _Tp* arrayValues = (_Tp*) a.data(0);
65
+ for (size_t i = 0; i < mat_size; ++i)
66
+ out_matrix.val[i] = arrayValues[i];
67
+ }
68
+ } // namespace cvnp
69
+
70
+
71
+
72
+ //
73
+ // 1. Casts with shared memory between {cv::Mat, cv::Matx, cv::Vec} and numpy.ndarray
74
+ //
75
+ // 2. Casts without shared memory between {cv::Size, cv::Point, cv::Point3} and python tuples
76
+ //
77
+ namespace pybind11
78
+ {
79
+ namespace detail
80
+ {
81
+ //
82
+ // Cast between cv::Mat and numpy.ndarray
83
+ // The cast between cv::Mat and numpy.ndarray works
84
+ // - *with* shared memory when going from C++ to Python
85
+ // - *with* shared memory when going from Python to C++
86
+ // any modification to the Matrix size, type, and values is immediately impacted on both sides.
87
+ template<>
88
+ struct type_caster<cv::Mat>
89
+ {
90
+ public:
91
+ PYBIND11_TYPE_CASTER(cv::Mat, _("numpy.ndarray"));
92
+
93
+ /**
94
+ * Conversion part 1 (Python->C++):
95
+ * Return false upon failure.
96
+ * The second argument indicates whether implicit conversions should be applied.
97
+ */
98
+ bool load(handle src, bool)
99
+ {
100
+ if (!isinstance<array>(src))
101
+ return false;
102
+
103
+ auto a = reinterpret_borrow<array>(src);
104
+ auto new_mat = cvnp::nparray_to_mat(a);
105
+ value = new_mat;
106
+ return true;
107
+ }
108
+
109
+ /**
110
+ * Conversion part 2 (C++ -> Python):
111
+ * The second and third arguments are used to indicate the return value policy and parent object
112
+ * (for ``return_value_policy::reference_internal``) and are generally
113
+ * ignored by implicit casters.
114
+ */
115
+ static handle cast(const cv::Mat &m, return_value_policy, handle defval)
116
+ {
117
+ auto a = cvnp::mat_to_nparray(m);
118
+ return a.release();
119
+ }
120
+ };
121
+
122
+ //
123
+ // Cast between cv::Mat_ and numpy.ndarray
124
+ // The cast between cv::Mat_ and numpy.ndarray works
125
+ // - *with* shared memory when going from C++ to Python
126
+ // - *with* shared memory when going from Python to C++
127
+ // any modification to the Matrix size, type, and values is immediately impacted on both sides.
128
+ template<typename _Tp>
129
+ struct type_caster<cv::Mat_<_Tp>>
130
+ {
131
+ using MatTp = cv::Mat_<_Tp>;
132
+ public:
133
+ PYBIND11_TYPE_CASTER(MatTp, _("numpy.ndarray"));
134
+
135
+ /**
136
+ * Conversion part 1 (Python->C++):
137
+ * Return false upon failure.
138
+ * The second argument indicates whether implicit conversions should be applied.
139
+ */
140
+ bool load(handle src, bool)
141
+ {
142
+ if (!isinstance<array>(src))
143
+ return false;
144
+
145
+ auto a = reinterpret_borrow<array>(src);
146
+ auto new_mat = cvnp::nparray_to_mat(a);
147
+ value = new_mat;
148
+ return true;
149
+ }
150
+
151
+ /**
152
+ * Conversion part 2 (C++ -> Python):
153
+ * The second and third arguments are used to indicate the return value policy and parent object
154
+ * (for ``return_value_policy::reference_internal``) and are generally
155
+ * ignored by implicit casters.
156
+ */
157
+ static handle cast(const MatTp &m, return_value_policy, handle defval)
158
+ {
159
+ auto a = cvnp::mat_to_nparray(m);
160
+ return a.release();
161
+ }
162
+ };
163
+
164
+
165
+
166
+ // Cast between cv::Matx<_rows,_cols> (aka Matx33d, Matx21d, etc) and numpy.ndarray
167
+ // *without* shared memory.
168
+ template<typename _Tp, int _rows, int _cols>
169
+ struct type_caster<cv::Matx<_Tp, _rows, _cols> >
170
+ {
171
+ using Matxxx = cv::Matx<_Tp, _rows, _cols>;
172
+
173
+ public:
174
+ PYBIND11_TYPE_CASTER(Matxxx, _("numpy.ndarray"));
175
+
176
+ // Conversion part 1 (Python->C++)
177
+ bool load(handle src, bool)
178
+ {
179
+ if (!isinstance<array>(src))
180
+ return false;
181
+
182
+ auto a = reinterpret_borrow<array>(src);
183
+ cvnp::nparray_to_matx<_Tp, _rows, _cols>(a, value);
184
+ return true;
185
+ }
186
+
187
+ // Conversion part 2 (C++ -> Python)
188
+ static handle cast(const Matxxx &m, return_value_policy, handle defval)
189
+ {
190
+ auto a = cvnp::matx_to_nparray<_Tp, _rows, _cols>(m);
191
+ return a.release();
192
+ }
193
+ };
194
+
195
+
196
+ // Cast between cv::Vec<_rows> and numpy.ndarray
197
+ // *without* shared memory.
198
+ template<typename _Tp, int _rows>
199
+ struct type_caster<cv::Vec<_Tp, _rows> >
200
+ {
201
+ using Vecxxx = cv::Vec<_Tp, _rows>;
202
+
203
+ public:
204
+ PYBIND11_TYPE_CASTER(Vecxxx, _("numpy.ndarray"));
205
+
206
+ // Conversion part 1 (Python->C++)
207
+ bool load(handle src, bool)
208
+ {
209
+ if (!isinstance<array>(src))
210
+ return false;
211
+
212
+ auto a = reinterpret_borrow<array>(src);
213
+ cvnp::nparray_to_matx<_Tp, _rows, 1>(a, value);
214
+ return true;
215
+ }
216
+
217
+ // Conversion part 2 (C++ -> Python)
218
+ static handle cast(const Vecxxx &m, return_value_policy, handle defval)
219
+ {
220
+ auto a = cvnp::matx_to_nparray<_Tp, _rows, 1>(m);
221
+ return a.release();
222
+ }
223
+ };
224
+
225
+
226
+ //
227
+ // Cast between cv::Size and a simple python tuple.
228
+ // No shared memory, you cannot modify the width or the height without
229
+ // transferring the whole Size from C++, or the tuple from python
230
+ //
231
+ template<typename _Tp>
232
+ struct type_caster<cv::Size_<_Tp>>
233
+ {
234
+ using SizeTp = cv::Size_<_Tp>;
235
+
236
+ public:
237
+ PYBIND11_TYPE_CASTER(SizeTp, _("tuple"));
238
+
239
+ // Conversion part 1 (Python->C++, i.e tuple -> Size)
240
+ bool load(handle src, bool)
241
+ {
242
+ if (!isinstance<pybind11::tuple>(src))
243
+ return false;
244
+
245
+ auto tuple = pybind11::reinterpret_borrow<pybind11::tuple>(src);
246
+ if (tuple.size() != 2)
247
+ throw std::invalid_argument("Size should be in a tuple of size 2");
248
+
249
+ SizeTp r;
250
+ r.width = tuple[0].cast<_Tp>();
251
+ r.height = tuple[1].cast<_Tp>();
252
+
253
+ value = r;
254
+ return true;
255
+ }
256
+
257
+ // Conversion part 2 (C++ -> Python, i.e Size -> tuple)
258
+ static handle cast(const SizeTp &value, return_value_policy, handle defval)
259
+ {
260
+ auto result = pybind11::make_tuple(value.width, value.height);
261
+ return result.release();
262
+ }
263
+ };
264
+
265
+
266
+ //
267
+ // Cast between cv::Point and a simple python tuple
268
+ // No shared memory, you cannot modify x or y without
269
+ // transferring the whole Point from C++, or the tuple from python
270
+ //
271
+ template<typename _Tp>
272
+ struct type_caster<cv::Point_<_Tp>>
273
+ {
274
+ using PointTp = cv::Point_<_Tp>;
275
+
276
+ public:
277
+ PYBIND11_TYPE_CASTER(PointTp , _("tuple"));
278
+
279
+ // Conversion part 1 (Python->C++)
280
+ bool load(handle src, bool)
281
+ {
282
+ if (!isinstance<pybind11::tuple>(src))
283
+ return false;
284
+
285
+ auto tuple = pybind11::reinterpret_borrow<pybind11::tuple>(src);
286
+ if (tuple.size() != 2)
287
+ throw std::invalid_argument("Point should be in a tuple of size 2");
288
+
289
+ PointTp r;
290
+ r.x = tuple[0].cast<_Tp>();
291
+ r.y = tuple[1].cast<_Tp>();
292
+
293
+ value = r;
294
+ return true;
295
+ }
296
+
297
+ // Conversion part 2 (C++ -> Python)
298
+ static handle cast(const PointTp &value, return_value_policy, handle defval)
299
+ {
300
+ auto result = pybind11::make_tuple(value.x, value.y);
301
+ return result.release();
302
+ }
303
+ };
304
+
305
+
306
+ //
307
+ // Point3
308
+ // No shared memory
309
+ //
310
+ template<typename _Tp>
311
+ struct type_caster<cv::Point3_<_Tp>>
312
+ {
313
+ using PointTp = cv::Point3_<_Tp>;
314
+
315
+ public:
316
+ PYBIND11_TYPE_CASTER(PointTp , _("tuple"));
317
+
318
+ // Conversion part 1 (Python->C++)
319
+ bool load(handle src, bool)
320
+ {
321
+ if (!isinstance<pybind11::tuple>(src))
322
+ return false;
323
+
324
+ auto tuple = pybind11::reinterpret_borrow<pybind11::tuple>(src);
325
+ if (tuple.size() != 3)
326
+ throw std::invalid_argument("Point3 should be in a tuple of size 3");
327
+
328
+ PointTp r;
329
+ r.x = tuple[0].cast<_Tp>();
330
+ r.y = tuple[1].cast<_Tp>();
331
+ r.z = tuple[2].cast<_Tp>();
332
+
333
+ value = r;
334
+ return true;
335
+ }
336
+
337
+ // Conversion part 2 (C++ -> Python)
338
+ static handle cast(const PointTp &value, return_value_policy, handle defval)
339
+ {
340
+ auto result = pybind11::make_tuple(value.x, value.y, value.z);
341
+ return result.release();
342
+ }
343
+ };
344
+
345
+ //
346
+ // Scalar
347
+ // No shared memory
348
+ //
349
+ template<typename _Tp>
350
+ struct type_caster<cv::Scalar_<_Tp>>
351
+ {
352
+ using ScalarTp = cv::Scalar_<_Tp>;
353
+
354
+ public:
355
+ PYBIND11_TYPE_CASTER(ScalarTp , _("tuple"));
356
+
357
+ // Conversion part 1 (Python->C++)
358
+ bool load(handle src, bool)
359
+ {
360
+ if (!isinstance<pybind11::tuple>(src))
361
+ return false;
362
+
363
+ auto tuple = pybind11::reinterpret_borrow<pybind11::tuple>(src);
364
+ const auto tupleSize = tuple.size();
365
+ if (tupleSize > 4)
366
+ throw std::invalid_argument("Scalar should be a tuple with at most 4 elements. Got " + std::to_string(tupleSize));
367
+
368
+ ScalarTp r;
369
+ if (tupleSize == 1)
370
+ r = ScalarTp(tuple[0].cast<_Tp>());
371
+ else if (tupleSize == 2)
372
+ r = ScalarTp(tuple[0].cast<_Tp>(), tuple[1].cast<_Tp>());
373
+ else if (tupleSize == 3)
374
+ r = ScalarTp(tuple[0].cast<_Tp>(), tuple[1].cast<_Tp>(), tuple[2].cast<_Tp>());
375
+ else if (tupleSize == 4)
376
+ r = ScalarTp(tuple[0].cast<_Tp>(), tuple[1].cast<_Tp>(), tuple[2].cast<_Tp>(), tuple[3].cast<_Tp>());
377
+
378
+ value = r;
379
+ return true;
380
+ }
381
+
382
+ // Conversion part 2 (C++ -> Python)
383
+ static handle cast(const ScalarTp &value, return_value_policy, handle defval)
384
+ {
385
+ auto result = pybind11::make_tuple(value[0], value[1], value[2], value[3]);
386
+ return result.release();
387
+ }
388
+ };
389
+
390
+ //
391
+ // Rect_
392
+ // No shared memory
393
+ //
394
+ template<typename _Tp>
395
+ struct type_caster<cv::Rect_<_Tp>>
396
+ {
397
+ using RectTp = cv::Rect_<_Tp>;
398
+
399
+ public:
400
+ PYBIND11_TYPE_CASTER(RectTp , _("tuple"));
401
+
402
+ // Conversion part 1 (Python->C++)
403
+ bool load(handle src, bool)
404
+ {
405
+ if (!isinstance<pybind11::tuple>(src))
406
+ return false;
407
+
408
+ auto tuple = pybind11::reinterpret_borrow<pybind11::tuple>(src);
409
+ const auto tupleSize = tuple.size();
410
+ if (tupleSize != 4)
411
+ throw std::invalid_argument("Rect should be a tuple with 4 elements. Got " + std::to_string(tupleSize));
412
+
413
+ RectTp r;
414
+ r.x = tuple[0].cast<_Tp>();
415
+ r.y = tuple[1].cast<_Tp>();
416
+ r.width = tuple[2].cast<_Tp>();
417
+ r.height = tuple[3].cast<_Tp>();
418
+
419
+ value = r;
420
+ return true;
421
+ }
422
+
423
+ // Conversion part 2 (C++ -> Python)
424
+ static handle cast(const RectTp &value, return_value_policy, handle defval)
425
+ {
426
+ auto result = pybind11::make_tuple(value.x, value.y, value.width, value.height);
427
+ return result.release();
428
+ }
429
+ };
430
+
431
+
432
+ } // namespace detail
433
+ } // namespace pybind11
434
+
@@ -0,0 +1,70 @@
1
+ #include "cvnp/cvnp_synonyms.h"
2
+ #include <string>
3
+ #include <iostream>
4
+
5
+
6
+ namespace cvnp
7
+ {
8
+ std::vector<TypeSynonyms> sTypeSynonyms
9
+ {
10
+ { CV_8U, "CV_8U", pybind11::format_descriptor<uint8_t>::format(), "np.uint8" },
11
+ { CV_8S, "CV_8S", pybind11::format_descriptor<int8_t>::format(), "np.int8" },
12
+ { CV_16U, "CV_16U", pybind11::format_descriptor<uint16_t>::format(), "np.uint16" },
13
+ { CV_16S, "CV_16S", pybind11::format_descriptor<int16_t>::format(), "np.int16" },
14
+ { CV_32S, "CV_32S", pybind11::format_descriptor<int32_t>::format(), "np.int32" },
15
+ { CV_32F, "CV_32F", pybind11::format_descriptor<float>::format(), "float" },
16
+ { CV_64F, "CV_64F", pybind11::format_descriptor<double>::format(), "np.float64" },
17
+
18
+ // Note: this format needs adaptations
19
+ //#if (CV_MAJOR_VERSION >= 4)
20
+ // { CV_16F, "CV_16F", pybind11::format_descriptor<cv::float16_t>::format() },
21
+ //#endif
22
+ };
23
+
24
+
25
+ static int sColumnWidth = 12;
26
+
27
+ static std::string align_center(const std::string& s)
28
+ {
29
+ int nb_spaces = s.size() < sColumnWidth ? sColumnWidth - s.size() : 0;
30
+ int nb_spaces_left = nb_spaces / 2;
31
+ int nb_spaces_right = sColumnWidth - s.size() - nb_spaces_left;
32
+ if (nb_spaces_right < 0)
33
+ nb_spaces_right = 0;
34
+ return std::string((size_t)nb_spaces_left, ' ') + s + std::string( (size_t)nb_spaces_right, ' ');
35
+ }
36
+ static std::string align_center(const int v)
37
+ {
38
+ return align_center(std::to_string(v));
39
+ }
40
+
41
+ std::string TypeSynonyms::str() const
42
+ {
43
+ return align_center(cv_depth) + align_center(cv_depth_name)
44
+ + align_center(np_format) + align_center(np_format_long);
45
+ }
46
+
47
+
48
+ std::string _print_types_synonyms_str()
49
+ {
50
+ std::string title =
51
+ align_center("cv_depth") + align_center("cv_depth_name")
52
+ + align_center("np_format") + align_center("np_format_long");;
53
+
54
+ std::string r;
55
+ r = title + "\n";
56
+ for (const auto& format: sTypeSynonyms)
57
+ r = r + format.str() + "\n";
58
+ return r;
59
+ }
60
+
61
+ std::vector<TypeSynonyms> list_types_synonyms()
62
+ {
63
+ return sTypeSynonyms;
64
+ }
65
+
66
+ void print_types_synonyms()
67
+ {
68
+ std::cout << _print_types_synonyms_str();
69
+ }
70
+ }
@@ -0,0 +1,25 @@
1
+ #pragma once
2
+ #include <opencv2/core.hpp>
3
+ #include <pybind11/numpy.h>
4
+ #include <string>
5
+ #include <vector>
6
+
7
+
8
+ namespace cvnp
9
+ {
10
+ struct TypeSynonyms
11
+ {
12
+ int cv_depth = -1;
13
+ std::string cv_depth_name;
14
+ std::string np_format;
15
+ std::string np_format_long;
16
+
17
+ pybind11::dtype dtype() { return pybind11::dtype(np_format); }
18
+ std::string str() const;
19
+ };
20
+
21
+ extern std::vector<TypeSynonyms> sTypeSynonyms;
22
+
23
+ std::vector<TypeSynonyms> list_types_synonyms();
24
+ void print_types_synonyms();
25
+ }
cscore/grip.py ADDED
@@ -0,0 +1,41 @@
1
+ import inspect
2
+
3
+ from .cameraserver import CameraServer
4
+
5
+
6
+ def run(grip_pipeline):
7
+ """
8
+ A function that can be used to run python image processing code
9
+ as generated by GRIP
10
+ """
11
+
12
+ if inspect.isclass(grip_pipeline):
13
+ grip_pipeline = grip_pipeline()
14
+
15
+ cs = CameraServer.getInstance()
16
+ cs.enableLogging()
17
+
18
+ cs.startAutomaticCapture()
19
+ cvSink = cs.getVideo()
20
+
21
+ outputStream = None
22
+ img = None
23
+
24
+ while True:
25
+ time, img = cvSink.grabFrame(img)
26
+ if time == 0:
27
+ if outputStream:
28
+ outputStream.notifyError(cvSink.getError())
29
+
30
+ continue
31
+
32
+ # Process it with GRIP
33
+ out_img = grip_pipeline.process(img)
34
+ if out_img is not None:
35
+ try:
36
+ outputStream.putFrame(out_img)
37
+ except AttributeError:
38
+ if outputStream is None:
39
+ outputStream = cs.putVideo("GRIP", img.shape[1], img.shape[0])
40
+ else:
41
+ raise