Как рассчитать количество операций для функции фильтра Гаусса opencv?

0

Проверяя исходный код 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>();
}
  • 0
    Если вы просто хотите узнать, сколько раз вызывается функция, используйте профилировщик . Если вам нужна сложность алгоритма, это свертка двумерного сигнала, хотя для этого конкретного ядра прямая свертка может быть оптимизирована с использованием БПФ
Теги:
opencv

1 ответ

0

Конечно, вы можете разобрать программу, которая даст вам количество команд, и вы также можете легко подсчитывать чтение и запись, например, grep. Я предлагаю использовать кросс-компилятор для разборки в какой-нибудь хороший RISC-ассемблер, такой как MIPS - чтение тайного, раздутый ассемблер X86 - не забава.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню