1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000, Intel Corporation, all rights reserved. 14 // Copyright (C) 2013, OpenCV Foundation, all rights reserved. 15 // Third party copyrights are property of their respective owners. 16 // 17 // Redistribution and use in source and binary forms, with or without modification, 18 // are permitted provided that the following conditions are met: 19 // 20 // * Redistribution's of source code must retain the above copyright notice, 21 // this list of conditions and the following disclaimer. 22 // 23 // * Redistribution's in binary form must reproduce the above copyright notice, 24 // this list of conditions and the following disclaimer in the documentation 25 // and/or other materials provided with the distribution. 26 // 27 // * The name of the copyright holders may not be used to endorse or promote products 28 // derived from this software without specific prior written permission. 29 // 30 // This software is provided by the copyright holders and contributors "as is" and 31 // any express or implied warranties, including, but not limited to, the implied 32 // warranties of merchantability and fitness for a particular purpose are disclaimed. 33 // In no event shall the Intel Corporation or contributors be liable for any direct, 34 // indirect, incidental, special, exemplary, or consequential damages 35 // (including, but not limited to, procurement of substitute goods or services; 36 // loss of use, data, or profits; or business interruption) however caused 37 // and on any theory of liability, whether in contract, strict liability, 38 // or tort (including negligence or otherwise) arising in any way out of 39 // the use of this software, even if advised of the possibility of such damage. 40 // 41 //M*/ 42 43 #include "precomp.hpp" 44 45 namespace cv 46 { 47 48 static const uchar* 49 adjustRect( const uchar* src, size_t src_step, int pix_size, 50 Size src_size, Size win_size, 51 Point ip, Rect* pRect ) 52 { 53 Rect rect; 54 55 if( ip.x >= 0 ) 56 { 57 src += ip.x*pix_size; 58 rect.x = 0; 59 } 60 else 61 { 62 rect.x = -ip.x; 63 if( rect.x > win_size.width ) 64 rect.x = win_size.width; 65 } 66 67 if( ip.x < src_size.width - win_size.width ) 68 rect.width = win_size.width; 69 else 70 { 71 rect.width = src_size.width - ip.x - 1; 72 if( rect.width < 0 ) 73 { 74 src += rect.width*pix_size; 75 rect.width = 0; 76 } 77 assert( rect.width <= win_size.width ); 78 } 79 80 if( ip.y >= 0 ) 81 { 82 src += ip.y * src_step; 83 rect.y = 0; 84 } 85 else 86 rect.y = -ip.y; 87 88 if( ip.y < src_size.height - win_size.height ) 89 rect.height = win_size.height; 90 else 91 { 92 rect.height = src_size.height - ip.y - 1; 93 if( rect.height < 0 ) 94 { 95 src += rect.height*src_step; 96 rect.height = 0; 97 } 98 } 99 100 *pRect = rect; 101 return src - rect.x*pix_size; 102 } 103 104 105 enum { SUBPIX_SHIFT=16 }; 106 107 struct scale_fixpt 108 { 109 int operator()(float a) const { return cvRound(a*(1 << SUBPIX_SHIFT)); } 110 }; 111 112 struct cast_8u 113 { 114 uchar operator()(int a) const { return (uchar)((a + (1 << (SUBPIX_SHIFT-1))) >> SUBPIX_SHIFT); } 115 }; 116 117 struct cast_flt_8u 118 { 119 uchar operator()(float a) const { return (uchar)cvRound(a); } 120 }; 121 122 template<typename _Tp> 123 struct nop 124 { 125 _Tp operator()(_Tp a) const { return a; } 126 }; 127 128 129 template<typename _Tp, typename _DTp, typename _WTp, class ScaleOp, class CastOp> 130 void getRectSubPix_Cn_(const _Tp* src, size_t src_step, Size src_size, 131 _DTp* dst, size_t dst_step, Size win_size, Point2f center, int cn ) 132 { 133 ScaleOp scale_op; 134 CastOp cast_op; 135 Point ip; 136 _WTp a11, a12, a21, a22, b1, b2; 137 float a, b; 138 int i, j, c; 139 140 center.x -= (win_size.width-1)*0.5f; 141 center.y -= (win_size.height-1)*0.5f; 142 143 ip.x = cvFloor( center.x ); 144 ip.y = cvFloor( center.y ); 145 146 a = center.x - ip.x; 147 b = center.y - ip.y; 148 a11 = scale_op((1.f-a)*(1.f-b)); 149 a12 = scale_op(a*(1.f-b)); 150 a21 = scale_op((1.f-a)*b); 151 a22 = scale_op(a*b); 152 b1 = scale_op(1.f - b); 153 b2 = scale_op(b); 154 155 src_step /= sizeof(src[0]); 156 dst_step /= sizeof(dst[0]); 157 158 if( 0 <= ip.x && ip.x < src_size.width - win_size.width && 159 0 <= ip.y && ip.y < src_size.height - win_size.height) 160 { 161 // extracted rectangle is totally inside the image 162 src += ip.y * src_step + ip.x*cn; 163 win_size.width *= cn; 164 165 for( i = 0; i < win_size.height; i++, src += src_step, dst += dst_step ) 166 { 167 for( j = 0; j <= win_size.width - 2; j += 2 ) 168 { 169 _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src[j+src_step]*a21 + src[j+src_step+cn]*a22; 170 _WTp s1 = src[j+1]*a11 + src[j+cn+1]*a12 + src[j+src_step+1]*a21 + src[j+src_step+cn+1]*a22; 171 dst[j] = cast_op(s0); 172 dst[j+1] = cast_op(s1); 173 } 174 175 for( ; j < win_size.width; j++ ) 176 { 177 _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src[j+src_step]*a21 + src[j+src_step+cn]*a22; 178 dst[j] = cast_op(s0); 179 } 180 } 181 } 182 else 183 { 184 Rect r; 185 src = (const _Tp*)adjustRect( (const uchar*)src, src_step*sizeof(*src), 186 sizeof(*src)*cn, src_size, win_size, ip, &r); 187 188 for( i = 0; i < win_size.height; i++, dst += dst_step ) 189 { 190 const _Tp *src2 = src + src_step; 191 _WTp s0; 192 193 if( i < r.y || i >= r.height ) 194 src2 -= src_step; 195 196 for( c = 0; c < cn; c++ ) 197 { 198 s0 = src[r.x*cn + c]*b1 + src2[r.x*cn + c]*b2; 199 for( j = 0; j < r.x; j++ ) 200 dst[j*cn + c] = cast_op(s0); 201 s0 = src[r.width*cn + c]*b1 + src2[r.width*cn + c]*b2; 202 for( j = r.width; j < win_size.width; j++ ) 203 dst[j*cn + c] = cast_op(s0); 204 } 205 206 for( j = r.x*cn; j < r.width*cn; j++ ) 207 { 208 s0 = src[j]*a11 + src[j+cn]*a12 + src2[j]*a21 + src2[j+cn]*a22; 209 dst[j] = cast_op(s0); 210 } 211 212 if( i < r.height ) 213 src = src2; 214 } 215 } 216 } 217 218 219 static void getRectSubPix_8u32f 220 ( const uchar* src, size_t src_step, Size src_size, 221 float* dst, size_t dst_step, Size win_size, Point2f center0, int cn ) 222 { 223 Point2f center = center0; 224 Point ip; 225 226 center.x -= (win_size.width-1)*0.5f; 227 center.y -= (win_size.height-1)*0.5f; 228 229 ip.x = cvFloor( center.x ); 230 ip.y = cvFloor( center.y ); 231 232 if( cn == 1 && 233 0 <= ip.x && ip.x + win_size.width < src_size.width && 234 0 <= ip.y && ip.y + win_size.height < src_size.height && 235 win_size.width > 0 && win_size.height > 0 ) 236 { 237 float a = center.x - ip.x; 238 float b = center.y - ip.y; 239 a = MAX(a,0.0001f); 240 float a12 = a*(1.f-b); 241 float a22 = a*b; 242 float b1 = 1.f - b; 243 float b2 = b; 244 double s = (1. - a)/a; 245 246 src_step /= sizeof(src[0]); 247 dst_step /= sizeof(dst[0]); 248 249 // extracted rectangle is totally inside the image 250 src += ip.y * src_step + ip.x; 251 252 for( ; win_size.height--; src += src_step, dst += dst_step ) 253 { 254 float prev = (1 - a)*(b1*src[0] + b2*src[src_step]); 255 for( int j = 0; j < win_size.width; j++ ) 256 { 257 float t = a12*src[j+1] + a22*src[j+1+src_step]; 258 dst[j] = prev + t; 259 prev = (float)(t*s); 260 } 261 } 262 } 263 else 264 { 265 getRectSubPix_Cn_<uchar, float, float, nop<float>, nop<float> > 266 (src, src_step, src_size, dst, dst_step, win_size, center0, cn ); 267 } 268 } 269 270 static void 271 getQuadrangleSubPix_8u32f_CnR( const uchar* src, size_t src_step, Size src_size, 272 float* dst, size_t dst_step, Size win_size, 273 const double *matrix, int cn ) 274 { 275 int x, y, k; 276 double A11 = matrix[0], A12 = matrix[1], A13 = matrix[2]; 277 double A21 = matrix[3], A22 = matrix[4], A23 = matrix[5]; 278 279 src_step /= sizeof(src[0]); 280 dst_step /= sizeof(dst[0]); 281 282 for( y = 0; y < win_size.height; y++, dst += dst_step ) 283 { 284 double xs = A12*y + A13; 285 double ys = A22*y + A23; 286 double xe = A11*(win_size.width-1) + A12*y + A13; 287 double ye = A21*(win_size.width-1) + A22*y + A23; 288 289 if( (unsigned)(cvFloor(xs)-1) < (unsigned)(src_size.width - 3) && 290 (unsigned)(cvFloor(ys)-1) < (unsigned)(src_size.height - 3) && 291 (unsigned)(cvFloor(xe)-1) < (unsigned)(src_size.width - 3) && 292 (unsigned)(cvFloor(ye)-1) < (unsigned)(src_size.height - 3)) 293 { 294 for( x = 0; x < win_size.width; x++ ) 295 { 296 int ixs = cvFloor( xs ); 297 int iys = cvFloor( ys ); 298 const uchar *ptr = src + src_step*iys; 299 float a = (float)(xs - ixs), b = (float)(ys - iys), a1 = 1.f - a, b1 = 1.f - b; 300 float w00 = a1*b1, w01 = a*b1, w10 = a1*b, w11 = a*b; 301 xs += A11; 302 ys += A21; 303 304 if( cn == 1 ) 305 { 306 ptr += ixs; 307 dst[x] = ptr[0]*w00 + ptr[1]*w01 + ptr[src_step]*w10 + ptr[src_step+1]*w11; 308 } 309 else if( cn == 3 ) 310 { 311 ptr += ixs*3; 312 float t0 = ptr[0]*w00 + ptr[3]*w01 + ptr[src_step]*w10 + ptr[src_step+3]*w11; 313 float t1 = ptr[1]*w00 + ptr[4]*w01 + ptr[src_step+1]*w10 + ptr[src_step+4]*w11; 314 float t2 = ptr[2]*w00 + ptr[5]*w01 + ptr[src_step+2]*w10 + ptr[src_step+5]*w11; 315 316 dst[x*3] = t0; 317 dst[x*3+1] = t1; 318 dst[x*3+2] = t2; 319 } 320 else 321 { 322 ptr += ixs*cn; 323 for( k = 0; k < cn; k++ ) 324 dst[x*cn+k] = ptr[k]*w00 + ptr[k+cn]*w01 + 325 ptr[src_step+k]*w10 + ptr[src_step+k+cn]*w11; 326 } 327 } 328 } 329 else 330 { 331 for( x = 0; x < win_size.width; x++ ) 332 { 333 int ixs = cvFloor( xs ), iys = cvFloor( ys ); 334 float a = (float)(xs - ixs), b = (float)(ys - iys), a1 = 1.f - a, b1 = 1.f - b; 335 float w00 = a1*b1, w01 = a*b1, w10 = a1*b, w11 = a*b; 336 const uchar *ptr0, *ptr1; 337 xs += A11; ys += A21; 338 339 if( (unsigned)iys < (unsigned)(src_size.height-1) ) 340 ptr0 = src + src_step*iys, ptr1 = ptr0 + src_step; 341 else 342 ptr0 = ptr1 = src + (iys < 0 ? 0 : src_size.height-1)*src_step; 343 344 if( (unsigned)ixs < (unsigned)(src_size.width-1) ) 345 { 346 ptr0 += ixs*cn; ptr1 += ixs*cn; 347 for( k = 0; k < cn; k++ ) 348 dst[x*cn + k] = ptr0[k]*w00 + ptr0[k+cn]*w01 + ptr1[k]*w10 + ptr1[k+cn]*w11; 349 } 350 else 351 { 352 ixs = ixs < 0 ? 0 : src_size.width - 1; 353 ptr0 += ixs*cn; ptr1 += ixs*cn; 354 for( k = 0; k < cn; k++ ) 355 dst[x*cn + k] = ptr0[k]*b1 + ptr1[k]*b; 356 } 357 } 358 } 359 } 360 } 361 362 } 363 364 365 void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, 366 OutputArray _patch, int patchType ) 367 { 368 Mat image = _image.getMat(); 369 int depth = image.depth(), cn = image.channels(); 370 int ddepth = patchType < 0 ? depth : CV_MAT_DEPTH(patchType); 371 372 CV_Assert( cn == 1 || cn == 3 ); 373 374 _patch.create(patchSize, CV_MAKETYPE(ddepth, cn)); 375 Mat patch = _patch.getMat(); 376 377 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) 378 CV_IPP_CHECK() 379 { 380 typedef IppStatus (CV_STDCALL *ippiGetRectSubPixFunc)( const void* src, int src_step, 381 IppiSize src_size, void* dst, 382 int dst_step, IppiSize win_size, 383 IppiPoint_32f center, 384 IppiPoint* minpt, IppiPoint* maxpt ); 385 386 IppiPoint minpt={0,0}, maxpt={0,0}; 387 IppiPoint_32f icenter = {center.x, center.y}; 388 IppiSize src_size={image.cols, image.rows}, win_size={patch.cols, patch.rows}; 389 int srctype = image.type(); 390 ippiGetRectSubPixFunc ippfunc = 391 srctype == CV_8UC1 && ddepth == CV_8U ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_8u_C1R : 392 srctype == CV_8UC1 && ddepth == CV_32F ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_8u32f_C1R : 393 srctype == CV_32FC1 && ddepth == CV_32F ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_32f_C1R : 0; 394 395 if( ippfunc) 396 { 397 if (ippfunc(image.ptr(), (int)image.step, src_size, patch.ptr(), 398 (int)patch.step, win_size, icenter, &minpt, &maxpt) >= 0 ) 399 { 400 CV_IMPL_ADD(CV_IMPL_IPP); 401 return; 402 } 403 setIppErrorStatus(); 404 } 405 } 406 #endif 407 408 if( depth == CV_8U && ddepth == CV_8U ) 409 getRectSubPix_Cn_<uchar, uchar, int, scale_fixpt, cast_8u> 410 (image.ptr(), image.step, image.size(), patch.ptr(), patch.step, patch.size(), center, cn); 411 else if( depth == CV_8U && ddepth == CV_32F ) 412 getRectSubPix_8u32f 413 (image.ptr(), image.step, image.size(), patch.ptr<float>(), patch.step, patch.size(), center, cn); 414 else if( depth == CV_32F && ddepth == CV_32F ) 415 getRectSubPix_Cn_<float, float, float, nop<float>, nop<float> > 416 (image.ptr<float>(), image.step, image.size(), patch.ptr<float>(), patch.step, patch.size(), center, cn); 417 else 418 CV_Error( CV_StsUnsupportedFormat, "Unsupported combination of input and output formats"); 419 } 420 421 422 CV_IMPL void 423 cvGetRectSubPix( const void* srcarr, void* dstarr, CvPoint2D32f center ) 424 { 425 cv::Mat src = cv::cvarrToMat(srcarr); 426 const cv::Mat dst = cv::cvarrToMat(dstarr); 427 CV_Assert( src.channels() == dst.channels() ); 428 429 cv::getRectSubPix(src, dst.size(), center, dst, dst.type()); 430 } 431 432 433 CV_IMPL void 434 cvGetQuadrangleSubPix( const void* srcarr, void* dstarr, const CvMat* mat ) 435 { 436 const cv::Mat src = cv::cvarrToMat(srcarr), m = cv::cvarrToMat(mat); 437 cv::Mat dst = cv::cvarrToMat(dstarr); 438 439 CV_Assert( src.channels() == dst.channels() ); 440 441 cv::Size win_size = dst.size(); 442 double matrix[6]; 443 cv::Mat M(2, 3, CV_64F, matrix); 444 m.convertTo(M, CV_64F); 445 double dx = (win_size.width - 1)*0.5; 446 double dy = (win_size.height - 1)*0.5; 447 matrix[2] -= matrix[0]*dx + matrix[1]*dy; 448 matrix[5] -= matrix[3]*dx + matrix[4]*dy; 449 450 if( src.depth() == CV_8U && dst.depth() == CV_32F ) 451 cv::getQuadrangleSubPix_8u32f_CnR( src.ptr(), src.step, src.size(), 452 dst.ptr<float>(), dst.step, dst.size(), 453 matrix, src.channels()); 454 else 455 { 456 CV_Assert( src.depth() == dst.depth() ); 457 cv::warpAffine(src, dst, M, dst.size(), 458 cv::INTER_LINEAR + cv::WARP_INVERSE_MAP, 459 cv::BORDER_REPLICATE); 460 } 461 } 462 463 464 CV_IMPL int 465 cvSampleLine( const void* _img, CvPoint pt1, CvPoint pt2, 466 void* _buffer, int connectivity ) 467 { 468 cv::Mat img = cv::cvarrToMat(_img); 469 cv::LineIterator li(img, pt1, pt2, connectivity, false); 470 uchar* buffer = (uchar*)_buffer; 471 size_t pixsize = img.elemSize(); 472 473 if( !buffer ) 474 CV_Error( CV_StsNullPtr, "" ); 475 476 for( int i = 0; i < li.count; i++, ++li ) 477 { 478 for( size_t k = 0; k < pixsize; k++ ) 479 *buffer++ = li.ptr[k]; 480 } 481 482 return li.count; 483 } 484 485 486 /* End of file. */ 487