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-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009, Willow Garage Inc., 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 //============================================================================== 46 // 47 // Error handling helpers 48 // 49 //============================================================================== 50 51 namespace 52 { 53 #define error_entry(entry) { entry, #entry } 54 55 struct ErrorEntry 56 { 57 int code; 58 const char* str; 59 }; 60 61 struct ErrorEntryComparer 62 { 63 int code; 64 ErrorEntryComparer(int code_) : code(code_) {} 65 bool operator()(const ErrorEntry& e) const { return e.code == code; } 66 }; 67 68 ////////////////////////////////////////////////////////////////////////// 69 // NCV errors 70 71 const ErrorEntry ncv_errors [] = 72 { 73 error_entry( NCV_SUCCESS ), 74 error_entry( NCV_UNKNOWN_ERROR ), 75 error_entry( NCV_CUDA_ERROR ), 76 error_entry( NCV_NPP_ERROR ), 77 error_entry( NCV_FILE_ERROR ), 78 error_entry( NCV_NULL_PTR ), 79 error_entry( NCV_INCONSISTENT_INPUT ), 80 error_entry( NCV_TEXTURE_BIND_ERROR ), 81 error_entry( NCV_DIMENSIONS_INVALID ), 82 error_entry( NCV_INVALID_ROI ), 83 error_entry( NCV_INVALID_STEP ), 84 error_entry( NCV_INVALID_SCALE ), 85 error_entry( NCV_INVALID_SCALE ), 86 error_entry( NCV_ALLOCATOR_NOT_INITIALIZED ), 87 error_entry( NCV_ALLOCATOR_BAD_ALLOC ), 88 error_entry( NCV_ALLOCATOR_BAD_DEALLOC ), 89 error_entry( NCV_ALLOCATOR_INSUFFICIENT_CAPACITY ), 90 error_entry( NCV_ALLOCATOR_DEALLOC_ORDER ), 91 error_entry( NCV_ALLOCATOR_BAD_REUSE ), 92 error_entry( NCV_MEM_COPY_ERROR ), 93 error_entry( NCV_MEM_RESIDENCE_ERROR ), 94 error_entry( NCV_MEM_INSUFFICIENT_CAPACITY ), 95 error_entry( NCV_HAAR_INVALID_PIXEL_STEP ), 96 error_entry( NCV_HAAR_TOO_MANY_FEATURES_IN_CLASSIFIER ), 97 error_entry( NCV_HAAR_TOO_MANY_FEATURES_IN_CASCADE ), 98 error_entry( NCV_HAAR_TOO_LARGE_FEATURES ), 99 error_entry( NCV_HAAR_XML_LOADING_EXCEPTION ), 100 error_entry( NCV_NOIMPL_HAAR_TILTED_FEATURES ), 101 error_entry( NCV_WARNING_HAAR_DETECTIONS_VECTOR_OVERFLOW ), 102 error_entry( NPPST_SUCCESS ), 103 error_entry( NPPST_ERROR ), 104 error_entry( NPPST_CUDA_KERNEL_EXECUTION_ERROR ), 105 error_entry( NPPST_NULL_POINTER_ERROR ), 106 error_entry( NPPST_TEXTURE_BIND_ERROR ), 107 error_entry( NPPST_MEMCPY_ERROR ), 108 error_entry( NPPST_MEM_ALLOC_ERR ), 109 error_entry( NPPST_MEMFREE_ERR ), 110 error_entry( NPPST_INVALID_ROI ), 111 error_entry( NPPST_INVALID_STEP ), 112 error_entry( NPPST_INVALID_SCALE ), 113 error_entry( NPPST_MEM_INSUFFICIENT_BUFFER ), 114 error_entry( NPPST_MEM_RESIDENCE_ERROR ), 115 error_entry( NPPST_MEM_INTERNAL_ERROR ) 116 }; 117 118 const size_t ncv_error_num = sizeof(ncv_errors) / sizeof(ncv_errors[0]); 119 } 120 121 cv::String cv::cuda::getNcvErrorMessage(int code) 122 { 123 size_t idx = std::find_if(ncv_errors, ncv_errors + ncv_error_num, ErrorEntryComparer(code)) - ncv_errors; 124 125 const char* msg = (idx != ncv_error_num) ? ncv_errors[idx].str : "Unknown error code"; 126 String str = cv::format("%s [Code = %d]", msg, code); 127 128 return str; 129 } 130 131 132 static void stdDebugOutput(const cv::String &msg) 133 { 134 std::cout << msg.c_str() << std::endl; 135 } 136 137 138 static NCVDebugOutputHandler *debugOutputHandler = stdDebugOutput; 139 140 141 void ncvDebugOutput(const cv::String &msg) 142 { 143 debugOutputHandler(msg); 144 } 145 146 147 void ncvSetDebugOutputHandler(NCVDebugOutputHandler *func) 148 { 149 debugOutputHandler = func; 150 } 151 152 153 //============================================================================== 154 // 155 // Memory wrappers and helpers 156 // 157 //============================================================================== 158 159 160 Ncv32u alignUp(Ncv32u what, Ncv32u alignment) 161 { 162 Ncv32u alignMask = alignment-1; 163 Ncv32u inverseAlignMask = ~alignMask; 164 Ncv32u res = (what + alignMask) & inverseAlignMask; 165 return res; 166 } 167 168 169 void NCVMemPtr::clear() 170 { 171 ptr = NULL; 172 memtype = NCVMemoryTypeNone; 173 } 174 175 176 void NCVMemSegment::clear() 177 { 178 begin.clear(); 179 size = 0; 180 } 181 182 183 NCVStatus memSegCopyHelper(void *dst, NCVMemoryType dstType, const void *src, NCVMemoryType srcType, size_t sz, cudaStream_t cuStream) 184 { 185 NCVStatus ncvStat; 186 switch (dstType) 187 { 188 case NCVMemoryTypeHostPageable: 189 case NCVMemoryTypeHostPinned: 190 switch (srcType) 191 { 192 case NCVMemoryTypeHostPageable: 193 case NCVMemoryTypeHostPinned: 194 memcpy(dst, src, sz); 195 ncvStat = NCV_SUCCESS; 196 break; 197 case NCVMemoryTypeDevice: 198 if (cuStream != 0) 199 { 200 ncvAssertCUDAReturn(cudaMemcpyAsync(dst, src, sz, cudaMemcpyDeviceToHost, cuStream), NCV_CUDA_ERROR); 201 } 202 else 203 { 204 ncvAssertCUDAReturn(cudaMemcpy(dst, src, sz, cudaMemcpyDeviceToHost), NCV_CUDA_ERROR); 205 } 206 ncvStat = NCV_SUCCESS; 207 break; 208 default: 209 ncvStat = NCV_MEM_RESIDENCE_ERROR; 210 } 211 break; 212 case NCVMemoryTypeDevice: 213 switch (srcType) 214 { 215 case NCVMemoryTypeHostPageable: 216 case NCVMemoryTypeHostPinned: 217 if (cuStream != 0) 218 { 219 ncvAssertCUDAReturn(cudaMemcpyAsync(dst, src, sz, cudaMemcpyHostToDevice, cuStream), NCV_CUDA_ERROR); 220 } 221 else 222 { 223 ncvAssertCUDAReturn(cudaMemcpy(dst, src, sz, cudaMemcpyHostToDevice), NCV_CUDA_ERROR); 224 } 225 ncvStat = NCV_SUCCESS; 226 break; 227 case NCVMemoryTypeDevice: 228 if (cuStream != 0) 229 { 230 ncvAssertCUDAReturn(cudaMemcpyAsync(dst, src, sz, cudaMemcpyDeviceToDevice, cuStream), NCV_CUDA_ERROR); 231 } 232 else 233 { 234 ncvAssertCUDAReturn(cudaMemcpy(dst, src, sz, cudaMemcpyDeviceToDevice), NCV_CUDA_ERROR); 235 } 236 ncvStat = NCV_SUCCESS; 237 break; 238 default: 239 ncvStat = NCV_MEM_RESIDENCE_ERROR; 240 } 241 break; 242 default: 243 ncvStat = NCV_MEM_RESIDENCE_ERROR; 244 } 245 246 return ncvStat; 247 } 248 249 250 NCVStatus memSegCopyHelper2D(void *dst, Ncv32u dstPitch, NCVMemoryType dstType, 251 const void *src, Ncv32u srcPitch, NCVMemoryType srcType, 252 Ncv32u widthbytes, Ncv32u height, cudaStream_t cuStream) 253 { 254 NCVStatus ncvStat; 255 switch (dstType) 256 { 257 case NCVMemoryTypeHostPageable: 258 case NCVMemoryTypeHostPinned: 259 switch (srcType) 260 { 261 case NCVMemoryTypeHostPageable: 262 case NCVMemoryTypeHostPinned: 263 for (Ncv32u i=0; i<height; i++) 264 { 265 memcpy((char*)dst + i * dstPitch, (char*)src + i * srcPitch, widthbytes); 266 } 267 ncvStat = NCV_SUCCESS; 268 break; 269 case NCVMemoryTypeDevice: 270 if (cuStream != 0) 271 { 272 ncvAssertCUDAReturn(cudaMemcpy2DAsync(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToHost, cuStream), NCV_CUDA_ERROR); 273 } 274 else 275 { 276 ncvAssertCUDAReturn(cudaMemcpy2D(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToHost), NCV_CUDA_ERROR); 277 } 278 ncvStat = NCV_SUCCESS; 279 break; 280 default: 281 ncvStat = NCV_MEM_RESIDENCE_ERROR; 282 } 283 break; 284 case NCVMemoryTypeDevice: 285 switch (srcType) 286 { 287 case NCVMemoryTypeHostPageable: 288 case NCVMemoryTypeHostPinned: 289 if (cuStream != 0) 290 { 291 ncvAssertCUDAReturn(cudaMemcpy2DAsync(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyHostToDevice, cuStream), NCV_CUDA_ERROR); 292 } 293 else 294 { 295 ncvAssertCUDAReturn(cudaMemcpy2D(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyHostToDevice), NCV_CUDA_ERROR); 296 } 297 ncvStat = NCV_SUCCESS; 298 break; 299 case NCVMemoryTypeDevice: 300 if (cuStream != 0) 301 { 302 ncvAssertCUDAReturn(cudaMemcpy2DAsync(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToDevice, cuStream), NCV_CUDA_ERROR); 303 } 304 else 305 { 306 ncvAssertCUDAReturn(cudaMemcpy2D(dst, dstPitch, src, srcPitch, widthbytes, height, cudaMemcpyDeviceToDevice), NCV_CUDA_ERROR); 307 } 308 ncvStat = NCV_SUCCESS; 309 break; 310 default: 311 ncvStat = NCV_MEM_RESIDENCE_ERROR; 312 } 313 break; 314 default: 315 ncvStat = NCV_MEM_RESIDENCE_ERROR; 316 } 317 318 return ncvStat; 319 } 320 321 322 //=================================================================== 323 // 324 // NCVMemStackAllocator class members implementation 325 // 326 //=================================================================== 327 328 329 NCVMemStackAllocator::NCVMemStackAllocator(Ncv32u alignment_) : 330 _memType(NCVMemoryTypeNone), 331 _alignment(alignment_), 332 allocBegin(NULL), 333 begin(NULL), 334 end(NULL), 335 currentSize(0), 336 _maxSize(0), 337 bReusesMemory(false) 338 { 339 NcvBool bProperAlignment = (alignment_ & (alignment_ - 1)) == 0; 340 ncvAssertPrintCheck(bProperAlignment, "NCVMemStackAllocator ctor:: alignment not power of 2"); 341 } 342 343 344 NCVMemStackAllocator::NCVMemStackAllocator(NCVMemoryType memT, size_t capacity, Ncv32u alignment_, void *reusePtr) : 345 _memType(memT), 346 _alignment(alignment_), 347 allocBegin(NULL), 348 currentSize(0), 349 _maxSize(0) 350 { 351 NcvBool bProperAlignment = (alignment_ & (alignment_ - 1)) == 0; 352 ncvAssertPrintCheck(bProperAlignment, "NCVMemStackAllocator ctor:: _alignment not power of 2"); 353 ncvAssertPrintCheck(memT != NCVMemoryTypeNone, "NCVMemStackAllocator ctor:: Incorrect allocator type"); 354 355 allocBegin = NULL; 356 357 if (reusePtr == NULL && capacity != 0) 358 { 359 bReusesMemory = false; 360 switch (memT) 361 { 362 case NCVMemoryTypeDevice: 363 ncvAssertCUDAReturn(cudaMalloc(&allocBegin, capacity), ); 364 break; 365 case NCVMemoryTypeHostPinned: 366 ncvAssertCUDAReturn(cudaMallocHost(&allocBegin, capacity), ); 367 break; 368 case NCVMemoryTypeHostPageable: 369 allocBegin = (Ncv8u *)malloc(capacity); 370 break; 371 default:; 372 } 373 } 374 else 375 { 376 bReusesMemory = true; 377 allocBegin = (Ncv8u *)reusePtr; 378 } 379 380 if (capacity == 0) 381 { 382 allocBegin = (Ncv8u *)(0x1); 383 } 384 385 if (!isCounting()) 386 { 387 begin = allocBegin; 388 end = begin + capacity; 389 } 390 } 391 392 393 NCVMemStackAllocator::~NCVMemStackAllocator() 394 { 395 if (allocBegin != NULL) 396 { 397 ncvAssertPrintCheck(currentSize == 0, "NCVMemStackAllocator dtor:: not all objects were deallocated properly, forcing destruction"); 398 399 if (!bReusesMemory && (allocBegin != (Ncv8u *)(0x1))) 400 { 401 switch (_memType) 402 { 403 case NCVMemoryTypeDevice: 404 ncvAssertCUDAReturn(cudaFree(allocBegin), ); 405 break; 406 case NCVMemoryTypeHostPinned: 407 ncvAssertCUDAReturn(cudaFreeHost(allocBegin), ); 408 break; 409 case NCVMemoryTypeHostPageable: 410 free(allocBegin); 411 break; 412 default:; 413 } 414 } 415 416 allocBegin = NULL; 417 } 418 } 419 420 421 NCVStatus NCVMemStackAllocator::alloc(NCVMemSegment &seg, size_t size) 422 { 423 seg.clear(); 424 ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC); 425 426 size = alignUp(static_cast<Ncv32u>(size), this->_alignment); 427 this->currentSize += size; 428 this->_maxSize = std::max(this->_maxSize, this->currentSize); 429 430 if (!isCounting()) 431 { 432 size_t availSize = end - begin; 433 ncvAssertReturn(size <= availSize, NCV_ALLOCATOR_INSUFFICIENT_CAPACITY); 434 } 435 436 seg.begin.ptr = begin; 437 seg.begin.memtype = this->_memType; 438 seg.size = size; 439 begin += size; 440 441 return NCV_SUCCESS; 442 } 443 444 445 NCVStatus NCVMemStackAllocator::dealloc(NCVMemSegment &seg) 446 { 447 ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC); 448 ncvAssertReturn(seg.begin.memtype == this->_memType, NCV_ALLOCATOR_BAD_DEALLOC); 449 ncvAssertReturn(seg.begin.ptr != NULL || isCounting(), NCV_ALLOCATOR_BAD_DEALLOC); 450 ncvAssertReturn(seg.begin.ptr == begin - seg.size, NCV_ALLOCATOR_DEALLOC_ORDER); 451 452 currentSize -= seg.size; 453 begin -= seg.size; 454 455 seg.clear(); 456 457 ncvAssertReturn(allocBegin <= begin, NCV_ALLOCATOR_BAD_DEALLOC); 458 459 return NCV_SUCCESS; 460 } 461 462 463 NcvBool NCVMemStackAllocator::isInitialized(void) const 464 { 465 return (((this->_alignment & (this->_alignment-1)) == 0) && isCounting()) || this->allocBegin != NULL; 466 } 467 468 469 NcvBool NCVMemStackAllocator::isCounting(void) const 470 { 471 return this->_memType == NCVMemoryTypeNone; 472 } 473 474 475 NCVMemoryType NCVMemStackAllocator::memType(void) const 476 { 477 return this->_memType; 478 } 479 480 481 Ncv32u NCVMemStackAllocator::alignment(void) const 482 { 483 return this->_alignment; 484 } 485 486 487 size_t NCVMemStackAllocator::maxSize(void) const 488 { 489 return this->_maxSize; 490 } 491 492 493 //=================================================================== 494 // 495 // NCVMemNativeAllocator class members implementation 496 // 497 //=================================================================== 498 499 500 NCVMemNativeAllocator::NCVMemNativeAllocator(NCVMemoryType memT, Ncv32u alignment_) : 501 _memType(memT), 502 _alignment(alignment_), 503 currentSize(0), 504 _maxSize(0) 505 { 506 ncvAssertPrintReturn(memT != NCVMemoryTypeNone, "NCVMemNativeAllocator ctor:: counting not permitted for this allocator type", ); 507 } 508 509 510 NCVMemNativeAllocator::~NCVMemNativeAllocator() 511 { 512 ncvAssertPrintCheck(currentSize == 0, "NCVMemNativeAllocator dtor:: detected memory leak"); 513 } 514 515 516 NCVStatus NCVMemNativeAllocator::alloc(NCVMemSegment &seg, size_t size) 517 { 518 seg.clear(); 519 ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC); 520 521 switch (this->_memType) 522 { 523 case NCVMemoryTypeDevice: 524 ncvAssertCUDAReturn(cudaMalloc(&seg.begin.ptr, size), NCV_CUDA_ERROR); 525 break; 526 case NCVMemoryTypeHostPinned: 527 ncvAssertCUDAReturn(cudaMallocHost(&seg.begin.ptr, size), NCV_CUDA_ERROR); 528 break; 529 case NCVMemoryTypeHostPageable: 530 seg.begin.ptr = (Ncv8u *)malloc(size); 531 break; 532 default:; 533 } 534 535 this->currentSize += alignUp(static_cast<Ncv32u>(size), this->_alignment); 536 this->_maxSize = std::max(this->_maxSize, this->currentSize); 537 538 seg.begin.memtype = this->_memType; 539 seg.size = size; 540 541 return NCV_SUCCESS; 542 } 543 544 545 NCVStatus NCVMemNativeAllocator::dealloc(NCVMemSegment &seg) 546 { 547 ncvAssertReturn(isInitialized(), NCV_ALLOCATOR_BAD_ALLOC); 548 ncvAssertReturn(seg.begin.memtype == this->_memType, NCV_ALLOCATOR_BAD_DEALLOC); 549 ncvAssertReturn(seg.begin.ptr != NULL, NCV_ALLOCATOR_BAD_DEALLOC); 550 551 ncvAssertReturn(currentSize >= alignUp(static_cast<Ncv32u>(seg.size), this->_alignment), NCV_ALLOCATOR_BAD_DEALLOC); 552 currentSize -= alignUp(static_cast<Ncv32u>(seg.size), this->_alignment); 553 554 switch (this->_memType) 555 { 556 case NCVMemoryTypeDevice: 557 ncvAssertCUDAReturn(cudaFree(seg.begin.ptr), NCV_CUDA_ERROR); 558 break; 559 case NCVMemoryTypeHostPinned: 560 ncvAssertCUDAReturn(cudaFreeHost(seg.begin.ptr), NCV_CUDA_ERROR); 561 break; 562 case NCVMemoryTypeHostPageable: 563 free(seg.begin.ptr); 564 break; 565 default:; 566 } 567 568 seg.clear(); 569 570 return NCV_SUCCESS; 571 } 572 573 574 NcvBool NCVMemNativeAllocator::isInitialized(void) const 575 { 576 return (this->_alignment != 0); 577 } 578 579 580 NcvBool NCVMemNativeAllocator::isCounting(void) const 581 { 582 return false; 583 } 584 585 586 NCVMemoryType NCVMemNativeAllocator::memType(void) const 587 { 588 return this->_memType; 589 } 590 591 592 Ncv32u NCVMemNativeAllocator::alignment(void) const 593 { 594 return this->_alignment; 595 } 596 597 598 size_t NCVMemNativeAllocator::maxSize(void) const 599 { 600 return this->_maxSize; 601 } 602 603 604 //=================================================================== 605 // 606 // Time and timer routines 607 // 608 //=================================================================== 609 610 611 typedef struct _NcvTimeMoment NcvTimeMoment; 612 613 #if defined(_WIN32) || defined(_WIN64) 614 615 #include <Windows.h> 616 617 typedef struct _NcvTimeMoment 618 { 619 LONGLONG moment, freq; 620 } NcvTimeMoment; 621 622 623 static void _ncvQueryMoment(NcvTimeMoment *t) 624 { 625 QueryPerformanceFrequency((LARGE_INTEGER *)&(t->freq)); 626 QueryPerformanceCounter((LARGE_INTEGER *)&(t->moment)); 627 } 628 629 630 double _ncvMomentToMicroseconds(NcvTimeMoment *t) 631 { 632 return 1000000.0 * t->moment / t->freq; 633 } 634 635 636 double _ncvMomentsDiffToMicroseconds(NcvTimeMoment *t1, NcvTimeMoment *t2) 637 { 638 return 1000000.0 * 2 * ((t2->moment) - (t1->moment)) / (t1->freq + t2->freq); 639 } 640 641 642 double _ncvMomentsDiffToMilliseconds(NcvTimeMoment *t1, NcvTimeMoment *t2) 643 { 644 return 1000.0 * 2 * ((t2->moment) - (t1->moment)) / (t1->freq + t2->freq); 645 } 646 647 #elif defined(__GNUC__) 648 649 #include <sys/time.h> 650 651 typedef struct _NcvTimeMoment 652 { 653 struct timeval tv; 654 struct timezone tz; 655 } NcvTimeMoment; 656 657 658 void _ncvQueryMoment(NcvTimeMoment *t) 659 { 660 gettimeofday(& t->tv, & t->tz); 661 } 662 663 664 double _ncvMomentToMicroseconds(NcvTimeMoment *t) 665 { 666 return 1000000.0 * t->tv.tv_sec + (double)t->tv.tv_usec; 667 } 668 669 670 double _ncvMomentsDiffToMicroseconds(NcvTimeMoment *t1, NcvTimeMoment *t2) 671 { 672 return (((double)t2->tv.tv_sec - (double)t1->tv.tv_sec) * 1000000 + (double)t2->tv.tv_usec - (double)t1->tv.tv_usec); 673 } 674 675 double _ncvMomentsDiffToMilliseconds(NcvTimeMoment *t1, NcvTimeMoment *t2) 676 { 677 return ((double)t2->tv.tv_sec - (double)t1->tv.tv_sec) * 1000; 678 } 679 680 #endif //#if defined(_WIN32) || defined(_WIN64) 681 682 683 struct _NcvTimer 684 { 685 NcvTimeMoment t1, t2; 686 }; 687 688 689 NcvTimer ncvStartTimer(void) 690 { 691 struct _NcvTimer *t; 692 t = (struct _NcvTimer *)malloc(sizeof(struct _NcvTimer)); 693 _ncvQueryMoment(&t->t1); 694 return t; 695 } 696 697 698 double ncvEndQueryTimerUs(NcvTimer t) 699 { 700 double res; 701 _ncvQueryMoment(&t->t2); 702 res = _ncvMomentsDiffToMicroseconds(&t->t1, &t->t2); 703 free(t); 704 return res; 705 } 706 707 708 double ncvEndQueryTimerMs(NcvTimer t) 709 { 710 double res; 711 _ncvQueryMoment(&t->t2); 712 res = _ncvMomentsDiffToMilliseconds(&t->t1, &t->t2); 713 free(t); 714 return res; 715 } 716 717 718 //=================================================================== 719 // 720 // Operations with rectangles 721 // 722 //=================================================================== 723 724 struct RectConvert 725 { 726 cv::Rect operator()(const NcvRect32u& nr) const { return cv::Rect(nr.x, nr.y, nr.width, nr.height); } 727 NcvRect32u operator()(const cv::Rect& nr) const 728 { 729 NcvRect32u rect; 730 rect.x = nr.x; 731 rect.y = nr.y; 732 rect.width = nr.width; 733 rect.height = nr.height; 734 return rect; 735 } 736 }; 737 738 static void groupRectangles(std::vector<NcvRect32u> &hypotheses, int groupThreshold, double eps, std::vector<Ncv32u> *weights) 739 { 740 #ifndef HAVE_OPENCV_OBJDETECT 741 (void) hypotheses; 742 (void) groupThreshold; 743 (void) eps; 744 (void) weights; 745 CV_Error(cv::Error::StsNotImplemented, "This functionality requires objdetect module"); 746 #else 747 std::vector<cv::Rect> rects(hypotheses.size()); 748 std::transform(hypotheses.begin(), hypotheses.end(), rects.begin(), RectConvert()); 749 750 if (weights) 751 { 752 std::vector<int> weights_int; 753 weights_int.assign(weights->begin(), weights->end()); 754 cv::groupRectangles(rects, weights_int, groupThreshold, eps); 755 } 756 else 757 { 758 cv::groupRectangles(rects, groupThreshold, eps); 759 } 760 std::transform(rects.begin(), rects.end(), hypotheses.begin(), RectConvert()); 761 hypotheses.resize(rects.size()); 762 #endif 763 } 764 765 766 767 NCVStatus ncvGroupRectangles_host(NCVVector<NcvRect32u> &hypotheses, 768 Ncv32u &numHypotheses, 769 Ncv32u minNeighbors, 770 Ncv32f intersectEps, 771 NCVVector<Ncv32u> *hypothesesWeights) 772 { 773 ncvAssertReturn(hypotheses.memType() == NCVMemoryTypeHostPageable || 774 hypotheses.memType() == NCVMemoryTypeHostPinned, NCV_MEM_RESIDENCE_ERROR); 775 if (hypothesesWeights != NULL) 776 { 777 ncvAssertReturn(hypothesesWeights->memType() == NCVMemoryTypeHostPageable || 778 hypothesesWeights->memType() == NCVMemoryTypeHostPinned, NCV_MEM_RESIDENCE_ERROR); 779 } 780 781 if (numHypotheses == 0) 782 { 783 return NCV_SUCCESS; 784 } 785 786 std::vector<NcvRect32u> rects(numHypotheses); 787 memcpy(&rects[0], hypotheses.ptr(), numHypotheses * sizeof(NcvRect32u)); 788 789 std::vector<Ncv32u> weights; 790 if (hypothesesWeights != NULL) 791 { 792 groupRectangles(rects, minNeighbors, intersectEps, &weights); 793 } 794 else 795 { 796 groupRectangles(rects, minNeighbors, intersectEps, NULL); 797 } 798 799 numHypotheses = (Ncv32u)rects.size(); 800 if (numHypotheses > 0) 801 { 802 memcpy(hypotheses.ptr(), &rects[0], numHypotheses * sizeof(NcvRect32u)); 803 } 804 805 if (hypothesesWeights != NULL) 806 { 807 memcpy(hypothesesWeights->ptr(), &weights[0], numHypotheses * sizeof(Ncv32u)); 808 } 809 810 return NCV_SUCCESS; 811 } 812 813 814 template <class T> 815 static NCVStatus drawRectsWrapperHost(T *h_dst, 816 Ncv32u dstStride, 817 Ncv32u dstWidth, 818 Ncv32u dstHeight, 819 NcvRect32u *h_rects, 820 Ncv32u numRects, 821 T color) 822 { 823 ncvAssertReturn(h_dst != NULL && h_rects != NULL, NCV_NULL_PTR); 824 ncvAssertReturn(dstWidth > 0 && dstHeight > 0, NCV_DIMENSIONS_INVALID); 825 ncvAssertReturn(dstStride >= dstWidth, NCV_INVALID_STEP); 826 ncvAssertReturn(numRects != 0, NCV_SUCCESS); 827 ncvAssertReturn(numRects <= dstWidth * dstHeight, NCV_DIMENSIONS_INVALID); 828 829 for (Ncv32u i=0; i<numRects; i++) 830 { 831 NcvRect32u rect = h_rects[i]; 832 833 if (rect.x < dstWidth) 834 { 835 for (Ncv32u each=rect.y; each<rect.y+rect.height && each<dstHeight; each++) 836 { 837 h_dst[each*dstStride+rect.x] = color; 838 } 839 } 840 if (rect.x+rect.width-1 < dstWidth) 841 { 842 for (Ncv32u each=rect.y; each<rect.y+rect.height && each<dstHeight; each++) 843 { 844 h_dst[each*dstStride+rect.x+rect.width-1] = color; 845 } 846 } 847 if (rect.y < dstHeight) 848 { 849 for (Ncv32u j=rect.x; j<rect.x+rect.width && j<dstWidth; j++) 850 { 851 h_dst[rect.y*dstStride+j] = color; 852 } 853 } 854 if (rect.y + rect.height - 1 < dstHeight) 855 { 856 for (Ncv32u j=rect.x; j<rect.x+rect.width && j<dstWidth; j++) 857 { 858 h_dst[(rect.y+rect.height-1)*dstStride+j] = color; 859 } 860 } 861 } 862 863 return NCV_SUCCESS; 864 } 865 866 867 NCVStatus ncvDrawRects_8u_host(Ncv8u *h_dst, 868 Ncv32u dstStride, 869 Ncv32u dstWidth, 870 Ncv32u dstHeight, 871 NcvRect32u *h_rects, 872 Ncv32u numRects, 873 Ncv8u color) 874 { 875 return drawRectsWrapperHost(h_dst, dstStride, dstWidth, dstHeight, h_rects, numRects, color); 876 } 877 878 879 NCVStatus ncvDrawRects_32u_host(Ncv32u *h_dst, 880 Ncv32u dstStride, 881 Ncv32u dstWidth, 882 Ncv32u dstHeight, 883 NcvRect32u *h_rects, 884 Ncv32u numRects, 885 Ncv32u color) 886 { 887 return drawRectsWrapperHost(h_dst, dstStride, dstWidth, dstHeight, h_rects, numRects, color); 888 } 889