robotpy-cscore 2027.0.0a3__cp314-cp314-macosx_13_0_x86_64.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.
- cscore/__init__.py +59 -0
- cscore/__main__.py +152 -0
- cscore/_cscore.cpython-314-darwin.so +0 -0
- cscore/_cscore.pyi +1615 -0
- cscore/_init__cscore.py +6 -0
- cscore/_logging.py +12 -0
- cscore/cscore-casters.pc +8 -0
- cscore/cscore-casters.pybind11.json +1 -0
- cscore/cscore.pc +10 -0
- cscore/cvnp/README.md +11 -0
- cscore/cvnp/cvnp.cpp +242 -0
- cscore/cvnp/cvnp.h +434 -0
- cscore/cvnp/cvnp_synonyms.cpp +70 -0
- cscore/cvnp/cvnp_synonyms.h +25 -0
- cscore/grip.py +41 -0
- cscore/imagewriter.py +146 -0
- cscore/py.typed +0 -0
- cscore/src/main.cpp +19 -0
- cscore/trampolines/cs__AxisCamera.hpp +9 -0
- cscore/trampolines/cs__CvSink.hpp +13 -0
- cscore/trampolines/cs__CvSource.hpp +13 -0
- cscore/trampolines/cs__HttpCamera.hpp +9 -0
- cscore/trampolines/cs__ImageSink.hpp +9 -0
- cscore/trampolines/cs__ImageSource.hpp +9 -0
- cscore/trampolines/cs__MjpegServer.hpp +9 -0
- cscore/trampolines/cs__RawEvent.hpp +9 -0
- cscore/trampolines/cs__UsbCamera.hpp +9 -0
- cscore/trampolines/cs__UsbCameraInfo.hpp +9 -0
- cscore/trampolines/cs__VideoCamera.hpp +9 -0
- cscore/trampolines/cs__VideoEvent.hpp +9 -0
- cscore/trampolines/cs__VideoListener.hpp +9 -0
- cscore/trampolines/cs__VideoMode.hpp +9 -0
- cscore/trampolines/cs__VideoProperty.hpp +9 -0
- cscore/trampolines/cs__VideoSink.hpp +9 -0
- cscore/trampolines/cs__VideoSource.hpp +9 -0
- cscore/trampolines/frc__CameraServer.hpp +12 -0
- cscore/version.py +3 -0
- robotpy_cscore-2027.0.0a3.dist-info/METADATA +11 -0
- robotpy_cscore-2027.0.0a3.dist-info/RECORD +42 -0
- robotpy_cscore-2027.0.0a3.dist-info/WHEEL +4 -0
- robotpy_cscore-2027.0.0a3.dist-info/entry_points.txt +3 -0
- robotpy_cscore-2027.0.0a3.dist-info/licenses/LICENSE +51 -0
cscore/_init__cscore.py
ADDED
cscore/_logging.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from ._cscore import _setLogger
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def enableLogging(level: typing.Optional[int] = None):
|
|
8
|
+
"""Enable logging for cscore"""
|
|
9
|
+
if level is None:
|
|
10
|
+
level = logging.DEBUG
|
|
11
|
+
logger = logging.getLogger("cscore")
|
|
12
|
+
_setLogger(lambda lvl, file, line, msg: logger.log(lvl, msg), level)
|
cscore/cscore-casters.pc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"headers": [{"header": "cvnp/cvnp.h", "types": ["cv::Mat"], "default_arg_cast": false}]}
|
cscore/cscore.pc
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# automatically generated by semiwrap.cmd_gen_pkgconf
|
|
2
|
+
prefix=${pcfiledir}
|
|
3
|
+
pkgconf_pypi_initpy=cscore._init__cscore
|
|
4
|
+
inc0=${prefix}/../lib/include
|
|
5
|
+
|
|
6
|
+
Name: cscore
|
|
7
|
+
Description: semiwrap pybind11 module
|
|
8
|
+
Version:
|
|
9
|
+
Cflags: -I${prefix} -I${inc0}
|
|
10
|
+
Requires: wpiutil wpinet ntcore cscore-casters
|
cscore/cvnp/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
This directory comes from https://github.com/pthom/cvnp/tree/master/cvnp
|
|
2
|
+
|
|
3
|
+
The MIT License (MIT)
|
|
4
|
+
|
|
5
|
+
Copyright © 2022 <Pascal Thomet>
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
cscore/cvnp/cvnp.cpp
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#include "cvnp/cvnp.h"
|
|
2
|
+
|
|
3
|
+
// Thanks to Dan Mašek who gave me some inspiration here:
|
|
4
|
+
// https://stackoverflow.com/questions/60949451/how-to-send-a-cvmat-to-python-over-shared-memory
|
|
5
|
+
|
|
6
|
+
namespace cvnp
|
|
7
|
+
{
|
|
8
|
+
|
|
9
|
+
namespace detail
|
|
10
|
+
{
|
|
11
|
+
// #define DEBUG_ALLOCATOR
|
|
12
|
+
|
|
13
|
+
#ifdef DEBUG_ALLOCATOR
|
|
14
|
+
int nbAllocations = 0;
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
namespace py = pybind11;
|
|
18
|
+
|
|
19
|
+
// Translated from cv2_numpy.cpp in OpenCV source code
|
|
20
|
+
class CvnpAllocator : public cv::MatAllocator
|
|
21
|
+
{
|
|
22
|
+
public:
|
|
23
|
+
CvnpAllocator() = default;
|
|
24
|
+
~CvnpAllocator() = default;
|
|
25
|
+
|
|
26
|
+
// Attaches a numpy array object to a cv::Mat
|
|
27
|
+
static void attach_nparray(cv::Mat &m, pybind11::array& a)
|
|
28
|
+
{
|
|
29
|
+
static CvnpAllocator instance;
|
|
30
|
+
|
|
31
|
+
cv::UMatData* u = new cv::UMatData(&instance);
|
|
32
|
+
u->data = u->origdata = (uchar*)a.mutable_data(0);
|
|
33
|
+
u->size = a.size();
|
|
34
|
+
u->userdata = a.inc_ref().ptr();
|
|
35
|
+
u->refcount = 1;
|
|
36
|
+
|
|
37
|
+
#ifdef DEBUG_ALLOCATOR
|
|
38
|
+
++nbAllocations;
|
|
39
|
+
printf("CvnpAllocator::attach_nparray(py::array) nbAllocations=%d\n", nbAllocations);
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
m.u = u;
|
|
43
|
+
m.allocator = &instance;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
cv::UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, cv::AccessFlag flags, cv::UMatUsageFlags usageFlags) const override
|
|
47
|
+
{
|
|
48
|
+
throw py::value_error("CvnpAllocator::allocate \"standard\" should never happen");
|
|
49
|
+
// return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
bool allocate(cv::UMatData* u, cv::AccessFlag accessFlags, cv::UMatUsageFlags usageFlags) const override
|
|
53
|
+
{
|
|
54
|
+
throw py::value_error("CvnpAllocator::allocate \"copy\" should never happen");
|
|
55
|
+
// return stdAllocator->allocate(u, accessFlags, usageFlags);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void deallocate(cv::UMatData* u) const override
|
|
59
|
+
{
|
|
60
|
+
if(!u)
|
|
61
|
+
{
|
|
62
|
+
#ifdef DEBUG_ALLOCATOR
|
|
63
|
+
printf("CvnpAllocator::deallocate() with null ptr!!! nbAllocations=%d\n", nbAllocations);
|
|
64
|
+
#endif
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// This function can be called from anywhere, so need the GIL
|
|
69
|
+
py::gil_scoped_acquire gil;
|
|
70
|
+
assert(u->urefcount >= 0);
|
|
71
|
+
assert(u->refcount >= 0);
|
|
72
|
+
if(u->refcount == 0)
|
|
73
|
+
{
|
|
74
|
+
PyObject* o = (PyObject*)u->userdata;
|
|
75
|
+
Py_XDECREF(o);
|
|
76
|
+
delete u;
|
|
77
|
+
#ifdef DEBUG_ALLOCATOR
|
|
78
|
+
--nbAllocations;
|
|
79
|
+
printf("CvnpAllocator::deallocate() nbAllocations=%d\n", nbAllocations);
|
|
80
|
+
#endif
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
{
|
|
84
|
+
#ifdef DEBUG_ALLOCATOR
|
|
85
|
+
printf("CvnpAllocator::deallocate() - not doing anything since urefcount=%d nbAllocations=%d\n",
|
|
86
|
+
u->urefcount,
|
|
87
|
+
nbAllocations);
|
|
88
|
+
#endif
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
py::dtype determine_np_dtype(int cv_depth)
|
|
94
|
+
{
|
|
95
|
+
for (auto format_synonym : cvnp::sTypeSynonyms)
|
|
96
|
+
if (format_synonym.cv_depth == cv_depth)
|
|
97
|
+
return format_synonym.dtype();
|
|
98
|
+
|
|
99
|
+
std::string msg = "numpy does not support this OpenCV depth: " + std::to_string(cv_depth) + " (in determine_np_dtype)";
|
|
100
|
+
throw std::invalid_argument(msg.c_str());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
int determine_cv_depth(pybind11::dtype dt)
|
|
104
|
+
{
|
|
105
|
+
for (auto format_synonym : cvnp::sTypeSynonyms)
|
|
106
|
+
if (format_synonym.np_format[0] == dt.char_())
|
|
107
|
+
return format_synonym.cv_depth;
|
|
108
|
+
|
|
109
|
+
std::string msg = std::string("OpenCV does not support this numpy format: ") + dt.char_() + " (in determine_np_dtype)";
|
|
110
|
+
throw std::invalid_argument(msg.c_str());
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
int determine_cv_type(const py::array& a, int depth)
|
|
114
|
+
{
|
|
115
|
+
if (a.ndim() < 2)
|
|
116
|
+
throw std::invalid_argument("determine_cv_type needs at least two dimensions");
|
|
117
|
+
if (a.ndim() > 3)
|
|
118
|
+
throw std::invalid_argument("determine_cv_type needs at most three dimensions");
|
|
119
|
+
if (a.ndim() == 2)
|
|
120
|
+
return CV_MAKETYPE(depth, 1);
|
|
121
|
+
//We now know that shape.size() == 3
|
|
122
|
+
return CV_MAKETYPE(depth, a.shape()[2]);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
cv::Size determine_cv_size(const py::array& a)
|
|
126
|
+
{
|
|
127
|
+
if (a.ndim() < 2)
|
|
128
|
+
throw std::invalid_argument("determine_cv_size needs at least two dimensions");
|
|
129
|
+
return cv::Size(static_cast<int>(a.shape()[1]), static_cast<int>(a.shape()[0]));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
std::vector<std::size_t> determine_shape(const cv::Mat& m)
|
|
133
|
+
{
|
|
134
|
+
if (m.channels() == 1) {
|
|
135
|
+
return {
|
|
136
|
+
static_cast<size_t>(m.rows)
|
|
137
|
+
, static_cast<size_t>(m.cols)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
static_cast<size_t>(m.rows)
|
|
142
|
+
, static_cast<size_t>(m.cols)
|
|
143
|
+
, static_cast<size_t>(m.channels())
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
std::vector<std::size_t> determine_strides(const cv::Mat& m) {
|
|
148
|
+
if (m.channels() == 1) {
|
|
149
|
+
return {
|
|
150
|
+
static_cast<size_t>(m.step[0]), // row stride (in bytes)
|
|
151
|
+
static_cast<size_t>(m.step[1]) // column stride (in bytes)
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
static_cast<size_t>(m.step[0]), // row stride (in bytes)
|
|
156
|
+
static_cast<size_t>(m.step[1]), // column stride (in bytes)
|
|
157
|
+
static_cast<size_t>(m.elemSize1()) // channel stride (in bytes)
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
py::capsule make_capsule_mat(const cv::Mat& m)
|
|
162
|
+
{
|
|
163
|
+
return py::capsule(new cv::Mat(m)
|
|
164
|
+
, [](void *v) { delete reinterpret_cast<cv::Mat*>(v); }
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
} // namespace detail
|
|
170
|
+
|
|
171
|
+
pybind11::array mat_to_nparray(const cv::Mat& m)
|
|
172
|
+
{
|
|
173
|
+
return pybind11::array(detail::determine_np_dtype(m.depth())
|
|
174
|
+
, detail::determine_shape(m)
|
|
175
|
+
, detail::determine_strides(m)
|
|
176
|
+
, m.data
|
|
177
|
+
, detail::make_capsule_mat(m)
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
bool is_array_contiguous(const pybind11::array& a)
|
|
183
|
+
{
|
|
184
|
+
return a.flags() & pybind11::array::c_style;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
cv::Mat nparray_to_mat(pybind11::array& a)
|
|
189
|
+
{
|
|
190
|
+
// note: empty arrays are not contiguous, but that's fine. Just
|
|
191
|
+
// make sure to not access mutable_data
|
|
192
|
+
bool is_contiguous = is_array_contiguous(a);
|
|
193
|
+
bool is_not_empty = a.size() != 0;
|
|
194
|
+
if (! is_contiguous && is_not_empty) {
|
|
195
|
+
throw std::invalid_argument("cvnp::nparray_to_mat / Only contiguous numpy arrays are supported. / Please use np.ascontiguousarray() to convert your matrix");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
int depth = detail::determine_cv_depth(a.dtype());
|
|
199
|
+
int type = detail::determine_cv_type(a, depth);
|
|
200
|
+
cv::Size size = detail::determine_cv_size(a);
|
|
201
|
+
cv::Mat m(size, type, is_not_empty ? a.mutable_data(0) : nullptr);
|
|
202
|
+
|
|
203
|
+
if (is_not_empty) {
|
|
204
|
+
detail::CvnpAllocator::attach_nparray(m, a); //, ndims, size, type, step);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return m;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// this version tries to handle strides and sub-matrices
|
|
211
|
+
// this is WIP, currently broken, and not used
|
|
212
|
+
cv::Mat nparray_to_mat_with_strides_broken(pybind11::array& a)
|
|
213
|
+
{
|
|
214
|
+
int depth = detail::determine_cv_depth(a.dtype());
|
|
215
|
+
int type = detail::determine_cv_type(a, depth);
|
|
216
|
+
cv::Size size = detail::determine_cv_size(a);
|
|
217
|
+
|
|
218
|
+
auto buffer_info = a.request();
|
|
219
|
+
|
|
220
|
+
// Get the array strides (convert from pybind11::ssize_t to size_t)
|
|
221
|
+
std::vector<size_t> strides;
|
|
222
|
+
for (auto v : buffer_info.strides)
|
|
223
|
+
strides.push_back(static_cast<size_t>(v));
|
|
224
|
+
|
|
225
|
+
// Get the number of dimensions
|
|
226
|
+
int ndims = static_cast<int>(buffer_info.ndim);
|
|
227
|
+
//if ((ndims != 2) && (ndims != 3))
|
|
228
|
+
// throw std::invalid_argument("nparray_to_mat needs support only 2 or 3 dimension matrices");
|
|
229
|
+
|
|
230
|
+
// Convert the shape (sizes) to a vector of int
|
|
231
|
+
std::vector<int> sizes;
|
|
232
|
+
for (auto v : buffer_info.shape)
|
|
233
|
+
sizes.push_back(static_cast<int>(v));
|
|
234
|
+
|
|
235
|
+
// Create the cv::Mat with the specified strides (steps)
|
|
236
|
+
// We are calling this Mat constructor:
|
|
237
|
+
// Mat(const std::vector<int>& sizes, int type, void* data, const size_t* steps=0)
|
|
238
|
+
cv::Mat m(sizes, type, a.mutable_data(0), strides.data());
|
|
239
|
+
return m;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
} // namespace cvnp
|