@@ -92,18 +92,200 @@ void define_get_item_2d_image(py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>
92
92
return (py::cast (self).template cast <np_array_cf<NpRep> >())[tuple].template cast <py::array_t <NpRep>>();
93
93
}, py::keep_alive<0 , 1 >());
94
94
}
95
+
96
+ std::tuple<int , int , int , int > solveSliceIndices (py::slice slice, unsigned int size)
97
+ {
98
+
99
+ py::handle start = slice.attr (" start" ), end = slice.attr (" stop" ), step = slice.attr (" step" );
100
+
101
+ int startI = 0 , endI = size, stepI = 1 ;
102
+ if (!start.is (py::none ())) {
103
+ startI = py::cast<int >(start);
104
+ if (startI < 0 ) {
105
+ startI = size + startI;
106
+ }
107
+
108
+ if (startI >= size) {
109
+ throw std::runtime_error (" Invalid slice indexing out of array" );
110
+ }
111
+ }
112
+
113
+ if (!end.is (py::none ())) {
114
+ endI = py::cast<int >(end);
115
+ if (endI < 0 ) {
116
+ endI = size + endI;
117
+ }
118
+
119
+ if (endI >= size) {
120
+ throw std::runtime_error (" Invalid slice indexing out of array" );
121
+ }
122
+ }
123
+
124
+ if (!step.is (py::none ())) {
125
+ stepI = py::cast<int >(step);
126
+ if (stepI <= 0 ) {
127
+ throw std::runtime_error (" Slice indexing: negative or zero step not supported!" );
128
+ }
129
+ }
130
+
131
+ if (endI < startI) {
132
+ throw std::runtime_error (" Slice indexing: end index is lower than start index" );
133
+ }
134
+
135
+ int count;
136
+
137
+ if (stepI > endI - startI) {
138
+ count = 1 ;
139
+ }
140
+ else {
141
+ count = (endI - startI) / stepI;
142
+ int endS = startI + t * stepI;
143
+ count = endS <= endI ? t : t - 1 ;
144
+ }
145
+
146
+ return std::make_tuple (startI, endI, stepI, count);
147
+ }
148
+
95
149
/*
96
150
* Image 2D indexing
97
151
*/
98
152
template <typename T, typename NpRep>
99
- void define_set_item_2d_image (py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyClass)
153
+ void define_set_item_2d_image (py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyClass, unsigned int componentsPerPixel )
100
154
{
155
+ pyClass.def (" __setitem__" , [](vpImage<T> &self, std::pair<int , int > pair, const T &value) {
156
+ int i = pair.first , j = pair.second ;
157
+ const int rows = (int )self.getRows (), cols = (int )self.getCols ();
158
+ if (i >= rows || j >= cols || i < -rows || j < -cols) {
159
+ std::stringstream ss;
160
+ ss << " Invalid indexing into a 2D image: got indices " << shape_to_string ({ i, j })
161
+ << " but image has dimensions " << shape_to_string ({ rows, cols });
162
+ throw std::runtime_error (ss.str ());
163
+ }
164
+ if (i < 0 ) {
165
+ i = rows + i;
166
+ }
167
+ if (j < 0 ) {
168
+ j = cols + j;
169
+ }
170
+ self[i][j] = value;
171
+ });
172
+ pyClass.def (" __setitem__" , [](vpImage<T> &self, int i, const T &value) {
173
+ const int rows = (int )self.getRows ();
174
+ if (i >= rows || i < -rows) {
175
+ std::stringstream ss;
176
+ ss << " Invalid indexing into a 2D image: got indices (" << i << " , :)"
177
+ << " but image has dimensions " << shape_to_string ({ rows, self.getCols () });
178
+ throw std::runtime_error (ss.str ());
179
+ }
180
+ if (i < 0 ) {
181
+ i = rows + i;
182
+ }
183
+ T *row = self[i];
184
+ for (int j = 0 ; j < self.getCols (); ++j) {
185
+ row[j] = value;
186
+ }
187
+ });
188
+ pyClass.def (" __setitem__" , [](vpImage<T> &self, py::slice slice, const T &value) {
189
+ int rowStart, rowEnd, rowStep;
190
+ std::tie (rowStart, rowEnd, rowStep) = solveSliceIndices (slice, self.getRows ());
191
+ for (int i = rowStart; i < rowEnd; i += rowStep) {
192
+ T *row = self[i];
193
+ for (int j = 0 ; j < self.getCols (); ++j) {
194
+ row[j] = value;
195
+ }
196
+ }
197
+ });
198
+ pyClass.def (" __setitem__" , [](vpImage<T> &self, std::tuple<py::slice, py::slice> slices, const T &value) {
199
+ py::slice sliceRows, sliceCols;
200
+ int rowStart, rowEnd, rowStep;
201
+ int colStart, colEnd, colStep;
202
+ std::tie (sliceRows, sliceCols) = slices;
203
+ std::tie (rowStart, rowEnd, rowStep) = solveSliceIndices (sliceRows, self.getRows ());
204
+ std::tie (colStart, colEnd, colStep) = solveSliceIndices (sliceCols, self.getCols ());
205
+
206
+ for (int i = rowStart; i < rowEnd; i += rowStep) {
207
+ T *row = self[i];
208
+ for (unsigned int j = colStart; j < colEnd; j += colStep) {
209
+ row[j] = value;
210
+ }
211
+ }
212
+ });
213
+
101
214
215
+ if (componentsPerPixel == 1 ) {
216
+ pyClass.def (" __setitem__" , [](vpImage<T> &self, py::slice sliceRows, py::array<NpRep, py::array::c_style> &values) {
217
+ int rowStart, rowEnd, rowStep;
218
+ std::tie (sliceRows, sliceCols) = slices;
219
+ std::tie (rowStart, rowEnd, rowStep) = solveSliceIndices (sliceRows, self.getRows ());
220
+
221
+ py::buffer_info values_info = values.request ();
222
+
223
+ // Copy the array into each row (same values in each row)
224
+ if (values_info.ndim == 1 ) {
225
+ if (values_info.shape [0 ] != self.getCols ()) {
226
+ throw std::runtime_error (" Number of image columns and NumPy array dimension do not match" );
227
+ }
228
+
229
+ const NpRep *value_ptr = static_cast <NpRep *>(valuesInfo.ptr );
230
+
231
+ for (int i = rowStart; i < rowEnd; i += rowStep) {
232
+ T *row = self[i];
233
+ unsigned int k = 0 ;
234
+ for (unsigned int j = colStart; j < colEnd; j += colStep) {
235
+ row[j] = value_ptr[k++];
236
+ }
237
+ }
238
+ }
239
+ // 2D array to 2D array
240
+ else if (values_info.ndim == 2 ) {
241
+ unsigned int numAssignedRows = 0 ;
242
+ if (values_info.shape [0 ] != numAssignedRows || values_info.shape [1 ] != self.getCols ()) {
243
+ throw std::runtime_error (" Indexing into 2D image: NumPy array has wrong size" );
244
+ }
245
+ const NpRep *value_ptr = static_cast <NpRep *>(valuesInfo.ptr );
246
+
247
+ unsigned int k = 0 ;
248
+ for (int i = rowStart; i < rowEnd; i += rowStep) {
249
+ T *row = self[i];
250
+ for (unsigned int j = colStart; j < colEnd; j += colStep) {
251
+ row[j] = value_ptr[k++];
252
+ }
253
+ }
254
+
255
+ }
256
+ else {
257
+ throw std::runtime_error (" Cannot write into 2D raw type image with multidimensional NumPy array that has more than 2 dimensions" );
258
+ }
259
+ });
260
+
261
+ }
262
+
263
+ // Handle vprgba/vprgbf
264
+ if (componentsPerPixel > 1 ) {
265
+ // pyClass.def("__setitem__", [](vpImage<T> &self, std::tuple<py::slice, py::slice> slices, const T &value) {
266
+ // py::slice sliceRows, sliceCols;
267
+ // int rowStart, rowEnd, rowStep;
268
+ // int colStart, colEnd, colStep;
269
+ // std::tie(sliceRows, sliceCols) = slices;
270
+ // std::tie(rowStart, rowEnd, rowStep) = solveSliceIndices(sliceRows, self.getRows());
271
+ // std::tie(colStart, colEnd, colStep) = solveSliceIndices(sliceCols, self.getCols());
272
+
273
+ // for (int i = rowStart; i < rowEnd; i += rowStep) {
274
+ // T *row = self[i];
275
+ // for (unsigned int j = colStart; j < colEnd; j += colStep) {
276
+ // row[j] = value;
277
+ // }
278
+ // }
279
+ // });
280
+
281
+
282
+ }
102
283
}
103
284
104
- /*
105
- * vpImage
106
- */
285
+
286
+ /*
287
+ * vpImage
288
+ */
107
289
template <typename T>
108
290
typename std::enable_if<std::is_fundamental<T>::value, void >::type
109
291
bindings_vpImage (py::class_<vpImage<T>, std::shared_ptr<vpImage<T>>> &pyImage)
@@ -129,7 +311,7 @@ Construct an image by **copying** a 2D numpy array.
129
311
)doc" , py::arg (" np_array" ));
130
312
131
313
define_get_item_2d_image<T, T>(pyImage);
132
- define_set_item_2d_image<T, T>(pyImage);
314
+ define_set_item_2d_image<T, T>(pyImage, 1 );
133
315
134
316
pyImage.def (" __repr__" , [](const vpImage<T> &self) -> std::string {
135
317
std::stringstream ss;
@@ -175,6 +357,8 @@ where the 4 denotes the red, green, blue and alpha components of the image.
175
357
176
358
)doc" , py::arg (" np_array" ));
177
359
define_get_item_2d_image<T, NpRep>(pyImage);
360
+ define_set_item_2d_image<T, NpRep>(pyImage, sizeof (T) / sizeof (NpRep));
361
+
178
362
179
363
pyImage.def (" __repr__" , [](const vpImage<T> &self) -> std::string {
180
364
std::stringstream ss;
@@ -219,7 +403,9 @@ where the 3 denotes the red, green and blue components of the image.
219
403
:param np_array: The numpy array to copy.
220
404
221
405
)doc" , py::arg (" np_array" ));
406
+
222
407
define_get_item_2d_image<T, NpRep>(pyImage);
408
+ define_set_item_2d_image<T, NpRep>(pyImage, sizeof (T) / sizeof (NpRep));
223
409
224
410
pyImage.def (" __repr__" , [](const vpImage<T> &self) -> std::string {
225
411
std::stringstream ss;
0 commit comments