Commit 06f4a564 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

converted flood fill, getrectsubpix & cornersubpix to C++

parent c527340c
......@@ -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<float> 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<float>();
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<float>(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. */
......@@ -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
......
This diff is collapsed.
......@@ -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));
......
......@@ -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_*/
This diff is collapsed.
......@@ -699,7 +699,6 @@ public:
private:
Mat src;
Mat dst;
int nStripes;
double thresh;
double maxval;
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment