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:
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user