如何计算opencv高斯滤波函数的运算次数?

时间:2014-09-12 05:10:05

标签: c++ opencv operations

通过检查opencv的源代码,子函数中还有子函数和一些子函数,通常我们怎样才能知道这个函数需要多少次操作以及内存的次数我们在函数中需要读写吗?

尝试手工计算看起来相当费力,有人试图用手或任何其他聪明的方式来计算它吗?

cv::Ptr<cv::FilterEngine> cv::createGaussianFilter( int type, Size ksize,
                                    double sigma1, double sigma2,
                                    int borderType )
{
    Mat kx, ky;
    createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);

    return createSeparableLinearFilter( type, type, kx, ky, Point(-1,-1), 0, borderType );
}


static void createGaussianKernels( Mat & kx, Mat & ky, int type, Size ksize,
                               double sigma1, double sigma2 )
{
int depth = CV_MAT_DEPTH(type);
if( sigma2 <= 0 )
    sigma2 = sigma1;

// automatic detection of kernel size from sigma
if( ksize.width <= 0 && sigma1 > 0 )
    ksize.width = cvRound(sigma1*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
if( ksize.height <= 0 && sigma2 > 0 )
    ksize.height = cvRound(sigma2*(depth == CV_8U ? 3 : 4)*2 + 1)|1;

CV_Assert( ksize.width > 0 && ksize.width % 2 == 1 &&
    ksize.height > 0 && ksize.height % 2 == 1 );

sigma1 = std::max( sigma1, 0. );
sigma2 = std::max( sigma2, 0. );

kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) );
if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON )
    ky = kx;
else
    ky = getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F) );
}


cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype )  
{
const int SMALL_GAUSSIAN_SIZE = 7;
static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
{
    {1.f},
    {0.25f, 0.5f, 0.25f},
    {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
    {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
};

const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
    small_gaussian_tab[n>>1] : 0;

CV_Assert( ktype == CV_32F || ktype == CV_64F );
Mat kernel(n, 1, ktype);
float* cf = kernel.ptr<float>();
double* cd = kernel.ptr<double>();

double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
double scale2X = -0.5/(sigmaX*sigmaX);
double sum = 0;

int i;
for( i = 0; i < n; i++ )
{
    double x = i - (n-1)*0.5;
    double t = fixed_kernel ? (double)fixed_kernel[i] : std::exp(scale2X*x*x);
    if( ktype == CV_32F )
    {
        cf[i] = (float)t;
        sum += cf[i];
    }
    else
    {
        cd[i] = t;
        sum += cd[i];
    }
}

sum = 1./sum;
for( i = 0; i < n; i++ )
{
    if( ktype == CV_32F )
        cf[i] = (float)(cf[i]*sum);
    else
        cd[i] *= sum;
}

return kernel;
}

cv::Ptr<cv::FilterEngine> cv::createSeparableLinearFilter(
int _srcType, int _dstType,
InputArray __rowKernel, InputArray __columnKernel,
Point _anchor, double _delta,
int _rowBorderType, int _columnBorderType,
const Scalar& _borderValue )
{
Mat _rowKernel = __rowKernel.getMat(), _columnKernel = __columnKernel.getMat();
_srcType = CV_MAT_TYPE(_srcType);
_dstType = CV_MAT_TYPE(_dstType);
int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);
int cn = CV_MAT_CN(_srcType);
CV_Assert( cn == CV_MAT_CN(_dstType) );
int rsize = _rowKernel.rows + _rowKernel.cols - 1;
int csize = _columnKernel.rows + _columnKernel.cols - 1;
if( _anchor.x < 0 )
    _anchor.x = rsize/2;
if( _anchor.y < 0 )
    _anchor.y = csize/2;
int rtype = getKernelType(_rowKernel,
    _rowKernel.rows == 1 ? Point(_anchor.x, 0) : Point(0, _anchor.x));
int ctype = getKernelType(_columnKernel,
    _columnKernel.rows == 1 ? Point(_anchor.y, 0) : Point(0, _anchor.y));
Mat rowKernel, columnKernel;

int bdepth = std::max(CV_32F,std::max(sdepth, ddepth));
int bits = 0;

if( sdepth == CV_8U &&
    ((rtype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
      ctype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
      ddepth == CV_8U) ||
     ((rtype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&
      (ctype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&
      (rtype & ctype & KERNEL_INTEGER) &&
      ddepth == CV_16S)) )
{
    bdepth = CV_32S;
    bits = ddepth == CV_8U ? 8 : 0;
    _rowKernel.convertTo( rowKernel, CV_32S, 1 << bits );
    _columnKernel.convertTo( columnKernel, CV_32S, 1 << bits );
    bits *= 2;
    _delta *= (1 << bits);
}
else
{
    if( _rowKernel.type() != bdepth )
        _rowKernel.convertTo( rowKernel, bdepth );
    else
        rowKernel = _rowKernel;
    if( _columnKernel.type() != bdepth )
        _columnKernel.convertTo( columnKernel, bdepth );
    else
        columnKernel = _columnKernel;
}
int _bufType = CV_MAKETYPE(bdepth, cn);
Ptr<BaseRowFilter> _rowFilter = getLinearRowFilter(
    _srcType, _bufType, rowKernel, _anchor.x, rtype);
Ptr<BaseColumnFilter> _columnFilter = getLinearColumnFilter(
    _bufType, _dstType, columnKernel, _anchor.y, ctype, _delta, bits );

return Ptr<FilterEngine>( new FilterEngine(Ptr<BaseFilter>(), _rowFilter, _columnFilter,
    _srcType, _dstType, _bufType, _rowBorderType, _columnBorderType, _borderValue ));
}


cv::Ptr<cv::BaseColumnFilter> cv::getLinearColumnFilter( int bufType, int dstType,
                                         InputArray _kernel, int anchor,
                                         int symmetryType, double delta,
                                         int bits )
{
Mat kernel = _kernel.getMat();
int sdepth = CV_MAT_DEPTH(bufType), ddepth = CV_MAT_DEPTH(dstType);
int cn = CV_MAT_CN(dstType);
CV_Assert( cn == CV_MAT_CN(bufType) &&
    sdepth >= std::max(ddepth, CV_32S) &&
    kernel.type() == sdepth );

if( !(symmetryType & (KERNEL_SYMMETRICAL|KERNEL_ASYMMETRICAL)) )
{
    if( ddepth == CV_8U && sdepth == CV_32S )
        return makePtr<ColumnFilter<FixedPtCastEx<int, uchar>, ColumnNoVec> >
        (kernel, anchor, delta, FixedPtCastEx<int, uchar>(bits));
    if( ddepth == CV_8U && sdepth == CV_32F )
        return makePtr<ColumnFilter<Cast<float, uchar>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_8U && sdepth == CV_64F )
        return makePtr<ColumnFilter<Cast<double, uchar>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_16U && sdepth == CV_32F )
        return makePtr<ColumnFilter<Cast<float, ushort>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_16U && sdepth == CV_64F )
        return makePtr<ColumnFilter<Cast<double, ushort>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_16S && sdepth == CV_32F )
        return makePtr<ColumnFilter<Cast<float, short>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_16S && sdepth == CV_64F )
        return makePtr<ColumnFilter<Cast<double, short>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_32F && sdepth == CV_32F )
        return makePtr<ColumnFilter<Cast<float, float>, ColumnNoVec> >(kernel, anchor, delta);
    if( ddepth == CV_64F && sdepth == CV_64F )
        return makePtr<ColumnFilter<Cast<double, double>, ColumnNoVec> >(kernel, anchor, delta);
}
else
{
    int ksize = kernel.rows + kernel.cols - 1;
    if( ksize == 3 )
    {
        if( ddepth == CV_8U && sdepth == CV_32S )
            return makePtr<SymmColumnSmallFilter<
                FixedPtCastEx<int, uchar>, SymmColumnVec_32s8u> >
                (kernel, anchor, delta, symmetryType, FixedPtCastEx<int, uchar>(bits),
                SymmColumnVec_32s8u(kernel, symmetryType, bits, delta));
        if( ddepth == CV_16S && sdepth == CV_32S && bits == 0 )
            return makePtr<SymmColumnSmallFilter<Cast<int, short>,
                SymmColumnSmallVec_32s16s> >(kernel, anchor, delta, symmetryType,
                    Cast<int, short>(), SymmColumnSmallVec_32s16s(kernel, symmetryType, bits, delta));
        if( ddepth == CV_32F && sdepth == CV_32F )
            return makePtr<SymmColumnSmallFilter<
                Cast<float, float>,SymmColumnSmallVec_32f> >
                (kernel, anchor, delta, symmetryType, Cast<float, float>(),
                SymmColumnSmallVec_32f(kernel, symmetryType, 0, delta));
    }
    if( ddepth == CV_8U && sdepth == CV_32S )
        return makePtr<SymmColumnFilter<FixedPtCastEx<int, uchar>, SymmColumnVec_32s8u> >
            (kernel, anchor, delta, symmetryType, FixedPtCastEx<int, uchar>(bits),
            SymmColumnVec_32s8u(kernel, symmetryType, bits, delta));
    if( ddepth == CV_8U && sdepth == CV_32F )
        return makePtr<SymmColumnFilter<Cast<float, uchar>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
    if( ddepth == CV_8U && sdepth == CV_64F )
        return makePtr<SymmColumnFilter<Cast<double, uchar>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
    if( ddepth == CV_16U && sdepth == CV_32F )
        return makePtr<SymmColumnFilter<Cast<float, ushort>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
    if( ddepth == CV_16U && sdepth == CV_64F )
        return makePtr<SymmColumnFilter<Cast<double, ushort>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
    if( ddepth == CV_16S && sdepth == CV_32S )
        return makePtr<SymmColumnFilter<Cast<int, short>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
    if( ddepth == CV_16S && sdepth == CV_32F )
        return makePtr<SymmColumnFilter<Cast<float, short>, SymmColumnVec_32f16s> >
             (kernel, anchor, delta, symmetryType, Cast<float, short>(),
              SymmColumnVec_32f16s(kernel, symmetryType, 0, delta));
    if( ddepth == CV_16S && sdepth == CV_64F )
        return makePtr<SymmColumnFilter<Cast<double, short>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
    if( ddepth == CV_32F && sdepth == CV_32F )
        return makePtr<SymmColumnFilter<Cast<float, float>, SymmColumnVec_32f> >
            (kernel, anchor, delta, symmetryType, Cast<float, float>(),
            SymmColumnVec_32f(kernel, symmetryType, 0, delta));
    if( ddepth == CV_64F && sdepth == CV_64F )
        return makePtr<SymmColumnFilter<Cast<double, double>, ColumnNoVec> >
            (kernel, anchor, delta, symmetryType);
}

CV_Error_( CV_StsNotImplemented,
    ("Unsupported combination of buffer format (=%d), and destination format (=%d)",
    bufType, dstType));

return Ptr<BaseColumnFilter>();
}

1 个答案:

答案 0 :(得分:0)

当然,您可以反汇编程序,这将为您提供指令计数,您还可以轻松地计算读取和写入数量。 grep的。我建议使用交叉编译器反汇编成一些不错的RISC汇编程序,如MIPS - 读取奥术,臃肿的X86汇编程序并不好玩。