+++ /dev/null
-/*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"
-
-/*
- Finds L1 norm between two blocks.
-*/
-static int
-icvCmpBlocksL1_8u_C1( const uchar * vec1, const uchar * vec2, int len )
-{
- int i, sum = 0;
-
- for( i = 0; i <= len - 4; i += 4 )
- {
- int t0 = abs(vec1[i] - vec2[i]);
- int t1 = abs(vec1[i + 1] - vec2[i + 1]);
- int t2 = abs(vec1[i + 2] - vec2[i + 2]);
- int t3 = abs(vec1[i + 3] - vec2[i + 3]);
-
- sum += t0 + t1 + t2 + t3;
- }
-
- for( ; i < len; i++ )
- {
- int t0 = abs(vec1[i] - vec2[i]);
- sum += t0;
- }
-
- return sum;
-}
-
-
-static void
-icvCopyBM_8u_C1R( const uchar* src, int src_step,
- uchar* dst, int dst_step, CvSize size )
-{
- for( ; size.height--; src += src_step, dst += dst_step )
- memcpy( dst, src, size.width );
-}
-
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: icvCalcOpticalFlowBM_8u32fR
-// Purpose: calculate Optical flow for 2 images using block matching algorithm
-// Context:
-// Parameters:
-// imgA, // pointer to first frame ROI
-// imgB, // pointer to second frame ROI
-// imgStep, // full width of input images in bytes
-// imgSize, // size of the image
-// blockSize, // size of basic blocks which are compared
-// shiftSize, // coordinates increments.
-// maxRange, // size of the scanned neighborhood.
-// usePrevious, // flag of using previous velocity field
-// velocityX, // pointer to ROI of horizontal and
-// velocityY, // vertical components of optical flow
-// velStep); // full width of velocity frames in bytes
-// Returns: CV_OK or error code
-// Notes:
-//F*/
-#define SMALL_DIFF 2
-#define BIG_DIFF 128
-
-static CvStatus CV_STDCALL
-icvCalcOpticalFlowBM_8u32fR( uchar * imgA, uchar * imgB,
- int imgStep, CvSize imgSize,
- CvSize blockSize, CvSize shiftSize,
- CvSize maxRange, int usePrev,
- float *velocityX, float *velocityY,
- int velStep )
-{
- const float back = 1.f / (float) (1 << 16);
-
- /* scanning scheme coordinates */
-
- CvPoint *ss = 0;
- int ss_count = 0;
-
- int stand_accept_level = blockSize.height * blockSize.width * SMALL_DIFF;
- int stand_escape_level = blockSize.height * blockSize.width * BIG_DIFF;
-
- int i, j;
-
- int *int_velocityX = (int *) velocityX;
- int *int_velocityY = (int *) velocityY;
-
- /* if image sizes can't be divided by block sizes then right blocks will */
- /* have not full width - BorderWidth */
- /* and bottom blocks will */
- /* have not full height - BorderHeight */
- int BorderWidth;
- int BorderHeight;
-
- int CurrentWidth;
- int CurrentHeight;
-
- int NumberBlocksX;
- int NumberBlocksY;
-
- int Y1 = 0;
- int X1 = 0;
-
- int DownStep = blockSize.height * imgStep;
-
- uchar *blockA = 0;
- uchar *blockB = 0;
- uchar *blockZ = 0;
- int blSize = blockSize.width * blockSize.height;
- int bufferSize = cvAlign(blSize + 9,16);
- int cmpSize = cvAlign(blSize,4);
- int patch_ofs = blSize & -8;
- int64 patch_mask = (((int64) 1) << (blSize - patch_ofs * 8)) - 1;
-
- velStep /= sizeof(velocityX[0]);
-
- if( patch_ofs == blSize )
- patch_mask = (int64) - 1;
-
-/****************************************************************************************\
-* Checking bad arguments *
-\****************************************************************************************/
- if( imgA == NULL )
- return CV_NULLPTR_ERR;
- if( imgB == NULL )
- return CV_NULLPTR_ERR;
-
-/****************************************************************************************\
-* Allocate buffers *
-\****************************************************************************************/
- blockA = (uchar *) cvAlloc( bufferSize * 3 );
- if( !blockA )
- return CV_OUTOFMEM_ERR;
-
- blockB = blockA + bufferSize;
- blockZ = blockB + bufferSize;
-
- memset( blockZ, 0, bufferSize );
-
- ss = (CvPoint *) cvAlloc( (2 * maxRange.width + 1) * (2 * maxRange.height + 1) *
- sizeof( CvPoint ));
- if( !ss )
- {
- cvFree( &blockA );
- return CV_OUTOFMEM_ERR;
- }
-
-/****************************************************************************************\
-* Calculate scanning scheme *
-\****************************************************************************************/
- {
- int X_shift_count = maxRange.width / shiftSize.width;
- int Y_shift_count = maxRange.height / shiftSize.height;
- int min_count = MIN( X_shift_count, Y_shift_count );
-
- /* cycle by neighborhood rings */
- /* scanning scheme is
-
- . 9 10 11 12
- . 8 1 2 13
- . 7 * 3 14
- . 6 5 4 15
- 20 19 18 17 16
- */
-
- for( i = 0; i < min_count; i++ )
- {
- /* four cycles along sides */
- int y = -(i + 1) * shiftSize.height;
- int x = -(i + 1) * shiftSize.width;
-
- /* upper side */
- for( j = -i; j <= i + 1; j++, ss_count++ )
- {
- x += shiftSize.width;
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- }
-
- /* right side */
- for( j = -i; j <= i + 1; j++, ss_count++ )
- {
- y += shiftSize.height;
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- }
-
- /* bottom side */
- for( j = -i; j <= i + 1; j++, ss_count++ )
- {
- x -= shiftSize.width;
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- }
-
- /* left side */
- for( j = -i; j <= i + 1; j++, ss_count++ )
- {
- y -= shiftSize.height;
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- }
- }
-
- /* the rest part */
- if( X_shift_count < Y_shift_count )
- {
- int xleft = -min_count * shiftSize.width;
-
- /* cycle by neighbor rings */
- for( i = min_count; i < Y_shift_count; i++ )
- {
- /* two cycles by x */
- int y = -(i + 1) * shiftSize.height;
- int x = xleft;
-
- /* upper side */
- for( j = -X_shift_count; j <= X_shift_count; j++, ss_count++ )
- {
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- x += shiftSize.width;
- }
-
- x = xleft;
- y = -y;
- /* bottom side */
- for( j = -X_shift_count; j <= X_shift_count; j++, ss_count++ )
- {
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- x += shiftSize.width;
- }
- }
- }
- else if( X_shift_count > Y_shift_count )
- {
- int yupper = -min_count * shiftSize.height;
-
- /* cycle by neighbor rings */
- for( i = min_count; i < X_shift_count; i++ )
- {
- /* two cycles by y */
- int x = -(i + 1) * shiftSize.width;
- int y = yupper;
-
- /* left side */
- for( j = -Y_shift_count; j <= Y_shift_count; j++, ss_count++ )
- {
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- y += shiftSize.height;
- }
-
- y = yupper;
- x = -x;
- /* right side */
- for( j = -Y_shift_count; j <= Y_shift_count; j++, ss_count++ )
- {
- ss[ss_count].x = x;
- ss[ss_count].y = y;
- y += shiftSize.height;
- }
- }
- }
-
- }
-
-/****************************************************************************************\
-* Calculate some neeeded variables *
-\****************************************************************************************/
- /* Calculate number of full blocks */
- NumberBlocksX = (int) imgSize.width / blockSize.width;
- NumberBlocksY = (int) imgSize.height / blockSize.height;
-
- /* add 1 if not full border blocks exist */
- BorderWidth = imgSize.width % blockSize.width;
- if( BorderWidth )
- NumberBlocksX++;
- else
- BorderWidth = blockSize.width;
-
- BorderHeight = imgSize.height % blockSize.height;
- if( BorderHeight )
- NumberBlocksY++;
- else
- BorderHeight = blockSize.height;
-
-/****************************************************************************************\
-* Round input velocities integer searching area center position *
-\****************************************************************************************/
- if( usePrev )
- {
- float *velxf = velocityX, *velyf = velocityY;
- int* velx = (int*)velocityX, *vely = (int*)velocityY;
-
- for( i = 0; i < NumberBlocksY; i++, velxf += velStep, velyf += velStep,
- velx += velStep, vely += velStep )
- {
- for( j = 0; j < NumberBlocksX; j++ )
- {
- int vx = cvRound( velxf[j] ), vy = cvRound( velyf[j] );
- velx[j] = vx; vely[j] = vy;
- }
- }
- }
-/****************************************************************************************\
-* Main loop *
-\****************************************************************************************/
- Y1 = 0;
- for( i = 0; i < NumberBlocksY; i++ )
- {
- /* calculate height of current block */
- CurrentHeight = (i == NumberBlocksY - 1) ? BorderHeight : blockSize.height;
- X1 = 0;
-
- for( j = 0; j < NumberBlocksX; j++ )
- {
- int accept_level;
- int escape_level;
-
- int blDist;
-
- int VelocityX = 0;
- int VelocityY = 0;
-
- int offX = 0, offY = 0;
-
- int CountDirection = 1;
-
- int main_flag = i < NumberBlocksY - 1 && j < NumberBlocksX - 1;
- CvSize CurSize;
-
- /* calculate width of current block */
- CurrentWidth = (j == NumberBlocksX - 1) ? BorderWidth : blockSize.width;
-
- /* compute initial offset */
- if( usePrev )
- {
- offX = int_velocityX[j];
- offY = int_velocityY[j];
- }
-
- CurSize.width = CurrentWidth;
- CurSize.height = CurrentHeight;
-
- if( main_flag )
- {
- icvCopyBM_8u_C1R( imgA + X1, imgStep, blockA,
- CurSize.width, CurSize );
- icvCopyBM_8u_C1R( imgB + (Y1 + offY)*imgStep + (X1 + offX),
- imgStep, blockB, CurSize.width, CurSize );
-
- *((int64 *) (blockA + patch_ofs)) &= patch_mask;
- *((int64 *) (blockB + patch_ofs)) &= patch_mask;
- }
- else
- {
- memset( blockA, 0, bufferSize );
- memset( blockB, 0, bufferSize );
-
- icvCopyBM_8u_C1R( imgA + X1, imgStep, blockA, blockSize.width, CurSize );
- icvCopyBM_8u_C1R( imgB + (Y1 + offY) * imgStep + (X1 + offX), imgStep,
- blockB, blockSize.width, CurSize );
- }
-
- if( !main_flag )
- {
- int tmp = CurSize.width * CurSize.height;
-
- accept_level = tmp * SMALL_DIFF;
- escape_level = tmp * BIG_DIFF;
- }
- else
- {
- accept_level = stand_accept_level;
- escape_level = stand_escape_level;
- }
-
- blDist = icvCmpBlocksL1_8u_C1( blockA, blockB, cmpSize );
-
- if( blDist > accept_level )
- {
- int k;
- int VelX = 0;
- int VelY = 0;
-
- /* walk around basic block */
-
- /* cycle for neighborhood */
- for( k = 0; k < ss_count; k++ )
- {
- int tmpDist;
-
- int Y2 = Y1 + offY + ss[k].y;
- int X2 = X1 + offX + ss[k].x;
-
- /* if we break upper border */
- if( Y2 < 0 )
- {
- continue;
- }
- /* if we break bottom border */
- if( Y2 + CurrentHeight >= imgSize.height )
- {
- continue;
- }
- /* if we break left border */
- if( X2 < 0 )
- {
- continue;
- }
- /* if we break right border */
- if( X2 + CurrentWidth >= imgSize.width )
- {
- continue;
- }
-
- if( main_flag )
- {
- icvCopyBM_8u_C1R( imgB + Y2 * imgStep + X2,
- imgStep, blockB, CurSize.width, CurSize );
-
- *((int64 *) (blockB + patch_ofs)) &= patch_mask;
- }
- else
- {
- memset( blockB, 0, bufferSize );
- icvCopyBM_8u_C1R( imgB + Y1 * imgStep + X1, imgStep,
- blockB, blockSize.width, CurSize );
- }
-
- tmpDist = icvCmpBlocksL1_8u_C1( blockA, blockB, cmpSize );
-
- if( tmpDist < accept_level )
- {
- VelX = ss[k].x;
- VelY = ss[k].y;
- break; /*for */
- }
- else if( tmpDist < blDist )
- {
- blDist = tmpDist;
- VelX = ss[k].x;
- VelY = ss[k].y;
- CountDirection = 1;
- }
- else if( tmpDist == blDist )
- {
- VelX += ss[k].x;
- VelY += ss[k].y;
- CountDirection++;
- }
- }
- if( blDist > escape_level )
- {
- VelX = VelY = 0;
- CountDirection = 1;
- }
- if( CountDirection > 1 )
- {
- int temp = CountDirection == 2 ? 1 << 15 : ((1 << 16) / CountDirection);
-
- VelocityX = VelX * temp;
- VelocityY = VelY * temp;
- }
- else
- {
- VelocityX = VelX << 16;
- VelocityY = VelY << 16;
- }
- } /*if */
-
- int_velocityX[j] = VelocityX + (offX << 16);
- int_velocityY[j] = VelocityY + (offY << 16);
-
- X1 += blockSize.width;
-
- } /*for */
- int_velocityX += velStep;
- int_velocityY += velStep;
-
- imgA += DownStep;
- Y1 += blockSize.height;
- } /*for */
-
-/****************************************************************************************\
-* Converting fixed point velocities to floating point *
-\****************************************************************************************/
- {
- float *velxf = velocityX, *velyf = velocityY;
- int* velx = (int*)velocityX, *vely = (int*)velocityY;
-
- for( i = 0; i < NumberBlocksY; i++, velxf += velStep, velyf += velStep,
- velx += velStep, vely += velStep )
- {
- for( j = 0; j < NumberBlocksX; j++ )
- {
- float vx = (float)velx[j]*back, vy = (float)vely[j]*back;
- velxf[j] = vx; velyf[j] = vy;
- }
- }
- }
-
- cvFree( &ss );
- cvFree( &blockA );
-
- return CV_OK;
-} /*cvCalcOpticalFlowBM_8u */
-
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: cvCalcOpticalFlowBM
-// Purpose: Optical flow implementation
-// Context:
-// Parameters:
-// srcA, srcB - source image
-// velx, vely - destination image
-// Returns:
-//
-// Notes:
-//F*/
-CV_IMPL void
-cvCalcOpticalFlowBM( const void* srcarrA, const void* srcarrB,
- CvSize blockSize, CvSize shiftSize,
- CvSize maxRange, int usePrevious,
- void* velarrx, void* velarry )
-{
- CV_FUNCNAME( "cvCalcOpticalFlowBM" );
-
- __BEGIN__;
-
- CvMat stubA, *srcA = (CvMat*)srcarrA;
- CvMat stubB, *srcB = (CvMat*)srcarrB;
- CvMat stubx, *velx = (CvMat*)velarrx;
- CvMat stuby, *vely = (CvMat*)velarry;
-
- CV_CALL( srcA = cvGetMat( srcA, &stubA ));
- CV_CALL( srcB = cvGetMat( srcB, &stubB ));
-
- CV_CALL( velx = cvGetMat( velx, &stubx ));
- CV_CALL( vely = cvGetMat( vely, &stuby ));
-
- if( !CV_ARE_TYPES_EQ( srcA, srcB ))
- CV_ERROR( CV_StsUnmatchedFormats, "Source images have different formats" );
-
- if( !CV_ARE_TYPES_EQ( velx, vely ))
- CV_ERROR( CV_StsUnmatchedFormats, "Destination images have different formats" );
-
- if( !CV_ARE_SIZES_EQ( srcA, srcB ) ||
- !CV_ARE_SIZES_EQ( velx, vely ) ||
- (unsigned)(velx->width*blockSize.width - srcA->width) >= (unsigned)blockSize.width ||
- (unsigned)(velx->height*blockSize.height - srcA->height) >= (unsigned)blockSize.height )
- CV_ERROR( CV_StsUnmatchedSizes, "" );
-
- if( CV_MAT_TYPE( srcA->type ) != CV_8UC1 ||
- CV_MAT_TYPE( velx->type ) != CV_32FC1 )
- CV_ERROR( CV_StsUnsupportedFormat, "Source images must have 8uC1 type and "
- "destination images must have 32fC1 type" );
-
- if( srcA->step != srcB->step || velx->step != vely->step )
- CV_ERROR( CV_BadStep, "two source or two destination images have different steps" );
-
- IPPI_CALL( icvCalcOpticalFlowBM_8u32fR( (uchar*)srcA->data.ptr, (uchar*)srcB->data.ptr,
- srcA->step, cvGetMatSize( srcA ), blockSize,
- shiftSize, maxRange, usePrevious,
- velx->data.fl, vely->data.fl, velx->step ));
- __END__;
-}
-
-
-/* End of file. */