1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

converted flood fill, getrectsubpix & cornersubpix to C++

This commit is contained in:
Vadim Pisarevsky
2013-02-11 23:49:10 +04:00
parent c527340cb6
commit 06f4a56469
8 changed files with 451 additions and 1186 deletions
+54 -152
View File
@@ -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;
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
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)" );
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, "" );
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 );
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;
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;
Point2f cI2;
double a = 0, b = 0, c = 0, bb1 = 0, bb2 = 0;
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 ));
getRectSubPix(src, Size(win_w+2, win_h+2), cI, subpix_buf, subpix_buf.type());
const float* subpix = &subpix_buf.at<float>(1,1);
/* 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 );
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 )
{
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;
cvFindCornerSubPix( &c_image, (CvPoint2D32f*)corners.data, ncorners,
winSize, zeroZone, criteria );
CV_IMPL void
cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* _corners,
int count, CvSize win, CvSize zeroZone,
CvTermCriteria criteria )
{
if(!_corners || count <= 0)
return;
cv::Mat src = cv::cvarrToMat(srcarr), corners(count, 1, CV_32FC2, _corners);
cv::cornerSubPix(src, corners, win, zeroZone, criteria);
}
/* End of file. */