cvlkpyramid.cpp.svn-base

来自「非结构化路识别」· SVN-BASE 代码 · 共 1,058 行 · 第 1/3 页

SVN-BASE
1,058
字号
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     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
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "_cv.h"
#include <float.h>

static void
intersect( CvPoint2D32f pt, CvSize win_size, CvSize img_size,
           CvPoint * min_pt, CvPoint * max_pt )
{
    CvPoint ipt;

    ipt.x = cvFloor( pt.x );
    ipt.y = cvFloor( pt.y );

    ipt.x -= win_size.width;
    ipt.y -= win_size.height;

    win_size.width = win_size.width * 2 + 1;
    win_size.height = win_size.height * 2 + 1;

    min_pt->x = MAX( 0, -ipt.x );
    min_pt->y = MAX( 0, -ipt.y );
    max_pt->x = MIN( win_size.width, img_size.width - ipt.x );
    max_pt->y = MIN( win_size.height, img_size.height - ipt.y );
}


static CvStatus
icvInitPyramidalAlgorithm( uchar * imgA, uchar * imgB,
                           int imgStep, CvSize imgSize,
                           uchar * pyrA, uchar * pyrB,
                           int level,
                           CvTermCriteria * criteria,
                           int max_iters, int flags,
                           uchar *** imgI, uchar *** imgJ,
                           int **step, CvSize** size,
                           double **scale, uchar ** buffer )
{
    uchar *pyr_down_temp_buffer = 0;
    CvStatus result = CV_OK;
    int pyrBytes, bufferBytes = 0;
    int level1 = level + 1;

    int i;
    CvSize levelSize;

    *buffer = 0;
    *imgI = *imgJ = 0;
    *step = 0;
    *scale = 0;
    *size = 0;

    /* check input arguments */
    if( !imgA || !imgB )
        return CV_NULLPTR_ERR;

    if( (flags & CV_LKFLOW_PYR_A_READY) != 0 && !pyrA ||
        (flags & CV_LKFLOW_PYR_B_READY) != 0 && !pyrB )
        return CV_BADFLAG_ERR;

    if( level < 0 )
        return CV_BADRANGE_ERR;

    switch (criteria->type)
    {
    case CV_TERMCRIT_ITER:
        criteria->epsilon = 0.f;
        break;
    case CV_TERMCRIT_EPS:
        criteria->maxIter = max_iters;
        break;
    case CV_TERMCRIT_ITER | CV_TERMCRIT_EPS:
        break;
    default:
        assert( 0 );
        return CV_BADFLAG_ERR;
    }

    /* compare squared values */
    criteria->epsilon *= criteria->epsilon;

    /* set pointers and step for every level */
    pyrBytes = 0;

#define ALIGN 8

    levelSize = imgSize;

    for( i = 1; i < level1; i++ )
    {
        levelSize.width = (levelSize.width + 1) >> 1;
        levelSize.height = (levelSize.height + 1) >> 1;

        int tstep = icvAlign(levelSize.width,ALIGN) * sizeof( imgA[0] );
        pyrBytes += tstep * levelSize.height;
    }

    assert( pyrBytes <= imgSize.width * imgSize.height * (int) sizeof( imgA[0] ) * 4 / 3 );

    /* buffer_size = <size for patches> + <size for pyramids> */
    bufferBytes = (level1 >= 0) * ((pyrA == 0) + (pyrB == 0)) * pyrBytes +
        (sizeof( imgI[0][0] ) * 2 + sizeof( step[0][0] ) +
         sizeof(size[0][0]) + sizeof( scale[0][0] )) * level1;

    *buffer = (uchar *) icvAlloc( bufferBytes );
    if( !buffer[0] )
        return CV_OUTOFMEM_ERR;

    *imgI = (uchar **) buffer[0];
    *imgJ = *imgI + level1;
    *step = (int *) (*imgJ + level1);
    *scale = (double *) (*step + level1);
    *size = (CvSize *)(*scale + level1);

    imgI[0][0] = imgA;
    imgJ[0][0] = imgB;
    step[0][0] = imgStep;
    scale[0][0] = 1;
    size[0][0] = imgSize;

    if( level > 0 )
    {
        uchar *bufPtr = (uchar *) (*size + level1);
        uchar *ptrA = pyrA;
        uchar *ptrB = pyrB;
        int pyr_down_buffer_size = 0;

        if( !ptrA )
        {
            ptrA = bufPtr;
            bufPtr += pyrBytes;
        }

        if( !ptrB )
            ptrB = bufPtr;

        icvPyrDownGetBufSize_Gauss5x5( imgSize.width, cv8u, 1, &pyr_down_buffer_size );
        pyr_down_temp_buffer = (uchar *) icvAlloc( pyr_down_buffer_size );
        
        levelSize = imgSize;

        /* build pyramids for both frames */
        for( i = 1; i <= level; i++ )
        {
            int levelBytes;
            CvSize srcSize = levelSize;

            levelSize.width = (levelSize.width + 1) >> 1;
            levelSize.height = (levelSize.height + 1) >> 1;

            size[0][i] = levelSize;
            step[0][i] = icvAlign( levelSize.width, ALIGN ) * sizeof( imgA[0] );
            scale[0][i] = scale[0][i - 1] * 0.5;

            levelBytes = step[0][i] * levelSize.height;
            imgI[0][i] = (uchar *) ptrA;
            ptrA += levelBytes;

            srcSize.width &= -2;
            srcSize.height &= -2;

            if( !(flags & CV_LKFLOW_PYR_A_READY) )
            {
                result = icvPyrDown_Gauss5x5_8u_C1R( imgI[0][i - 1], step[0][i - 1],
                                                     imgI[0][i], step[0][i],
                                                     srcSize, pyr_down_temp_buffer );
                if( result < 0 )
                    goto func_exit;
                icvPyrDownBorder_8u_CnR( imgI[0][i - 1], step[0][i - 1], size[0][i-1],
                                         imgI[0][i], step[0][i], size[0][i], 1 );
            }

            imgJ[0][i] = (uchar *) ptrB;
            ptrB += levelBytes;

            if( !(flags & CV_LKFLOW_PYR_B_READY) )
            {
                result = icvPyrDown_Gauss5x5_8u_C1R( imgJ[0][i - 1], step[0][i - 1],
                                                     imgJ[0][i], step[0][i],
                                                     srcSize, pyr_down_temp_buffer );
                if( result < 0 )
                    goto func_exit;
                icvPyrDownBorder_8u_CnR( imgJ[0][i - 1], step[0][i - 1], size[0][i-1],
                                         imgJ[0][i], step[0][i], size[0][i], 1 );
            }
        }
    }

  func_exit:
    icvFree( &pyr_down_temp_buffer );

    return CV_OK;
}


/*F///////////////////////////////////////////////////////////////////////////////////////
//    Name: icvCalcOpticalFlowPyrLK_8uC1R ( Lucas & Kanade method,
//                                           modification that uses pyramids )
//    Purpose:
//      Calculates optical flow between two images for certain set of points.
//    Context:
//    Parameters:
//            imgA     - pointer to first frame (time t)
//            imgB     - pointer to second frame (time t+1)
//            imgStep  - full width of the source images in bytes
//            imgSize  - size of the source images
//            pyrA     - buffer for pyramid for the first frame.
//                       if the pointer is not NULL, the buffer must have size enough to
//                       store pyramid (from level 1 to level #<level> (see below))
//                       (imgSize.width*imgSize.height/3 will be enough)).
//            pyrB     - similar to pyrA, but for the second frame.
//                       
//                       for both parameters above the following rules work:
//                           If pointer is 0, the function allocates the buffer internally,
//                           calculates pyramid and releases the buffer after processing.
//                           Else (it should be large enough then) the function calculates
//                           pyramid and stores it in the buffer unless the
//                           CV_LKFLOW_PYR_A[B]_READY flag is set. In both cases
//                           (flag is set or not) the subsequent calls may reuse the calculated
//                           pyramid by setting CV_LKFLOW_PYR_A[B]_READY.
//
//            featuresA - array of points, for which the flow needs to be found
//            count    - number of feature points 
//            winSize  - size of search window on each pyramid level
//            level    - maximal pyramid level number
//                         (if 0, pyramids are not used (single level),
//                          if 1, two levels are used etc.)
//
//            next parameters are arrays of <count> elements.
//            ------------------------------------------------------
//            featuresB - array of 2D points, containing calculated
//                       new positions of input features (in the second image).
//            status   - array, every element of which will be set to 1 if the flow for the
//                       corresponding feature has been found, 0 else.
//            error    - array of double numbers, containing difference between
//                       patches around the original and moved points
//                       (it is optional parameter, can be NULL).
//            ------------------------------------------------------
//            criteria   - specifies when to stop the iteration process of finding flow
//                         for each point on each pyramid level
//
//            flags      - miscellaneous flags:
//                            CV_LKFLOW_PYR_A_READY - pyramid for the first frame
//                                                      is precalculated before call
//                            CV_LKFLOW_PYR_B_READY - pyramid for the second frame
//                                                      is precalculated before call
//                            CV_LKFLOW_INITIAL_GUESSES - featuresB array holds initial
//                                                       guesses about new features'
//                                                       locations before function call.
//    Returns: CV_OK       - all ok
//             CV_OUTOFMEM_ERR - insufficient memory for function work
//             CV_NULLPTR_ERR  - if one of input pointers is NULL
//             CV_BADSIZE_ERR  - wrong input sizes interrelation
//
//    Notes:  For calculating spatial derivatives 3x3 Sobel operator is used.
//            The values of pixels beyond the image are determined using replication mode.
//F*/
static  CvStatus  icvCalcOpticalFlowPyrLK_8uC1R( uchar * imgA,
                                                 uchar * imgB,
                                                 int imgStep,
                                                 CvSize imgSize,
                                                 uchar * pyrA,
                                                 uchar * pyrB,
                                                 CvPoint2D32f * featuresA,
                                                 CvPoint2D32f * featuresB,
                                                 int count,
                                                 CvSize winSize,
                                                 int level,
                                                 char *status,
                                                 float *error,
                                                 CvTermCriteria criteria, int flags )
{
#define MAX_LEVEL 10
#define MAX_ITERS 100

    static const float kerX[] = { -1, 0, 1 }, kerY[] =
    {
    0.09375, 0.3125, 0.09375};  /* 3/32, 10/32, 3/32 */

    uchar *pyr_buffer = 0;
    uchar *buffer = 0;
    int bufferBytes = 0;

    uchar **imgI = 0;
    uchar **imgJ = 0;
    int *step = 0;
    double *scale = 0;
    CvSize* size = 0;

    float *patchI;
    float *patchJ;
    float *Ix;
    float *Iy;

    int i, j, k;
    int x, y;

    CvSize patchSize = cvSize( winSize.width * 2 + 1, winSize.height * 2 + 1 );
    int patchLen = patchSize.width * patchSize.height;
    int patchStep = patchSize.width * sizeof( patchI[0] );

    CvSize srcPatchSize = cvSize( patchSize.width + 2, patchSize.height + 2 );
    int srcPatchLen = srcPatchSize.width * srcPatchSize.height;
    int srcPatchStep = srcPatchSize.width * sizeof( patchI[0] );

    CvStatus result = CV_OK;

    /* check input arguments */
    if( !featuresA || !featuresB )
        return CV_NULLPTR_ERR;
    if( winSize.width <= 1 || winSize.height <= 1 )
        return CV_BADSIZE_ERR;

    if( (flags & ~7) != 0 )
        return CV_BADFLAG_ERR;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?