@@ -175,107 +175,144 @@ void warpPerspective(InputArray _src, OutputArray _dst, InputArray _M0, Size dsi
175
175
FcvWarpPerspectiveLoop_Invoker (src, tmp, dst, tmp, matrix, fcvInterpolation, fcvBorder, fcvBorderValue), nStripes);
176
176
}
177
177
178
- void warpAffine (InputArray _src, OutputArray _dst, InputArray _M, Size dsize, int interpolation, int borderValue)
178
+ void warpAffine (InputArray _src, OutputArray _dst, InputArray _M, Size dsize,
179
+ int interpolation, int borderValue)
179
180
{
180
181
INITIALIZATION_CHECK;
181
- CV_Assert (!_src.empty () && _src. type () == CV_8UC1 );
182
+ CV_Assert (!_src.empty ());
182
183
CV_Assert (!_M.empty ());
183
184
184
185
Mat src = _src.getMat ();
185
- _dst.create (dsize, src.type ());
186
- Mat dst = _dst.getMat ();
187
186
Mat M = _M.getMat ();
188
187
189
- fcvStatus status ;
190
- fcvInterpolationType fcvInterpolation ;
188
+ CV_CheckEQ (M. rows , 2 , " Affine Matrix must have 2 rows " ) ;
189
+ CV_Check (M. cols , M. cols == 2 || M. cols == 3 , " Affine Matrix must be 2x2 or 2x3 " ) ;
191
190
192
- float32_t affineMatrix[6 ] = { M.at <float >(0 , 0 ), M.at <float >(0 , 1 ), M.at <float >(0 , 2 ),
193
- M.at <float >(1 , 0 ), M.at <float >(1 , 1 ), M.at <float >(1 , 2 ) };
194
-
195
- switch (interpolation)
191
+ if (M.rows == 2 && M.cols == 2 )
196
192
{
197
- case cv::InterpolationFlags::INTER_NEAREST:
198
- {
199
- fcvInterpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
200
- break ;
201
- }
202
- case cv::InterpolationFlags::INTER_LINEAR:
193
+ CV_CheckTypeEQ (src.type (), CV_8UC1, " 2x2 matrix transformation only supports CV_8UC1" );
194
+
195
+ // Check if src is a ROI
196
+ Size wholeSize;
197
+ Point ofs;
198
+ src.locateROI (wholeSize, ofs);
199
+ bool isROI = (wholeSize.width > src.cols || wholeSize.height > src.rows );
200
+
201
+ Mat fullImage;
202
+ Point2f center;
203
+
204
+ if (isROI)
203
205
{
204
- fcvInterpolation = FASTCV_INTERPOLATION_TYPE_BILINEAR;
205
- break ;
206
+ center.x = ofs.x + src.cols / 2 .0f ;
207
+ center.y = ofs.y + src.rows / 2 .0f ;
208
+
209
+ CV_Check (center.x , center.x >= 0 && center.x < wholeSize.width , " ROI center X is outside full image bounds" );
210
+ CV_Check (center.y , center.y >= 0 && center.y < wholeSize.height , " ROI center Y is outside full image bounds" );
211
+
212
+ size_t offset = ofs.y * src.step + ofs.x * src.elemSize ();
213
+ fullImage = Mat (wholeSize, src.type (), src.data - offset);
206
214
}
207
- case cv::InterpolationFlags::INTER_AREA:
215
+ else
208
216
{
209
- fcvInterpolation = FASTCV_INTERPOLATION_TYPE_AREA;
210
- break ;
217
+ // Use src as is, center at image center
218
+ fullImage = src;
219
+ center.x = src.cols / 2 .0f ;
220
+ center.y = src.rows / 2 .0f ;
221
+
222
+ CV_LOG_WARNING (NULL , " 2x2 matrix with non-ROI input. Using image center for patch extraction." );
211
223
}
212
- default :
213
- CV_Error (cv::Error::StsBadArg, " Unsupported interpolation type" );
214
- }
215
224
216
- status = fcvTransformAffineClippedu8_v3 ((const uint8_t *)src.data , src.cols , src.rows , src.step , affineMatrix,
217
- (uint8_t *)dst.data , dst.cols , dst.rows , dst.step , NULL , fcvInterpolation, FASTCV_BORDER_CONSTANT, borderValue);
225
+ float affineMatrix[4 ] = {
226
+ M.at <float >(0 , 0 ), M.at <float >(0 , 1 ),
227
+ M.at <float >(1 , 0 ), M.at <float >(1 , 1 )};
218
228
219
- if (status != FASTCV_SUCCESS)
220
- {
221
- std::string s = fcvStatusStrings.count (status) ? fcvStatusStrings.at (status) : " unknown" ;
222
- CV_Error ( cv::Error::StsInternal, " FastCV error: " + s);
223
- }
224
- }
225
-
226
- void warpAffine3Channel (InputArray _src, OutputArray _dst, InputArray _M, Size dsize, OutputArray _dstBorder)
227
- {
228
- INITIALIZATION_CHECK;
229
+ float position[2 ] = {center.x , center.y };
229
230
230
- CV_Assert (!_src.empty () && _src.type () == CV_8UC3);
231
- CV_Assert (!_M.empty ());
231
+ _dst.create (dsize, src.type ());
232
+ Mat dst = _dst.getMat ();
233
+ dst.step = dst.cols * src.elemSize ();
232
234
235
+ int status = fcvTransformAffineu8_v2 (
236
+ (const uint8_t *)fullImage.data ,
237
+ fullImage.cols , fullImage.rows , fullImage.step ,
238
+ position,
239
+ affineMatrix,
240
+ (uint8_t *)dst.data ,
241
+ dst.cols , dst.rows , dst.step );
233
242
234
- Mat src = _src. getMat ();
235
- _dst. create (dsize, src. type ());
236
- Mat dst = _dst. getMat ( );
237
- Mat M = _M. getMat ();
243
+ if (status != 0 )
244
+ {
245
+ CV_Error (Error::StsInternal, " FastCV patch extraction failed " );
246
+ }
238
247
239
- _dstBorder. create ( 1 , dsize. height * 2 , CV_32S) ;
240
- Mat dstBorder = _dstBorder. getMat ();
248
+ return ;
249
+ }
241
250
242
- float32_t affineMatrix[6 ] = { M.at <float >(0 , 0 ), M.at <float >(0 , 1 ), M.at <float >(0 , 2 ),
243
- M.at <float >(1 , 0 ), M.at <float >(1 , 1 ), M.at <float >(1 , 2 ) };
251
+ // Validate 2x3 matrix for standard transformation
252
+ CV_CheckEQ (M.cols , 3 , " Matrix must be 2x3 for standard affine transformation" );
253
+ CV_Check (src.type (), src.type () == CV_8UC1 || src.type () == CV_8UC3, " Standard transformation supports CV_8UC1 or CV_8UC3" );
244
254
255
+ float32_t affineMatrix[6 ] = {
256
+ M.at <float >(0 , 0 ), M.at <float >(0 , 1 ), M.at <float >(0 , 2 ),
257
+ M.at <float >(1 , 0 ), M.at <float >(1 , 1 ), M.at <float >(1 , 2 )};
245
258
246
- fcv3ChannelTransformAffineClippedBCu8 ((const uint8_t *)src.data , src.cols , src.rows , src.step [0 ],
247
- affineMatrix, (uint8_t *)dst.data , dst.cols , dst.rows , dst.step [0 ], (uint32_t *)dstBorder.data );
248
- }
259
+ _dst.create (dsize, src.type ());
260
+ Mat dst = _dst.getMat ();
249
261
250
- void warpAffineROI (InputArray _src, const cv::Point2f& position, InputArray _affine, OutputArray _patch, Size patchSize)
251
- {
252
- INITIALIZATION_CHECK;
262
+ if (src.channels () == 1 )
263
+ {
264
+ fcvStatus status;
265
+ fcvInterpolationType fcvInterpolation;
253
266
254
- cv::Mat src = _src.getMat ();
255
- cv::Mat affine = _affine.getMat ();
267
+ switch (interpolation)
268
+ {
269
+ case cv::InterpolationFlags::INTER_NEAREST:
270
+ fcvInterpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
271
+ break ;
272
+ case cv::InterpolationFlags::INTER_LINEAR:
273
+ fcvInterpolation = FASTCV_INTERPOLATION_TYPE_BILINEAR;
274
+ break ;
275
+ case cv::InterpolationFlags::INTER_AREA:
276
+ fcvInterpolation = FASTCV_INTERPOLATION_TYPE_AREA;
277
+ break ;
278
+ default :
279
+ CV_Error (cv::Error::StsBadArg, " Unsupported interpolation type" );
280
+ }
256
281
257
- CV_Assert (!src.empty () && src.type () == CV_8UC1);
258
- CV_Assert (!affine.empty () && affine.type () == CV_32FC1);
282
+ status = fcvTransformAffineClippedu8_v3 (
283
+ (const uint8_t *)src.data , src.cols , src.rows , src.step ,
284
+ affineMatrix,
285
+ (uint8_t *)dst.data , dst.cols , dst.rows , dst.step ,
286
+ NULL ,
287
+ fcvInterpolation,
288
+ FASTCV_BORDER_CONSTANT,
289
+ borderValue);
259
290
260
- float affineMatrix[4 ];
261
- for (int i = 0 ; i < 4 ; i++) {
262
- affineMatrix[i] = affine.at <float >(i / 2 , i % 2 );
291
+ if (status != FASTCV_SUCCESS)
292
+ {
293
+ std::string s = fcvStatusStrings.count (status) ? fcvStatusStrings.at (status) : " unknown" ;
294
+ CV_Error (cv::Error::StsInternal, " FastCV error: " + s);
295
+ }
263
296
}
297
+ else if (src.channels () == 3 )
298
+ {
299
+ CV_LOG_INFO (NULL , " warpAffine: 3-channel images use bicubic interpolation internally." );
264
300
265
- _patch.create (patchSize, src.type ());
266
- cv::Mat patch = _patch.getMat ();
267
-
268
- float positionArray[2 ];
269
- positionArray[0 ] = position.x ;
270
- positionArray[1 ] = position.y ;
271
-
272
- // Perform affine transformation
273
- int status = fcvTransformAffineu8_v2 ((const uint8_t *)src.data , src.cols , src.rows , src.step , positionArray,
274
- affineMatrix, (uint8_t *)patch.data , patch.cols , patch.rows , patch.step );
301
+ std::vector<uint32_t > dstBorder;
302
+ try
303
+ {
304
+ dstBorder.resize (dsize.height * 2 );
305
+ }
306
+ catch (const std::bad_alloc &)
307
+ {
308
+ CV_Error (Error::StsNoMem, " Failed to allocate border array" );
309
+ }
275
310
276
- if (status != 0 )
277
- {
278
- CV_Error (cv::Error::StsInternal, " FastCV error: General failure" );
311
+ fcv3ChannelTransformAffineClippedBCu8 (
312
+ (const uint8_t *)src.data , src.cols , src.rows , src.step [0 ],
313
+ affineMatrix,
314
+ (uint8_t *)dst.data , dst.cols , dst.rows , dst.step [0 ],
315
+ dstBorder.data ());
279
316
}
280
317
}
281
318
0 commit comments