From 06f4a56469836c443bfcc929d294822bb93e3aa3 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 11 Feb 2013 23:49:10 +0400 Subject: [PATCH] converted flood fill, getrectsubpix & cornersubpix to C++ --- modules/imgproc/src/cornersubpix.cpp | 204 ++---- modules/imgproc/src/deriv.cpp | 77 --- modules/imgproc/src/floodfill.cpp | 381 +++++------ modules/imgproc/src/imgwarp.cpp | 8 +- modules/imgproc/src/precomp.hpp | 29 - modules/imgproc/src/samplers.cpp | 871 +++++------------------- modules/imgproc/src/thresh.cpp | 1 - modules/imgproc/test/test_floodfill.cpp | 6 + 8 files changed, 421 insertions(+), 1156 deletions(-) diff --git a/modules/imgproc/src/cornersubpix.cpp b/modules/imgproc/src/cornersubpix.cpp index 1f55fa7513..11f08e7903 100644 --- a/modules/imgproc/src/cornersubpix.cpp +++ b/modules/imgproc/src/cornersubpix.cpp @@ -7,10 +7,11 @@ // copy or use the software. // // -// Intel License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -23,7 +24,7 @@ // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -// * The name of Intel Corporation may not be used to endorse or promote products +// * The name of the copyright holders may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and @@ -40,119 +41,43 @@ //M*/ #include "precomp.hpp" -CV_IMPL void -cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners, - int count, CvSize win, CvSize zeroZone, - CvTermCriteria criteria ) +void cv::cornerSubPix( InputArray _image, InputOutputArray _corners, + Size win, Size zeroZone, TermCriteria criteria ) { - cv::AutoBuffer buffer; - const int MAX_ITERS = 100; - const float drv[] = { -1.f, 0.f, 1.f }; - float *maskX; - float *maskY; - float *mask; - float *src_buffer; - float *gx_buffer; - float *gy_buffer; int win_w = win.width * 2 + 1, win_h = win.height * 2 + 1; - int win_rect_size = (win_w + 4) * (win_h + 4); - double coeff; - CvSize size, src_buf_size; - int i, j, k, pt_i; - int max_iters = 10; - double eps = 0; - - CvMat stub, *src = (CvMat*)srcarr; - src = cvGetMat( srcarr, &stub ); - - if( CV_MAT_TYPE( src->type ) != CV_8UC1 ) - CV_Error( CV_StsUnsupportedFormat, "The source image must be 8-bit single-channel (CV_8UC1)" ); + int i, j, k; + int max_iters = (criteria.type & CV_TERMCRIT_ITER) ? MIN(MAX(criteria.maxCount, 1), MAX_ITERS) : MAX_ITERS; + double eps = (criteria.type & CV_TERMCRIT_EPS) ? MAX(criteria.epsilon, 0.) : 0; + eps *= eps; // use square of error in comparsion operations - if( !corners ) - CV_Error( CV_StsNullPtr, "" ); - - if( count < 0 ) - CV_Error( CV_StsBadSize, "" ); + cv::Mat src = _image.getMat(), cornersmat = _corners.getMat(); + int count = cornersmat.checkVector(2, CV_32F); + CV_Assert( count >= 0 ); + Point2f* corners = (Point2f*)cornersmat.data; if( count == 0 ) return; - if( win.width <= 0 || win.height <= 0 ) - CV_Error( CV_StsBadSize, "" ); - - size = cvGetMatSize( src ); - - if( size.width < win_w + 4 || size.height < win_h + 4 ) - CV_Error( CV_StsBadSize, "" ); - - /* initialize variables, controlling loop termination */ - switch( criteria.type ) - { - case CV_TERMCRIT_ITER: - eps = 0.f; - max_iters = criteria.max_iter; - break; - case CV_TERMCRIT_EPS: - eps = criteria.epsilon; - max_iters = MAX_ITERS; - break; - case CV_TERMCRIT_ITER | CV_TERMCRIT_EPS: - eps = criteria.epsilon; - max_iters = criteria.max_iter; - break; - default: - assert( 0 ); - CV_Error( CV_StsBadFlag, "" ); - } - - eps = MAX( eps, 0 ); - eps *= eps; /* use square of error in comparsion operations. */ - - max_iters = MAX( max_iters, 1 ); - max_iters = MIN( max_iters, MAX_ITERS ); - - buffer.allocate( win_rect_size * 5 + win_w + win_h + 32 ); - - /* assign pointers */ - maskX = buffer; - maskY = maskX + win_w + 4; - mask = maskY + win_h + 4; - src_buffer = mask + win_w * win_h; - gx_buffer = src_buffer + win_rect_size; - gy_buffer = gx_buffer + win_rect_size; + CV_Assert( win.width > 0 && win.height > 0 ); + CV_Assert( src.cols >= win_w + 4 && src.rows >= win_h + 4 ); + CV_Assert( src.channels() == 1 ); - coeff = 1. / (win.width * win.width); - - /* calculate mask */ - for( i = -win.width, k = 0; i <= win.width; i++, k++ ) - { - maskX[k] = (float)exp( -i * i * coeff ); - } - - if( win.width == win.height ) - { - maskY = maskX; - } - else - { - coeff = 1. / (win.height * win.height); - for( i = -win.height, k = 0; i <= win.height; i++, k++ ) - { - maskY[k] = (float) exp( -i * i * coeff ); - } - } + Mat maskm(win_h, win_w, CV_32F), subpix_buf(win_h+2, win_w+2, CV_32F); + float* mask = maskm.ptr(); for( i = 0; i < win_h; i++ ) { + float y = (float)(i - win.height)/win.height; + float vy = std::exp(-y*y); for( j = 0; j < win_w; j++ ) { - mask[i * win_w + j] = maskX[j] * maskY[i]; + float x = (float)(j - win.width)/win.width; + mask[i * win_w + j] = (float)(vy*std::exp(-x*x)); } } - - /* make zero_zone */ + // make zero_zone if( zeroZone.width >= 0 && zeroZone.height >= 0 && zeroZone.width * 2 + 1 < win_w && zeroZone.height * 2 + 1 < win_h ) { @@ -165,46 +90,31 @@ cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners, } } - /* set sizes of image rectangles, used in convolutions */ - src_buf_size.width = win_w + 2; - src_buf_size.height = win_h + 2; - - /* do optimization loop for all the points */ - for( pt_i = 0; pt_i < count; pt_i++ ) + // do optimization loop for all the points + for( int pt_i = 0; pt_i < count; pt_i++ ) { - CvPoint2D32f cT = corners[pt_i], cI = cT; + Point2f cT = corners[pt_i], cI = cT; int iter = 0; - double err; + double err = 0; do { - CvPoint2D32f cI2; - double a, b, c, bb1, bb2; - - IPPI_CALL( icvGetRectSubPix_8u32f_C1R( (uchar*)src->data.ptr, src->step, size, - src_buffer, (win_w + 2) * sizeof( src_buffer[0] ), - cvSize( win_w + 2, win_h + 2 ), cI )); + Point2f cI2; + double a = 0, b = 0, c = 0, bb1 = 0, bb2 = 0; - /* calc derivatives */ - icvSepConvSmall3_32f( src_buffer+src_buf_size.width, src_buf_size.width * sizeof(src_buffer[0]), - gx_buffer, win_w * sizeof(gx_buffer[0]), - src_buf_size, drv, NULL, NULL ); - icvSepConvSmall3_32f( src_buffer+1, src_buf_size.width * sizeof(src_buffer[0]), - gy_buffer, win_w * sizeof(gy_buffer[0]), - src_buf_size, NULL, drv, NULL ); + getRectSubPix(src, Size(win_w+2, win_h+2), cI, subpix_buf, subpix_buf.type()); + const float* subpix = &subpix_buf.at(1,1); - a = b = c = bb1 = bb2 = 0; - - /* process gradient */ - for( i = 0, k = 0; i < win_h; i++ ) + // process gradient + for( i = 0, k = 0; i < win_h; i++, subpix += win_w + 2 ) { double py = i - win.height; for( j = 0; j < win_w; j++, k++ ) { double m = mask[k]; - double tgx = gx_buffer[k]; - double tgy = gy_buffer[k]; + double tgx = subpix[1] - subpix[-1]; + double tgy = subpix[win_w+2] - subpix[-win_w-2]; double gxx = tgx * tgx * m; double gxy = tgx * tgy * m; double gyy = tgy * tgy * m; @@ -220,46 +130,38 @@ cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners, } double det=a*c-b*b; - if( fabs( det ) > DBL_EPSILON*DBL_EPSILON ) - { - // 2x2 matrix inversion - double scale=1.0/det; - cI2.x = (float)(cI.x + c*scale*bb1 - b*scale*bb2); - cI2.y = (float)(cI.y - b*scale*bb1 + a*scale*bb2); - } - else - { - cI2 = cI; - } + if( fabs( det ) <= DBL_EPSILON*DBL_EPSILON ) + break; + // 2x2 matrix inversion + double scale=1.0/det; + cI2.x = (float)(cI.x + c*scale*bb1 - b*scale*bb2); + cI2.y = (float)(cI.y - b*scale*bb1 + a*scale*bb2); err = (cI2.x - cI.x) * (cI2.x - cI.x) + (cI2.y - cI.y) * (cI2.y - cI.y); cI = cI2; } while( ++iter < max_iters && err > eps ); - /* if new point is too far from initial, it means poor convergence. - leave initial point as the result */ + // if new point is too far from initial, it means poor convergence. + // leave initial point as the result if( fabs( cI.x - cT.x ) > win.width || fabs( cI.y - cT.y ) > win.height ) - { cI = cT; - } - corners[pt_i] = cI; /* store result */ + corners[pt_i] = cI; } } -void cv::cornerSubPix( InputArray _image, InputOutputArray _corners, - Size winSize, Size zeroZone, - TermCriteria criteria ) + +CV_IMPL void +cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* _corners, + int count, CvSize win, CvSize zeroZone, + CvTermCriteria criteria ) { - Mat corners = _corners.getMat(); - int ncorners = corners.checkVector(2); - CV_Assert( ncorners >= 0 && corners.depth() == CV_32F ); - Mat image = _image.getMat(); - CvMat c_image = image; + if(!_corners || count <= 0) + return; - cvFindCornerSubPix( &c_image, (CvPoint2D32f*)corners.data, ncorners, - winSize, zeroZone, criteria ); + cv::Mat src = cv::cvarrToMat(srcarr), corners(count, 1, CV_32FC2, _corners); + cv::cornerSubPix(src, corners, win, zeroZone, criteria); } /* End of file. */ diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 1e5d78c510..8950b61868 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -43,83 +43,6 @@ #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) static IppStatus sts = ippInit(); #endif -/****************************************************************************************/ - -/* lightweight convolution with 3x3 kernel */ -void icvSepConvSmall3_32f( float* src, int src_step, float* dst, int dst_step, - CvSize src_size, const float* kx, const float* ky, float* buffer ) -{ - int dst_width, buffer_step = 0; - int x, y; - bool fast_kx = true, fast_ky = true; - - assert( src && dst && src_size.width > 2 && src_size.height > 2 && - (src_step & 3) == 0 && (dst_step & 3) == 0 && - (kx || ky) && (buffer || !kx || !ky)); - - src_step /= sizeof(src[0]); - dst_step /= sizeof(dst[0]); - - dst_width = src_size.width - 2; - - if( !kx ) - { - /* set vars, so that vertical convolution - will write results into destination ROI and - horizontal convolution won't run */ - src_size.width = dst_width; - buffer_step = dst_step; - buffer = dst; - dst_width = 0; - } - else - fast_kx = kx[1] == 0.f && kx[0] == -kx[2] && kx[0] == -1.f; - - assert( src_step >= src_size.width && dst_step >= dst_width ); - - src_size.height -= 2; - if( !ky ) - { - /* set vars, so that vertical convolution won't run and - horizontal convolution will write results into destination ROI */ - src_size.height += 2; - buffer_step = src_step; - buffer = src; - src_size.width = 0; - } - else - fast_ky = ky[1] == 0.f && ky[0] == -ky[2] && ky[0] == -1.f; - - for( y = 0; y < src_size.height; y++, src += src_step, - dst += dst_step, - buffer += buffer_step ) - { - float* src2 = src + src_step; - float* src3 = src + src_step*2; - if( fast_ky ) - for( x = 0; x < src_size.width; x++ ) - { - buffer[x] = (float)(src3[x] - src[x]); - } - else - for( x = 0; x < src_size.width; x++ ) - { - buffer[x] = (float)(ky[0]*src[x] + ky[1]*src2[x] + ky[2]*src3[x]); - } - - if( fast_kx ) - for( x = 0; x < dst_width; x++ ) - { - dst[x] = (float)(buffer[x+2] - buffer[x]); - } - else - for( x = 0; x < dst_width; x++ ) - { - dst[x] = (float)(kx[0]*buffer[x] + kx[1]*buffer[x+1] + kx[2]*buffer[x+2]); - } - } -} - /****************************************************************************************\ Sobel & Scharr Derivative Filters diff --git a/modules/imgproc/src/floodfill.cpp b/modules/imgproc/src/floodfill.cpp index d93511353e..e4e64b9d10 100644 --- a/modules/imgproc/src/floodfill.cpp +++ b/modules/imgproc/src/floodfill.cpp @@ -7,10 +7,11 @@ // copy or use the software. // // -// Intel License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -23,7 +24,7 @@ // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -// * The name of Intel Corporation may not be used to endorse or promote products +// * The name of the copyright holders may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and @@ -41,7 +42,10 @@ #include "precomp.hpp" -typedef struct CvFFillSegment +namespace cv +{ + +struct FFillSegment { ushort y; ushort l; @@ -49,11 +53,13 @@ typedef struct CvFFillSegment ushort prevl; ushort prevr; short dir; -} -CvFFillSegment; +}; -#define UP 1 -#define DOWN -1 +enum +{ + UP = 1, + DOWN = -1 +}; #define ICV_PUSH( Y, L, R, PREV_L, PREV_R, DIR ) \ { \ @@ -65,7 +71,7 @@ CvFFillSegment; tail->dir = (short)(DIR); \ if( ++tail == buffer_end ) \ { \ - buffer->resize(buffer->size() * 2); \ + buffer->resize(buffer->size() * 3/2); \ tail = &buffer->front() + (tail - head); \ head = &buffer->front(); \ buffer_end = head + buffer->size(); \ @@ -83,23 +89,52 @@ CvFFillSegment; DIR = tail->dir; \ } -/****************************************************************************************\ -* Simple Floodfill (repainting single-color connected component) * -\****************************************************************************************/ +struct ConnectedComp +{ + ConnectedComp(); + Rect rect; + Point pt; + int threshold; + int label; + int area; + int harea; + int carea; + int perimeter; + int nholes; + int ninflections; + double mx; + double my; + Scalar avg; + Scalar sdv; +}; + +ConnectedComp::ConnectedComp() +{ + rect = Rect(0, 0, 0, 0); + pt = Point(-1, -1); + threshold = -1; + label = -1; + area = harea = carea = perimeter = nholes = ninflections = 0; + mx = my = 0; + avg = sdv = Scalar::all(0); +} + +// Simple Floodfill (repainting single-color connected component) template static void -icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed, - _Tp newVal, CvConnectedComp* region, int flags, - std::vector* buffer ) +floodFill_CnIR( Mat& image, Point seed, + _Tp newVal, ConnectedComp* region, int flags, + std::vector* buffer ) { - typedef typename cv::DataType<_Tp>::channel_type _CTp; - _Tp* img = (_Tp*)(pImage + step * seed.y); + typedef typename DataType<_Tp>::channel_type _CTp; + _Tp* img = (_Tp*)(image.data + image.step * seed.y); + Size roi = image.size(); int i, L, R; int area = 0; int XMin, XMax, YMin = seed.y, YMax = seed.y; int _8_connectivity = (flags & 255) == 8; - CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front(); + FFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front(); L = R = XMin = XMax = seed.x; @@ -142,7 +177,7 @@ icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed, for( k = 0; k < 3; k++ ) { dir = data[k][0]; - img = (_Tp*)(pImage + (YC + dir) * step); + img = (_Tp*)(image.data + (YC + dir) * image.step); int left = data[k][1]; int right = data[k][2]; @@ -169,12 +204,12 @@ icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed, if( region ) { + region->pt = seed; region->area = area; region->rect.x = XMin; region->rect.y = YMin; region->rect.width = XMax - XMin + 1; region->rect.height = YMax - YMin + 1; - region->value = cv::Scalar(newVal); } } @@ -192,12 +227,12 @@ struct Diff8uC1 struct Diff8uC3 { - Diff8uC3(cv::Vec3b _lo, cv::Vec3b _up) + Diff8uC3(Vec3b _lo, Vec3b _up) { for( int k = 0; k < 3; k++ ) lo[k] = _lo[k], interval[k] = _lo[k] + _up[k]; } - bool operator()(const cv::Vec3b* a, const cv::Vec3b* b) const + bool operator()(const Vec3b* a, const Vec3b* b) const { return (unsigned)(a[0][0] - b[0][0] + lo[0]) <= interval[0] && (unsigned)(a[0][1] - b[0][1] + lo[1]) <= interval[1] && @@ -233,37 +268,30 @@ struct DiffC3 }; typedef DiffC1 Diff32sC1; -typedef DiffC3 Diff32sC3; +typedef DiffC3 Diff32sC3; typedef DiffC1 Diff32fC1; -typedef DiffC3 Diff32fC3; +typedef DiffC3 Diff32fC3; -static cv::Vec3i& operator += (cv::Vec3i& a, const cv::Vec3b& b) -{ - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - return a; -} - -template +template static void -icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep, - CvSize /*roi*/, CvPoint seed, _Tp newVal, Diff diff, - CvConnectedComp* region, int flags, - std::vector* buffer ) +floodFillGrad_CnIR( Mat& image, Mat& msk, + Point seed, _Tp newVal, _MTp newMaskVal, + Diff diff, ConnectedComp* region, int flags, + std::vector* buffer ) { - typedef typename cv::DataType<_Tp>::channel_type _CTp; + typedef typename DataType<_Tp>::channel_type _CTp; + int step = (int)image.step, maskStep = (int)msk.step; + uchar* pImage = image.data; _Tp* img = (_Tp*)(pImage + step*seed.y); - uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y; + uchar* pMask = msk.data + maskStep + sizeof(_MTp); + _MTp* mask = (_MTp*)(pMask + maskStep*seed.y); int i, L, R; int area = 0; - _WTp sum = _WTp((typename cv::DataType<_Tp>::channel_type)0); int XMin, XMax, YMin = seed.y, YMax = seed.y; int _8_connectivity = (flags & 255) == 8; - int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE; - int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0; - uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1); - CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front(); + int fixedRange = flags & FLOODFILL_FIXED_RANGE; + int fillImage = (flags & FLOODFILL_MASK_ONLY) == 0; + FFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front(); L = R = seed.x; if( mask[L] ) @@ -323,7 +351,7 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep, dir = data[k][0]; img = (_Tp*)(pImage + (YC + dir) * step); _Tp* img1 = (_Tp*)(pImage + YC * step); - mask = pMask + (YC + dir) * maskStep; + mask = (_MTp*)(pMask + (YC + dir) * maskStep); int left = data[k][1]; int right = data[k][2]; @@ -354,7 +382,7 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep, mask[j] = newMaskVal; while( !mask[++i] && - (diff( img + i, img + (i-1) ) || + (diff( img + i, img + (i-1) ) || (diff( img + i, img1 + i) && i <= R))) mask[i] = newMaskVal; @@ -368,13 +396,13 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep, _Tp val; if( !mask[i] && - (((val = img[i], - (unsigned)(idx = i-L-1) <= length) && - diff( &val, img1 + (i-1))) || + (((val = img[i], + (unsigned)(idx = i-L-1) <= length) && + diff( &val, img1 + (i-1))) || ((unsigned)(++idx) <= length && - diff( &val, img1 + i )) || + diff( &val, img1 + i )) || ((unsigned)(++idx) <= length && - diff( &val, img1 + (i+1) )))) + diff( &val, img1 + (i+1) )))) { int j = i; mask[i] = newMaskVal; @@ -382,14 +410,14 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep, mask[j] = newMaskVal; while( !mask[++i] && - ((val = img[i], - diff( &val, img + (i-1) )) || + ((val = img[i], + diff( &val, img + (i-1) )) || (((unsigned)(idx = i-L-1) <= length && - diff( &val, img1 + (i-1) ))) || + diff( &val, img1 + (i-1) ))) || ((unsigned)(++idx) <= length && - diff( &val, img1 + i )) || + diff( &val, img1 + i )) || ((unsigned)(++idx) <= length && - diff( &val, img1 + (i+1) )))) + diff( &val, img1 + (i+1) )))) mask[i] = newMaskVal; ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir ); @@ -401,56 +429,40 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep, if( fillImage ) for( i = L; i <= R; i++ ) img[i] = newVal; - else if( region ) - for( i = L; i <= R; i++ ) - sum += img[i]; + /*else if( region ) + for( i = L; i <= R; i++ ) + sum += img[i];*/ } if( region ) { + region->pt = seed; + region->label = saturate_cast(newMaskVal); region->area = area; region->rect.x = XMin; region->rect.y = YMin; region->rect.width = XMax - XMin + 1; region->rect.height = YMax - YMin + 1; - - if( fillImage ) - region->value = cv::Scalar(newVal); - else - { - double iarea = area ? 1./area : 0; - region->value = cv::Scalar(sum*iarea); - } } } +} /****************************************************************************************\ * External Functions * \****************************************************************************************/ -typedef void (*CvFloodFillFunc)( - void* img, int step, CvSize size, CvPoint seed, void* newval, - CvConnectedComp* comp, int flags, void* buffer, int cn ); - -typedef void (*CvFloodFillGradFunc)( - void* img, int step, uchar* mask, int maskStep, CvSize size, - CvPoint seed, void* newval, void* d_lw, void* d_up, void* ccomp, - int flags, void* buffer, int cn ); - -CV_IMPL void -cvFloodFill( CvArr* arr, CvPoint seed_point, - CvScalar newVal, CvScalar lo_diff, CvScalar up_diff, - CvConnectedComp* comp, int flags, CvArr* maskarr ) +int cv::floodFill( InputOutputArray _image, InputOutputArray _mask, + Point seedPoint, Scalar newVal, Rect* rect, + Scalar loDiff, Scalar upDiff, int flags ) { - cv::Ptr tempMask; - std::vector buffer; + ConnectedComp comp; + vector buffer; - if( comp ) - memset( comp, 0, sizeof(*comp) ); + if( rect ) + *rect = Rect(); - int i, type, depth, cn, is_simple; - int buffer_size, connectivity = flags & 255; + int i, connectivity = flags & 255; union { uchar b[4]; int i[4]; @@ -459,191 +471,176 @@ cvFloodFill( CvArr* arr, CvPoint seed_point, } nv_buf; nv_buf._[0] = nv_buf._[1] = nv_buf._[2] = nv_buf._[3] = 0; - struct { cv::Vec3b b; cv::Vec3i i; cv::Vec3f f; } ld_buf, ud_buf; - CvMat stub, *img = cvGetMat(arr, &stub); - CvMat maskstub, *mask = (CvMat*)maskarr; - CvSize size; + struct { Vec3b b; Vec3i i; Vec3f f; } ld_buf, ud_buf; + Mat img = _image.getMat(), mask; + if( !_mask.empty() ) + mask = _mask.getMat(); + Size size = img.size(); - type = CV_MAT_TYPE( img->type ); - depth = CV_MAT_DEPTH(type); - cn = CV_MAT_CN(type); + int type = img.type(); + int depth = img.depth(); + int cn = img.channels(); if( connectivity == 0 ) connectivity = 4; else if( connectivity != 4 && connectivity != 8 ) CV_Error( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" ); - is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0; + bool is_simple = mask.empty() && (flags & FLOODFILL_MASK_ONLY) == 0; for( i = 0; i < cn; i++ ) { - if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 ) + if( loDiff[i] < 0 || upDiff[i] < 0 ) CV_Error( CV_StsBadArg, "lo_diff and up_diff must be non-negative" ); - is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON; + is_simple = is_simple && fabs(loDiff[i]) < DBL_EPSILON && fabs(upDiff[i]) < DBL_EPSILON; } - size = cvGetMatSize( img ); - - if( (unsigned)seed_point.x >= (unsigned)size.width || - (unsigned)seed_point.y >= (unsigned)size.height ) + if( (unsigned)seedPoint.x >= (unsigned)size.width || + (unsigned)seedPoint.y >= (unsigned)size.height ) CV_Error( CV_StsOutOfRange, "Seed point is outside of image" ); - cvScalarToRawData( &newVal, &nv_buf, type, 0 ); - buffer_size = MAX( size.width, size.height ) * 2; + scalarToRawData( newVal, &nv_buf, type, 0); + size_t buffer_size = MAX( size.width, size.height ) * 2; buffer.resize( buffer_size ); if( is_simple ) { - int elem_size = CV_ELEM_SIZE(type); - const uchar* seed_ptr = img->data.ptr + img->step*seed_point.y + elem_size*seed_point.x; + int elem_size = img.elemSize(); + const uchar* seed_ptr = img.data + img.step*seedPoint.y + elem_size*seedPoint.x; for(i = 0; i < elem_size; i++) if (seed_ptr[i] != nv_buf.b[i]) break; - if (i != elem_size) + if( i != elem_size ) { if( type == CV_8UC1 ) - icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.b[0], - comp, flags, &buffer); + floodFill_CnIR(img, seedPoint, nv_buf.b[0], &comp, flags, &buffer); else if( type == CV_8UC3 ) - icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3b(nv_buf.b), - comp, flags, &buffer); + floodFill_CnIR(img, seedPoint, Vec3b(nv_buf.b), &comp, flags, &buffer); else if( type == CV_32SC1 ) - icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.i[0], - comp, flags, &buffer); + floodFill_CnIR(img, seedPoint, nv_buf.i[0], &comp, flags, &buffer); else if( type == CV_32FC1 ) - icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.f[0], - comp, flags, &buffer); + floodFill_CnIR(img, seedPoint, nv_buf.f[0], &comp, flags, &buffer); else if( type == CV_32SC3 ) - icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3i(nv_buf.i), - comp, flags, &buffer); + floodFill_CnIR(img, seedPoint, Vec3i(nv_buf.i), &comp, flags, &buffer); else if( type == CV_32FC3 ) - icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3f(nv_buf.f), - comp, flags, &buffer); + floodFill_CnIR(img, seedPoint, Vec3f(nv_buf.f), &comp, flags, &buffer); else CV_Error( CV_StsUnsupportedFormat, "" ); - return; + if( rect ) + *rect = comp.rect; + return comp.area; } } - if( !mask ) + if( mask.empty() ) { - /* created mask will be 8-byte aligned */ - tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 ); + Mat tempMask( size.height + 2, size.width + 2, CV_8UC1 ); + tempMask.setTo(Scalar::all(0)); mask = tempMask; } else { - mask = cvGetMat( mask, &maskstub ); - if( !CV_IS_MASK_ARR( mask )) - CV_Error( CV_StsBadMask, "" ); - - if( mask->width != size.width + 2 || mask->height != size.height + 2 ) - CV_Error( CV_StsUnmatchedSizes, "mask must be 2 pixel wider " - "and 2 pixel taller than filled image" ); + CV_Assert( mask.rows == size.height+2 && mask.cols == size.width+2 ); + CV_Assert( mask.type() == CV_8U ); } - int width = tempMask ? mask->step : size.width + 2; - uchar* mask_row = mask->data.ptr + mask->step; - memset( mask_row - mask->step, 1, width ); + memset( mask.data, 1, mask.cols ); + memset( mask.data + mask.step*(mask.rows-1), 1, mask.cols ); - for( i = 1; i <= size.height; i++, mask_row += mask->step ) + for( i = 1; i <= size.height; i++ ) { - if( tempMask ) - memset( mask_row, 0, width ); - mask_row[0] = mask_row[size.width+1] = (uchar)1; + mask.at(i, 0) = mask.at(i, mask.cols-1) = (uchar)1; } - memset( mask_row, 1, width ); if( depth == CV_8U ) for( i = 0; i < cn; i++ ) { - int t = cvFloor(lo_diff.val[i]); - ld_buf.b[i] = CV_CAST_8U(t); - t = cvFloor(up_diff.val[i]); - ud_buf.b[i] = CV_CAST_8U(t); + ld_buf.b[i] = saturate_cast(cvFloor(loDiff[i])); + ud_buf.b[i] = saturate_cast(cvFloor(upDiff[i])); } else if( depth == CV_32S ) for( i = 0; i < cn; i++ ) { - int t = cvFloor(lo_diff.val[i]); - ld_buf.i[i] = t; - t = cvFloor(up_diff.val[i]); - ud_buf.i[i] = t; + ld_buf.i[i] = cvFloor(loDiff[i]); + ud_buf.i[i] = cvFloor(upDiff[i]); } else if( depth == CV_32F ) for( i = 0; i < cn; i++ ) { - ld_buf.f[i] = (float)lo_diff.val[i]; - ud_buf.f[i] = (float)up_diff.val[i]; + ld_buf.f[i] = (float)loDiff[i]; + ud_buf.f[i] = (float)upDiff[i]; } else CV_Error( CV_StsUnsupportedFormat, "" ); + uchar newMaskVal = (uchar)((flags & ~0xff) == 0 ? 1 : ((flags >> 8) & 255)); + if( type == CV_8UC1 ) - icvFloodFillGrad_CnIR( - img->data.ptr, img->step, mask->data.ptr, mask->step, - size, seed_point, nv_buf.b[0], - Diff8uC1(ld_buf.b[0], ud_buf.b[0]), - comp, flags, &buffer); + floodFillGrad_CnIR( + img, mask, seedPoint, nv_buf.b[0], newMaskVal, + Diff8uC1(ld_buf.b[0], ud_buf.b[0]), + &comp, flags, &buffer); else if( type == CV_8UC3 ) - icvFloodFillGrad_CnIR( - img->data.ptr, img->step, mask->data.ptr, mask->step, - size, seed_point, cv::Vec3b(nv_buf.b), - Diff8uC3(ld_buf.b, ud_buf.b), - comp, flags, &buffer); + floodFillGrad_CnIR( + img, mask, seedPoint, Vec3b(nv_buf.b), newMaskVal, + Diff8uC3(ld_buf.b, ud_buf.b), + &comp, flags, &buffer); else if( type == CV_32SC1 ) - icvFloodFillGrad_CnIR( - img->data.ptr, img->step, mask->data.ptr, mask->step, - size, seed_point, nv_buf.i[0], - Diff32sC1(ld_buf.i[0], ud_buf.i[0]), - comp, flags, &buffer); + floodFillGrad_CnIR( + img, mask, seedPoint, nv_buf.i[0], newMaskVal, + Diff32sC1(ld_buf.i[0], ud_buf.i[0]), + &comp, flags, &buffer); else if( type == CV_32SC3 ) - icvFloodFillGrad_CnIR( - img->data.ptr, img->step, mask->data.ptr, mask->step, - size, seed_point, cv::Vec3i(nv_buf.i), - Diff32sC3(ld_buf.i, ud_buf.i), - comp, flags, &buffer); + floodFillGrad_CnIR( + img, mask, seedPoint, Vec3i(nv_buf.i), newMaskVal, + Diff32sC3(ld_buf.i, ud_buf.i), + &comp, flags, &buffer); else if( type == CV_32FC1 ) - icvFloodFillGrad_CnIR( - img->data.ptr, img->step, mask->data.ptr, mask->step, - size, seed_point, nv_buf.f[0], - Diff32fC1(ld_buf.f[0], ud_buf.f[0]), - comp, flags, &buffer); + floodFillGrad_CnIR( + img, mask, seedPoint, nv_buf.f[0], newMaskVal, + Diff32fC1(ld_buf.f[0], ud_buf.f[0]), + &comp, flags, &buffer); else if( type == CV_32FC3 ) - icvFloodFillGrad_CnIR( - img->data.ptr, img->step, mask->data.ptr, mask->step, - size, seed_point, cv::Vec3f(nv_buf.f), - Diff32fC3(ld_buf.f, ud_buf.f), - comp, flags, &buffer); + floodFillGrad_CnIR( + img, mask, seedPoint, Vec3f(nv_buf.f), newMaskVal, + Diff32fC3(ld_buf.f, ud_buf.f), + &comp, flags, &buffer); else CV_Error(CV_StsUnsupportedFormat, ""); + + if( rect ) + *rect = comp.rect; + return comp.area; } int cv::floodFill( InputOutputArray _image, Point seedPoint, - Scalar newVal, Rect* rect, - Scalar loDiff, Scalar upDiff, int flags ) + Scalar newVal, Rect* rect, + Scalar loDiff, Scalar upDiff, int flags ) { - CvConnectedComp ccomp; - CvMat c_image = _image.getMat(); - cvFloodFill(&c_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, 0); - if( rect ) - *rect = ccomp.rect; - return cvRound(ccomp.area); + return floodFill(_image, Mat(), seedPoint, newVal, rect, loDiff, upDiff, flags); } -int cv::floodFill( InputOutputArray _image, InputOutputArray _mask, - Point seedPoint, Scalar newVal, Rect* rect, - Scalar loDiff, Scalar upDiff, int flags ) + +CV_IMPL void +cvFloodFill( CvArr* arr, CvPoint seed_point, + CvScalar newVal, CvScalar lo_diff, CvScalar up_diff, + CvConnectedComp* comp, int flags, CvArr* maskarr ) { - CvConnectedComp ccomp; - CvMat c_image = _image.getMat(), c_mask = _mask.getMat(); - cvFloodFill(&c_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, c_mask.data.ptr ? &c_mask : 0); - if( rect ) - *rect = ccomp.rect; - return cvRound(ccomp.area); + if( comp ) + memset( comp, 0, sizeof(*comp) ); + + cv::Mat img = cv::cvarrToMat(arr), mask = cv::cvarrToMat(maskarr); + int area = cv::floodFill(img, mask, seed_point, newVal, + comp ? (cv::Rect*)&comp->rect : 0, + lo_diff, up_diff, flags ); + if( comp ) + { + comp->area = area; + comp->value = newVal; + } } /* End of file. */ diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 682f6d0d29..623b0eb6a2 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -2891,10 +2891,10 @@ class RemapInvoker : { public: RemapInvoker(const Mat& _src, Mat& _dst, const Mat *_m1, - const Mat *_m2, int _interpolation, int _borderType, const Scalar &_borderValue, + const Mat *_m2, int _borderType, const Scalar &_borderValue, int _planar_input, RemapNNFunc _nnfunc, RemapFunc _ifunc, const void *_ctab) : ParallelLoopBody(), src(&_src), dst(&_dst), m1(_m1), m2(_m2), - interpolation(_interpolation), borderType(_borderType), borderValue(_borderValue), + borderType(_borderType), borderValue(_borderValue), planar_input(_planar_input), nnfunc(_nnfunc), ifunc(_ifunc), ctab(_ctab) { } @@ -3077,7 +3077,7 @@ private: const Mat* src; Mat* dst; const Mat *m1, *m2; - int interpolation, borderType; + int borderType; Scalar borderValue; int planar_input; RemapNNFunc nnfunc; @@ -3178,7 +3178,7 @@ void cv::remap( InputArray _src, OutputArray _dst, planar_input = map1.channels() == 1; } - RemapInvoker invoker(src, dst, m1, m2, interpolation, + RemapInvoker invoker(src, dst, m1, m2, borderType, borderValue, planar_input, nnfunc, ifunc, ctab); parallel_for_(Range(0, dst.rows), invoker, dst.total()/(double)(1<<16)); diff --git a/modules/imgproc/src/precomp.hpp b/modules/imgproc/src/precomp.hpp index 842a15ceaf..dc2650bf41 100644 --- a/modules/imgproc/src/precomp.hpp +++ b/modules/imgproc/src/precomp.hpp @@ -116,41 +116,12 @@ CvPyramid; #define CV_SET( dst, val, len, idx ) \ for( (idx) = 0; (idx) < (len); (idx)++) (dst)[idx] = (val) -/* performs convolution of 2d floating-point array with 3x1, 1x3 or separable 3x3 mask */ -void icvSepConvSmall3_32f( float* src, int src_step, float* dst, int dst_step, - CvSize src_size, const float* kx, const float* ky, float* buffer ); - #undef CV_CALC_MIN #define CV_CALC_MIN(a, b) if((a) > (b)) (a) = (b) #undef CV_CALC_MAX #define CV_CALC_MAX(a, b) if((a) < (b)) (a) = (b) -CvStatus CV_STDCALL -icvCopyReplicateBorder_8u( const uchar* src, int srcstep, CvSize srcroi, - uchar* dst, int dststep, CvSize dstroi, - int left, int right, int cn, const uchar* value = 0 ); - -CvStatus CV_STDCALL icvGetRectSubPix_8u_C1R -( const uchar* src, int src_step, CvSize src_size, - uchar* dst, int dst_step, CvSize win_size, CvPoint2D32f center ); -CvStatus CV_STDCALL icvGetRectSubPix_8u32f_C1R -( const uchar* src, int src_step, CvSize src_size, - float* dst, int dst_step, CvSize win_size, CvPoint2D32f center ); -CvStatus CV_STDCALL icvGetRectSubPix_32f_C1R -( const float* src, int src_step, CvSize src_size, - float* dst, int dst_step, CvSize win_size, CvPoint2D32f center ); - -CvStatus CV_STDCALL icvGetQuadrangleSubPix_8u_C1R -( const uchar* src, int src_step, CvSize src_size, - uchar* dst, int dst_step, CvSize win_size, const float *matrix ); -CvStatus CV_STDCALL icvGetQuadrangleSubPix_8u32f_C1R -( const uchar* src, int src_step, CvSize src_size, - float* dst, int dst_step, CvSize win_size, const float *matrix ); -CvStatus CV_STDCALL icvGetQuadrangleSubPix_32f_C1R -( const float* src, int src_step, CvSize src_size, - float* dst, int dst_step, CvSize win_size, const float *matrix ); - #include "_geom.h" #endif /*__OPENCV_CV_INTERNAL_H_*/ diff --git a/modules/imgproc/src/samplers.cpp b/modules/imgproc/src/samplers.cpp index e6d2d1214e..38df5d0ddd 100644 --- a/modules/imgproc/src/samplers.cpp +++ b/modules/imgproc/src/samplers.cpp @@ -7,10 +7,11 @@ // copy or use the software. // // -// Intel License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -23,7 +24,7 @@ // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -// * The name of Intel Corporation may not be used to endorse or promote products +// * The name of the copyright holders may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and @@ -41,49 +42,15 @@ #include "precomp.hpp" -/**************************************************************************************\ -* line samplers * -\**************************************************************************************/ - -CV_IMPL int -cvSampleLine( const void* img, CvPoint pt1, CvPoint pt2, - void* _buffer, int connectivity ) +namespace cv { - int count = -1; - - int i, coi = 0, pix_size; - CvMat stub, *mat = cvGetMat( img, &stub, &coi ); - CvLineIterator iterator; - uchar* buffer = (uchar*)_buffer; - - if( coi != 0 ) - CV_Error( CV_BadCOI, "" ); - - if( !buffer ) - CV_Error( CV_StsNullPtr, "" ); - - count = cvInitLineIterator( mat, pt1, pt2, &iterator, connectivity ); - - pix_size = CV_ELEM_SIZE(mat->type); - for( i = 0; i < count; i++ ) - { - for( int j = 0; j < pix_size; j++ ) - buffer[j] = iterator.ptr[j]; - buffer += pix_size; - CV_NEXT_LINE_POINT( iterator ); - } - - return count; -} - -static const void* -icvAdjustRect( const void* srcptr, int src_step, int pix_size, - CvSize src_size, CvSize win_size, - CvPoint ip, CvRect* pRect ) +static const uchar* +adjustRect( const uchar* src, int src_step, int pix_size, + Size src_size, Size win_size, + Point ip, Rect* pRect ) { - CvRect rect; - const char* src = (const char*)srcptr; + Rect rect; if( ip.x >= 0 ) { @@ -135,256 +102,40 @@ icvAdjustRect( const void* srcptr, int src_step, int pix_size, } -#define ICV_DEF_GET_RECT_SUB_PIX_FUNC( flavor, srctype, dsttype, worktype, \ - cast_macro, scale_macro, cast_macro2 )\ -CvStatus CV_STDCALL icvGetRectSubPix_##flavor##_C1R \ -( const srctype* src, int src_step, CvSize src_size, \ - dsttype* dst, int dst_step, CvSize win_size, CvPoint2D32f center ) \ -{ \ - CvPoint ip; \ - worktype a11, a12, a21, a22, b1, b2; \ - float a, b; \ - int i, j; \ - \ - center.x -= (win_size.width-1)*0.5f; \ - center.y -= (win_size.height-1)*0.5f; \ - \ - ip.x = cvFloor( center.x ); \ - ip.y = cvFloor( center.y ); \ - \ - a = center.x - ip.x; \ - b = center.y - ip.y; \ - a11 = scale_macro((1.f-a)*(1.f-b)); \ - a12 = scale_macro(a*(1.f-b)); \ - a21 = scale_macro((1.f-a)*b); \ - a22 = scale_macro(a*b); \ - b1 = scale_macro(1.f - b); \ - b2 = scale_macro(b); \ - \ - src_step /= sizeof(src[0]); \ - dst_step /= sizeof(dst[0]); \ - \ - if( 0 <= ip.x && ip.x + win_size.width < src_size.width && \ - 0 <= ip.y && ip.y + win_size.height < src_size.height ) \ - { \ - /* extracted rectangle is totally inside the image */ \ - src += ip.y * src_step + ip.x; \ - \ - for( i = 0; i < win_size.height; i++, src += src_step, \ - dst += dst_step ) \ - { \ - for( j = 0; j <= win_size.width - 2; j += 2 ) \ - { \ - worktype s0 = cast_macro(src[j])*a11 + \ - cast_macro(src[j+1])*a12 + \ - cast_macro(src[j+src_step])*a21 + \ - cast_macro(src[j+src_step+1])*a22; \ - worktype s1 = cast_macro(src[j+1])*a11 + \ - cast_macro(src[j+2])*a12 + \ - cast_macro(src[j+src_step+1])*a21 + \ - cast_macro(src[j+src_step+2])*a22; \ - \ - dst[j] = (dsttype)cast_macro2(s0); \ - dst[j+1] = (dsttype)cast_macro2(s1); \ - } \ - \ - for( ; j < win_size.width; j++ ) \ - { \ - worktype s0 = cast_macro(src[j])*a11 + \ - cast_macro(src[j+1])*a12 + \ - cast_macro(src[j+src_step])*a21 + \ - cast_macro(src[j+src_step+1])*a22; \ - \ - dst[j] = (dsttype)cast_macro2(s0); \ - } \ - } \ - } \ - else \ - { \ - CvRect r; \ - \ - src = (const srctype*)icvAdjustRect( src, src_step*sizeof(*src), \ - sizeof(*src), src_size, win_size,ip, &r); \ - \ - for( i = 0; i < win_size.height; i++, dst += dst_step ) \ - { \ - const srctype *src2 = src + src_step; \ - \ - if( i < r.y || i >= r.height ) \ - src2 -= src_step; \ - \ - for( j = 0; j < r.x; j++ ) \ - { \ - worktype s0 = cast_macro(src[r.x])*b1 + \ - cast_macro(src2[r.x])*b2; \ - \ - dst[j] = (dsttype)cast_macro2(s0); \ - } \ - \ - for( ; j < r.width; j++ ) \ - { \ - worktype s0 = cast_macro(src[j])*a11 + \ - cast_macro(src[j+1])*a12 + \ - cast_macro(src2[j])*a21 + \ - cast_macro(src2[j+1])*a22; \ - \ - dst[j] = (dsttype)cast_macro2(s0); \ - } \ - \ - for( ; j < win_size.width; j++ ) \ - { \ - worktype s0 = cast_macro(src[r.width])*b1 + \ - cast_macro(src2[r.width])*b2; \ - \ - dst[j] = (dsttype)cast_macro2(s0); \ - } \ - \ - if( i < r.height ) \ - src = src2; \ - } \ - } \ - \ - return CV_OK; \ -} +enum { SUBPIX_SHIFT=16 }; +struct scale_fixpt +{ + int operator()(float a) const { return cvRound(a*(1 << SUBPIX_SHIFT)); } +}; -#define ICV_DEF_GET_RECT_SUB_PIX_FUNC_C3( flavor, srctype, dsttype, worktype, \ - cast_macro, scale_macro, mul_macro )\ -static CvStatus CV_STDCALL icvGetRectSubPix_##flavor##_C3R \ -( const srctype* src, int src_step, CvSize src_size, \ - dsttype* dst, int dst_step, CvSize win_size, CvPoint2D32f center ) \ -{ \ - CvPoint ip; \ - worktype a, b; \ - int i, j; \ - \ - center.x -= (win_size.width-1)*0.5f; \ - center.y -= (win_size.height-1)*0.5f; \ - \ - ip.x = cvFloor( center.x ); \ - ip.y = cvFloor( center.y ); \ - \ - a = scale_macro( center.x - ip.x ); \ - b = scale_macro( center.y - ip.y ); \ - \ - src_step /= sizeof( src[0] ); \ - dst_step /= sizeof( dst[0] ); \ - \ - if( 0 <= ip.x && ip.x + win_size.width < src_size.width && \ - 0 <= ip.y && ip.y + win_size.height < src_size.height ) \ - { \ - /* extracted rectangle is totally inside the image */ \ - src += ip.y * src_step + ip.x*3; \ - \ - for( i = 0; i < win_size.height; i++, src += src_step, \ - dst += dst_step ) \ - { \ - for( j = 0; j < win_size.width; j++ ) \ - { \ - worktype s0 = cast_macro(src[j*3]); \ - worktype s1 = cast_macro(src[j*3 + src_step]); \ - s0 += mul_macro( a, (cast_macro(src[j*3+3]) - s0)); \ - s1 += mul_macro( a, (cast_macro(src[j*3+3+src_step]) - s1));\ - dst[j*3] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[j*3+1]); \ - s1 = cast_macro(src[j*3+1 + src_step]); \ - s0 += mul_macro( a, (cast_macro(src[j*3+4]) - s0)); \ - s1 += mul_macro( a, (cast_macro(src[j*3+4+src_step]) - s1));\ - dst[j*3+1] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[j*3+2]); \ - s1 = cast_macro(src[j*3+2 + src_step]); \ - s0 += mul_macro( a, (cast_macro(src[j*3+5]) - s0)); \ - s1 += mul_macro( a, (cast_macro(src[j*3+5+src_step]) - s1));\ - dst[j*3+2] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - } \ - } \ - } \ - else \ - { \ - CvRect r; \ - \ - src = (const srctype*)icvAdjustRect( src, src_step*sizeof(*src), \ - sizeof(*src)*3, src_size, win_size, ip, &r ); \ - \ - for( i = 0; i < win_size.height; i++, dst += dst_step ) \ - { \ - const srctype *src2 = src + src_step; \ - \ - if( i < r.y || i >= r.height ) \ - src2 -= src_step; \ - \ - for( j = 0; j < r.x; j++ ) \ - { \ - worktype s0 = cast_macro(src[r.x*3]); \ - worktype s1 = cast_macro(src2[r.x*3]); \ - dst[j*3] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[r.x*3+1]); \ - s1 = cast_macro(src2[r.x*3+1]); \ - dst[j*3+1] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[r.x*3+2]); \ - s1 = cast_macro(src2[r.x*3+2]); \ - dst[j*3+2] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - } \ - \ - for( ; j < r.width; j++ ) \ - { \ - worktype s0 = cast_macro(src[j*3]); \ - worktype s1 = cast_macro(src2[j*3]); \ - s0 += mul_macro( a, (cast_macro(src[j*3 + 3]) - s0)); \ - s1 += mul_macro( a, (cast_macro(src2[j*3 + 3]) - s1)); \ - dst[j*3] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[j*3+1]); \ - s1 = cast_macro(src2[j*3+1]); \ - s0 += mul_macro( a, (cast_macro(src[j*3 + 4]) - s0)); \ - s1 += mul_macro( a, (cast_macro(src2[j*3 + 4]) - s1)); \ - dst[j*3+1] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[j*3+2]); \ - s1 = cast_macro(src2[j*3+2]); \ - s0 += mul_macro( a, (cast_macro(src[j*3 + 5]) - s0)); \ - s1 += mul_macro( a, (cast_macro(src2[j*3 + 5]) - s1)); \ - dst[j*3+2] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - } \ - \ - for( ; j < win_size.width; j++ ) \ - { \ - worktype s0 = cast_macro(src[r.width*3]); \ - worktype s1 = cast_macro(src2[r.width*3]); \ - dst[j*3] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[r.width*3+1]); \ - s1 = cast_macro(src2[r.width*3+1]); \ - dst[j*3+1] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - \ - s0 = cast_macro(src[r.width*3+2]); \ - s1 = cast_macro(src2[r.width*3+2]); \ - dst[j*3+2] = (dsttype)(s0 + mul_macro( b, (s1 - s0))); \ - } \ - \ - if( i < r.height ) \ - src = src2; \ - } \ - } \ - \ - return CV_OK; \ -} +struct cast_8u +{ + uchar operator()(int a) const { return (uchar)((a + (1 << (SUBPIX_SHIFT-1))) >> SUBPIX_SHIFT); } +}; +struct cast_flt_8u +{ + uchar operator()(float a) const { return (uchar)cvRound(a); } +}; + +template +struct nop +{ + _Tp operator()(_Tp a) const { return a; } +}; -CvStatus CV_STDCALL icvGetRectSubPix_8u32f_C1R -( const uchar* src, int src_step, CvSize src_size, - float* dst, int dst_step, CvSize win_size, CvPoint2D32f center ) +template +void getRectSubPix_Cn_(const _Tp* src, int src_step, Size src_size, + _DTp* dst, int dst_step, Size win_size, Point2f center, int cn ) { - CvPoint ip; - float a12, a22, b1, b2; + ScaleOp scale_op; + CastOp cast_op; + Point ip; + _WTp a11, a12, a21, a22, b1, b2; float a, b; - double s = 0; - int i, j; + int i, j, c; center.x -= (win_size.width-1)*0.5f; center.y -= (win_size.height-1)*0.5f; @@ -392,491 +143,207 @@ CvStatus CV_STDCALL icvGetRectSubPix_8u32f_C1R ip.x = cvFloor( center.x ); ip.y = cvFloor( center.y ); - if( win_size.width <= 0 || win_size.height <= 0 ) - return CV_BADRANGE_ERR; - a = center.x - ip.x; b = center.y - ip.y; - a = MAX(a,0.0001f); - a12 = a*(1.f-b); - a22 = a*b; - b1 = 1.f - b; - b2 = b; - s = (1. - a)/a; + a11 = scale_op((1.f-a)*(1.f-b)); + a12 = scale_op(a*(1.f-b)); + a21 = scale_op((1.f-a)*b); + a22 = scale_op(a*b); + b1 = scale_op(1.f - b); + b2 = scale_op(b); src_step /= sizeof(src[0]); dst_step /= sizeof(dst[0]); if( 0 <= ip.x && ip.x + win_size.width < src_size.width && - 0 <= ip.y && ip.y + win_size.height < src_size.height ) + 0 <= ip.y && ip.y + win_size.height < src_size.height ) { // extracted rectangle is totally inside the image - src += ip.y * src_step + ip.x; - -#if 0 - if( icvCopySubpix_8u32f_C1R_p && - icvCopySubpix_8u32f_C1R_p( src, src_step, dst, - dst_step*sizeof(dst[0]), win_size, a, b ) >= 0 ) - return CV_OK; -#endif + src += ip.y * src_step + ip.x*cn; + win_size.width *= cn; - for( ; win_size.height--; src += src_step, dst += dst_step ) + for( i = 0; i < win_size.height; i++, src += src_step, dst += dst_step ) { - float prev = (1 - a)*(b1*CV_8TO32F(src[0]) + b2*CV_8TO32F(src[src_step])); + for( j = 0; j <= win_size.width - 2; j += 2 ) + { + _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src[j+src_step]*a21 + src[j+src_step+cn]*a22; + _WTp s1 = src[j+1]*a11 + src[j+cn+1]*a12 + src[j+src_step+1]*a21 + src[j+src_step+cn+1]*a22; + dst[j] = cast_op(s0); + dst[j+1] = cast_op(s1); + } + for( j = 0; j < win_size.width; j++ ) { - float t = a12*CV_8TO32F(src[j+1]) + a22*CV_8TO32F(src[j+1+src_step]); - dst[j] = prev + t; - prev = (float)(t*s); + _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src[j+src_step]*a21 + src[j+src_step+cn]*a22; + dst[j] = cast_op(s0); } } } else { - CvRect r; - - src = (const uchar*)icvAdjustRect( src, src_step*sizeof(*src), - sizeof(*src), src_size, win_size,ip, &r); + Rect r; + src = (const _Tp*)adjustRect( (const uchar*)src, src_step*sizeof(*src), + sizeof(*src)*cn, src_size, win_size, ip, &r); for( i = 0; i < win_size.height; i++, dst += dst_step ) { - const uchar *src2 = src + src_step; + const _Tp *src2 = src + src_step; + _WTp s0; if( i < r.y || i >= r.height ) src2 -= src_step; - for( j = 0; j < r.x; j++ ) - { - float s0 = CV_8TO32F(src[r.x])*b1 + - CV_8TO32F(src2[r.x])*b2; - - dst[j] = (float)(s0); - } - - if( j < r.width ) + for( c = 0; c < cn; c++ ) { - float prev = (1 - a)*(b1*CV_8TO32F(src[j]) + b2*CV_8TO32F(src2[j])); - - for( ; j < r.width; j++ ) - { - float t = a12*CV_8TO32F(src[j+1]) + a22*CV_8TO32F(src2[j+1]); - dst[j] = prev + t; - prev = (float)(t*s); - } + s0 = src[r.x*cn + c]*b1 + src2[r.x*cn + c]*b2; + for( j = 0; j < r.x; j++ ) + dst[j*cn + c] = cast_op(s0); + s0 = src[r.width*cn + c]*b1 + src2[r.width*cn + c]*b2; + for( j = r.width; j < win_size.width; j++ ) + dst[j*cn + c] = cast_op(s0); } - for( ; j < win_size.width; j++ ) + for( j = r.x*cn; j < r.width*cn; j++ ) { - float s0 = CV_8TO32F(src[r.width])*b1 + - CV_8TO32F(src2[r.width])*b2; - - dst[j] = (float)(s0); + _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src2[j]*a21 + src2[j+cn]*a22; + dst[j] = cast_op(s0); } if( i < r.height ) src = src2; } } - - return CV_OK; -} - - - -#define ICV_SHIFT 16 -#define ICV_SCALE(x) cvRound((x)*(1 << ICV_SHIFT)) -#define ICV_MUL_SCALE(x,y) (((x)*(y) + (1 << (ICV_SHIFT-1))) >> ICV_SHIFT) -#define ICV_DESCALE(x) (((x)+(1 << (ICV_SHIFT-1))) >> ICV_SHIFT) - -/*icvCopySubpix_8u_C1R_t icvCopySubpix_8u_C1R_p = 0; -icvCopySubpix_8u32f_C1R_t icvCopySubpix_8u32f_C1R_p = 0; -icvCopySubpix_32f_C1R_t icvCopySubpix_32f_C1R_p = 0;*/ - -ICV_DEF_GET_RECT_SUB_PIX_FUNC( 8u, uchar, uchar, int, CV_NOP, ICV_SCALE, ICV_DESCALE ) -//ICV_DEF_GET_RECT_SUB_PIX_FUNC( 8u32f, uchar, float, float, CV_8TO32F, CV_NOP, CV_NOP ) -ICV_DEF_GET_RECT_SUB_PIX_FUNC( 32f, float, float, float, CV_NOP, CV_NOP, CV_NOP ) - -ICV_DEF_GET_RECT_SUB_PIX_FUNC_C3( 8u, uchar, uchar, int, CV_NOP, ICV_SCALE, ICV_MUL_SCALE ) -ICV_DEF_GET_RECT_SUB_PIX_FUNC_C3( 8u32f, uchar, float, float, CV_8TO32F, CV_NOP, CV_MUL ) -ICV_DEF_GET_RECT_SUB_PIX_FUNC_C3( 32f, float, float, float, CV_NOP, CV_NOP, CV_MUL ) - - -#define ICV_DEF_INIT_SUBPIX_TAB( FUNCNAME, FLAG ) \ -static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab ) \ -{ \ - tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##FLAG; \ - tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##FLAG; \ - \ - tab->fn_2d[1] = (void*)icv##FUNCNAME##_8u32f_##FLAG; \ } -ICV_DEF_INIT_SUBPIX_TAB( GetRectSubPix, C1R ) -ICV_DEF_INIT_SUBPIX_TAB( GetRectSubPix, C3R ) - -typedef CvStatus (CV_STDCALL *CvGetRectSubPixFunc)( const void* src, int src_step, - CvSize src_size, void* dst, - int dst_step, CvSize win_size, - CvPoint2D32f center ); - -CV_IMPL void -cvGetRectSubPix( const void* srcarr, void* dstarr, CvPoint2D32f center ) +static void getRectSubPix_8u32f +( const uchar* src, int src_step, Size src_size, + float* dst, int dst_step, Size win_size, Point2f center0, int cn ) { - static CvFuncTable gr_tab[2]; - static int inittab = 0; - - CvMat srcstub, *src = (CvMat*)srcarr; - CvMat dststub, *dst = (CvMat*)dstarr; - CvSize src_size, dst_size; - CvGetRectSubPixFunc func; - int cn, src_step, dst_step; - - if( !inittab ) - { - icvInitGetRectSubPixC1RTable( gr_tab + 0 ); - icvInitGetRectSubPixC3RTable( gr_tab + 1 ); - inittab = 1; - } + Point2f center = center0; + Point ip; - if( !CV_IS_MAT(src)) - src = cvGetMat( src, &srcstub ); - - if( !CV_IS_MAT(dst)) - dst = cvGetMat( dst, &dststub ); - - cn = CV_MAT_CN( src->type ); + center.x -= (win_size.width-1)*0.5f; + center.y -= (win_size.height-1)*0.5f; - if( (cn != 1 && cn != 3) || !CV_ARE_CNS_EQ( src, dst )) - CV_Error( CV_StsUnsupportedFormat, "" ); + ip.x = cvFloor( center.x ); + ip.y = cvFloor( center.y ); - src_size = cvGetMatSize( src ); - dst_size = cvGetMatSize( dst ); - src_step = src->step ? src->step : CV_STUB_STEP; - dst_step = dst->step ? dst->step : CV_STUB_STEP; + if( cn == 1 && + 0 <= ip.x && ip.x + win_size.width < src_size.width && + 0 <= ip.y && ip.y + win_size.height < src_size.height && + win_size.width > 0 && win_size.height > 0 ) + { + float a = center.x - ip.x; + float b = center.y - ip.y; + a = MAX(a,0.0001f); + float a12 = a*(1.f-b); + float a22 = a*b; + float b1 = 1.f - b; + float b2 = b; + double s = (1. - a)/a; + + src_step /= sizeof(src[0]); + dst_step /= sizeof(dst[0]); - //if( dst_size.width > src_size.width || dst_size.height > src_size.height ) - // CV_ERROR( CV_StsBadSize, "destination ROI must be smaller than source ROI" ); + // extracted rectangle is totally inside the image + src += ip.y * src_step + ip.x; - if( CV_ARE_DEPTHS_EQ( src, dst )) - { - func = (CvGetRectSubPixFunc)(gr_tab[cn != 1].fn_2d[CV_MAT_DEPTH(src->type)]); + for( ; win_size.height--; src += src_step, dst += dst_step ) + { + float prev = (1 - a)*(b1*src[0] + b2*src[src_step]); + for( int j = 0; j < win_size.width; j++ ) + { + float t = a12*src[j+1] + a22*src[j+1+src_step]; + dst[j] = prev + t; + prev = (float)(t*s); + } + } } else { - if( CV_MAT_DEPTH( src->type ) != CV_8U || CV_MAT_DEPTH( dst->type ) != CV_32F ) - CV_Error( CV_StsUnsupportedFormat, "" ); - - func = (CvGetRectSubPixFunc)(gr_tab[cn != 1].fn_2d[1]); + getRectSubPix_Cn_, nop > + (src, src_step, src_size, dst, dst_step, win_size, center0, cn ); } - - if( !func ) - CV_Error( CV_StsUnsupportedFormat, "" ); - - IPPI_CALL( func( src->data.ptr, src_step, src_size, - dst->data.ptr, dst_step, dst_size, center )); } - -#define ICV_32F8U(x) ((uchar)cvRound(x)) - -#define ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC( flavor, srctype, dsttype, \ - worktype, cast_macro, cvt ) \ -CvStatus CV_STDCALL \ -icvGetQuadrangleSubPix_##flavor##_C1R \ -( const srctype * src, int src_step, CvSize src_size, \ - dsttype *dst, int dst_step, CvSize win_size, const float *matrix ) \ -{ \ - int x, y; \ - double dx = (win_size.width - 1)*0.5; \ - double dy = (win_size.height - 1)*0.5; \ - double A11 = matrix[0], A12 = matrix[1], A13 = matrix[2]-A11*dx-A12*dy; \ - double A21 = matrix[3], A22 = matrix[4], A23 = matrix[5]-A21*dx-A22*dy; \ - \ - src_step /= sizeof(srctype); \ - dst_step /= sizeof(dsttype); \ - \ - for( y = 0; y < win_size.height; y++, dst += dst_step ) \ - { \ - double xs = A12*y + A13; \ - double ys = A22*y + A23; \ - double xe = A11*(win_size.width-1) + A12*y + A13; \ - double ye = A21*(win_size.width-1) + A22*y + A23; \ - \ - if( (unsigned)(cvFloor(xs)-1) < (unsigned)(src_size.width - 3) && \ - (unsigned)(cvFloor(ys)-1) < (unsigned)(src_size.height - 3) && \ - (unsigned)(cvFloor(xe)-1) < (unsigned)(src_size.width - 3) && \ - (unsigned)(cvFloor(ye)-1) < (unsigned)(src_size.height - 3)) \ - { \ - for( x = 0; x < win_size.width; x++ ) \ - { \ - int ixs = cvFloor( xs ); \ - int iys = cvFloor( ys ); \ - const srctype *ptr = src + src_step*iys + ixs; \ - double a = xs - ixs, b = ys - iys, a1 = 1.f - a; \ - worktype p0 = cvt(ptr[0])*a1 + cvt(ptr[1])*a; \ - worktype p1 = cvt(ptr[src_step])*a1 + cvt(ptr[src_step+1])*a;\ - xs += A11; \ - ys += A21; \ - \ - dst[x] = cast_macro(p0 + b * (p1 - p0)); \ - } \ - } \ - else \ - { \ - for( x = 0; x < win_size.width; x++ ) \ - { \ - int ixs = cvFloor( xs ), iys = cvFloor( ys ); \ - double a = xs - ixs, b = ys - iys, a1 = 1.f - a; \ - const srctype *ptr0, *ptr1; \ - worktype p0, p1; \ - xs += A11; ys += A21; \ - \ - if( (unsigned)iys < (unsigned)(src_size.height-1) ) \ - ptr0 = src + src_step*iys, ptr1 = ptr0 + src_step; \ - else \ - ptr0 = ptr1 = src + (iys < 0 ? 0 : src_size.height-1)*src_step; \ - \ - if( (unsigned)ixs < (unsigned)(src_size.width-1) ) \ - { \ - p0 = cvt(ptr0[ixs])*a1 + cvt(ptr0[ixs+1])*a; \ - p1 = cvt(ptr1[ixs])*a1 + cvt(ptr1[ixs+1])*a; \ - } \ - else \ - { \ - ixs = ixs < 0 ? 0 : src_size.width - 1; \ - p0 = cvt(ptr0[ixs]); p1 = cvt(ptr1[ixs]); \ - } \ - dst[x] = cast_macro(p0 + b * (p1 - p0)); \ - } \ - } \ - } \ - \ - return CV_OK; \ } - -#define ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC_C3( flavor, srctype, dsttype, \ - worktype, cast_macro, cvt ) \ -static CvStatus CV_STDCALL \ -icvGetQuadrangleSubPix_##flavor##_C3R \ -( const srctype * src, int src_step, CvSize src_size, \ - dsttype *dst, int dst_step, CvSize win_size, const float *matrix ) \ -{ \ - int x, y; \ - double dx = (win_size.width - 1)*0.5; \ - double dy = (win_size.height - 1)*0.5; \ - double A11 = matrix[0], A12 = matrix[1], A13 = matrix[2]-A11*dx-A12*dy; \ - double A21 = matrix[3], A22 = matrix[4], A23 = matrix[5]-A21*dx-A22*dy; \ - \ - src_step /= sizeof(srctype); \ - dst_step /= sizeof(dsttype); \ - \ - for( y = 0; y < win_size.height; y++, dst += dst_step ) \ - { \ - double xs = A12*y + A13; \ - double ys = A22*y + A23; \ - double xe = A11*(win_size.width-1) + A12*y + A13; \ - double ye = A21*(win_size.width-1) + A22*y + A23; \ - \ - if( (unsigned)(cvFloor(xs)-1) < (unsigned)(src_size.width - 3) && \ - (unsigned)(cvFloor(ys)-1) < (unsigned)(src_size.height - 3) && \ - (unsigned)(cvFloor(xe)-1) < (unsigned)(src_size.width - 3) && \ - (unsigned)(cvFloor(ye)-1) < (unsigned)(src_size.height - 3)) \ - { \ - for( x = 0; x < win_size.width; x++ ) \ - { \ - int ixs = cvFloor( xs ); \ - int iys = cvFloor( ys ); \ - const srctype *ptr = src + src_step*iys + ixs*3; \ - double a = xs - ixs, b = ys - iys, a1 = 1.f - a; \ - worktype p0, p1; \ - xs += A11; \ - ys += A21; \ - \ - p0 = cvt(ptr[0])*a1 + cvt(ptr[3])*a; \ - p1 = cvt(ptr[src_step])*a1 + cvt(ptr[src_step+3])*a; \ - dst[x*3] = cast_macro(p0 + b * (p1 - p0)); \ - \ - p0 = cvt(ptr[1])*a1 + cvt(ptr[4])*a; \ - p1 = cvt(ptr[src_step+1])*a1 + cvt(ptr[src_step+4])*a; \ - dst[x*3+1] = cast_macro(p0 + b * (p1 - p0)); \ - \ - p0 = cvt(ptr[2])*a1 + cvt(ptr[5])*a; \ - p1 = cvt(ptr[src_step+2])*a1 + cvt(ptr[src_step+5])*a; \ - dst[x*3+2] = cast_macro(p0 + b * (p1 - p0)); \ - } \ - } \ - else \ - { \ - for( x = 0; x < win_size.width; x++ ) \ - { \ - int ixs = cvFloor(xs), iys = cvFloor(ys); \ - double a = xs - ixs, b = ys - iys; \ - const srctype *ptr0, *ptr1; \ - xs += A11; ys += A21; \ - \ - if( (unsigned)iys < (unsigned)(src_size.height-1) ) \ - ptr0 = src + src_step*iys, ptr1 = ptr0 + src_step; \ - else \ - ptr0 = ptr1 = src + (iys < 0 ? 0 : src_size.height-1)*src_step; \ - \ - if( (unsigned)ixs < (unsigned)(src_size.width - 1) ) \ - { \ - double a1 = 1.f - a; \ - worktype p0, p1; \ - ptr0 += ixs*3; ptr1 += ixs*3; \ - p0 = cvt(ptr0[0])*a1 + cvt(ptr0[3])*a; \ - p1 = cvt(ptr1[0])*a1 + cvt(ptr1[3])*a; \ - dst[x*3] = cast_macro(p0 + b * (p1 - p0)); \ - \ - p0 = cvt(ptr0[1])*a1 + cvt(ptr0[4])*a; \ - p1 = cvt(ptr1[1])*a1 + cvt(ptr1[4])*a; \ - dst[x*3+1] = cast_macro(p0 + b * (p1 - p0)); \ - \ - p0 = cvt(ptr0[2])*a1 + cvt(ptr0[5])*a; \ - p1 = cvt(ptr1[2])*a1 + cvt(ptr1[5])*a; \ - dst[x*3+2] = cast_macro(p0 + b * (p1 - p0)); \ - } \ - else \ - { \ - double b1 = 1.f - b; \ - ixs = ixs < 0 ? 0 : src_size.width - 1; \ - ptr0 += ixs*3; ptr1 += ixs*3; \ - \ - dst[x*3] = cast_macro(cvt(ptr0[0])*b1 + cvt(ptr1[0])*b);\ - dst[x*3+1]=cast_macro(cvt(ptr0[1])*b1 + cvt(ptr1[1])*b);\ - dst[x*3+2]=cast_macro(cvt(ptr0[2])*b1 + cvt(ptr1[2])*b);\ - } \ - } \ - } \ - } \ - \ - return CV_OK; \ +void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, + OutputArray _patch, int patchType ) +{ + Mat image = _image.getMat(); + int depth = image.depth(), cn = image.channels(); + int ddepth = patchType < 0 ? depth : CV_MAT_DEPTH(patchType); + + CV_Assert( cn == 1 || cn == 3 ); + + _patch.create(patchSize, CV_MAKETYPE(ddepth, cn)); + Mat patch = _patch.getMat(); + + if( depth == CV_8U && ddepth == CV_8U ) + getRectSubPix_Cn_ + (image.data, image.step, image.size(), patch.data, patch.step, patch.size(), center, cn); + else if( depth == CV_8U && ddepth == CV_32F ) + getRectSubPix_8u32f + (image.data, image.step, image.size(), (float*)patch.data, patch.step, patch.size(), center, cn); + else if( depth == CV_32F && ddepth == CV_32F ) + getRectSubPix_Cn_, nop > + ((const float*)image.data, image.step, image.size(), (float*)patch.data, patch.step, patch.size(), center, cn); + else + CV_Error( CV_StsUnsupportedFormat, "Unsupported combination of input and output formats"); } -/*#define srctype uchar -#define dsttype uchar -#define worktype float -#define cvt CV_8TO32F -#define cast_macro ICV_32F8U - -#undef srctype -#undef dsttype -#undef worktype -#undef cvt -#undef cast_macro*/ - -ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC( 8u, uchar, uchar, double, ICV_32F8U, CV_8TO32F ) -ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC( 32f, float, float, double, CV_CAST_32F, CV_NOP ) -ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC( 8u32f, uchar, float, double, CV_CAST_32F, CV_8TO32F ) - -ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC_C3( 8u, uchar, uchar, double, ICV_32F8U, CV_8TO32F ) -ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC_C3( 32f, float, float, double, CV_CAST_32F, CV_NOP ) -ICV_DEF_GET_QUADRANGLE_SUB_PIX_FUNC_C3( 8u32f, uchar, float, double, CV_CAST_32F, CV_8TO32F ) +CV_IMPL void +cvGetRectSubPix( const void* srcarr, void* dstarr, CvPoint2D32f center ) +{ + cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); + CV_Assert( src.channels() == dst.channels() ); -ICV_DEF_INIT_SUBPIX_TAB( GetQuadrangleSubPix, C1R ) -ICV_DEF_INIT_SUBPIX_TAB( GetQuadrangleSubPix, C3R ) + cv::getRectSubPix(src, dst.size(), center, dst, dst.type()); +} -typedef CvStatus (CV_STDCALL *CvGetQuadrangleSubPixFunc)( - const void* src, int src_step, - CvSize src_size, void* dst, - int dst_step, CvSize win_size, - const float* matrix ); CV_IMPL void cvGetQuadrangleSubPix( const void* srcarr, void* dstarr, const CvMat* mat ) { - static CvFuncTable gq_tab[2]; - static int inittab = 0; - - CvMat srcstub, *src = (CvMat*)srcarr; - CvMat dststub, *dst = (CvMat*)dstarr; - CvSize src_size, dst_size; - CvGetQuadrangleSubPixFunc func; - float m[6]; - int k, cn; - - if( !inittab ) - { - icvInitGetQuadrangleSubPixC1RTable( gq_tab + 0 ); - icvInitGetQuadrangleSubPixC3RTable( gq_tab + 1 ); - inittab = 1; - } - - if( !CV_IS_MAT(src)) - src = cvGetMat( src, &srcstub ); - - if( !CV_IS_MAT(dst)) - dst = cvGetMat( dst, &dststub ); - - if( !CV_IS_MAT(mat)) - CV_Error( CV_StsBadArg, "map matrix is not valid" ); - - cn = CV_MAT_CN( src->type ); - - if( (cn != 1 && cn != 3) || !CV_ARE_CNS_EQ( src, dst )) - CV_Error( CV_StsUnsupportedFormat, "" ); - - src_size = cvGetMatSize( src ); - dst_size = cvGetMatSize( dst ); - - /*if( dst_size.width > src_size.width || dst_size.height > src_size.height ) - CV_ERROR( CV_StsBadSize, "destination ROI must not be larger than source ROI" );*/ + cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), m = cv::cvarrToMat(mat); + cv::Size win_size = dst.size(); + double matrix[6]; + cv::Mat M(2, 3, CV_64F, matrix); + m.convertTo(M, CV_64F); + double dx = (win_size.width - 1)*0.5; + double dy = (win_size.height - 1)*0.5; + matrix[2] -= matrix[0]*dx + matrix[1]*dy; + matrix[5] -= matrix[3]*dx + matrix[4]*dy; + + cv::warpAffine(src, dst, M, dst.size(), + cv::INTER_LINEAR + cv::WARP_INVERSE_MAP, + cv::BORDER_REPLICATE); +} - if( mat->rows != 2 || mat->cols != 3 ) - CV_Error( CV_StsBadArg, - "Transformation matrix must be 2x3" ); - if( CV_MAT_TYPE( mat->type ) == CV_32FC1 ) - { - for( k = 0; k < 3; k++ ) - { - m[k] = mat->data.fl[k]; - m[3 + k] = ((float*)(mat->data.ptr + mat->step))[k]; - } - } - else if( CV_MAT_TYPE( mat->type ) == CV_64FC1 ) - { - for( k = 0; k < 3; k++ ) - { - m[k] = (float)mat->data.db[k]; - m[3 + k] = (float)((double*)(mat->data.ptr + mat->step))[k]; - } - } - else - CV_Error( CV_StsUnsupportedFormat, - "The transformation matrix should have 32fC1 or 64fC1 type" ); +CV_IMPL int +cvSampleLine( const void* _img, CvPoint pt1, CvPoint pt2, + void* _buffer, int connectivity ) +{ + cv::Mat img = cv::cvarrToMat(_img); + cv::LineIterator li(img, pt1, pt2, connectivity, false); + uchar* buffer = (uchar*)_buffer; + size_t pixsize = img.elemSize(); + + if( !buffer ) + CV_Error( CV_StsNullPtr, "" ); - if( CV_ARE_DEPTHS_EQ( src, dst )) - { - func = (CvGetQuadrangleSubPixFunc)(gq_tab[cn != 1].fn_2d[CV_MAT_DEPTH(src->type)]); - } - else + for( int i = 0; i < li.count; i++, ++li ) { - if( CV_MAT_DEPTH( src->type ) != CV_8U || CV_MAT_DEPTH( dst->type ) != CV_32F ) - CV_Error( CV_StsUnsupportedFormat, "" ); - - func = (CvGetQuadrangleSubPixFunc)(gq_tab[cn != 1].fn_2d[1]); + for( size_t k = 0; k < pixsize; k++ ) + *buffer++ = li.ptr[k]; } - if( !func ) - CV_Error( CV_StsUnsupportedFormat, "" ); - - IPPI_CALL( func( src->data.ptr, src->step, src_size, - dst->data.ptr, dst->step, dst_size, m )); + return li.count; } -void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, - OutputArray _patch, int patchType ) -{ - Mat image = _image.getMat(); - _patch.create(patchSize, patchType < 0 ? image.type() : - CV_MAKETYPE(CV_MAT_DEPTH(patchType),image.channels())); - Mat patch = _patch.getMat(); - CvMat _cimage = image, _cpatch = patch; - cvGetRectSubPix(&_cimage, &_cpatch, center); -} - /* End of file. */ diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 06906dc015..6e80b3b2ae 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -699,7 +699,6 @@ public: private: Mat src; Mat dst; - int nStripes; double thresh; double maxval; diff --git a/modules/imgproc/test/test_floodfill.cpp b/modules/imgproc/test/test_floodfill.cpp index e46e9e120c..558aa322b6 100644 --- a/modules/imgproc/test/test_floodfill.cpp +++ b/modules/imgproc/test/test_floodfill.cpp @@ -490,6 +490,7 @@ _exit_: comp[2] = r.y; comp[3] = r.width - r.x + 1; comp[4] = r.height - r.y + 1; +#if 0 if( mask_only ) { double t = area ? 1./area : 0; @@ -500,6 +501,11 @@ _exit_: comp[5] = s0; comp[6] = s1; comp[7] = s2; +#else + comp[5] = new_val.val[0]; + comp[6] = new_val.val[1]; + comp[7] = new_val.val[2]; +#endif comp[8] = 0; }