+++ /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"
-
-typedef struct
-{
- float xx;
- float xy;
- float yy;
- float xt;
- float yt;
-}
-icvDerProduct;
-
-
-#define CONV( A, B, C) ((float)( A + (B<<1) + C ))
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: icvCalcOpticalFlowLK_8u32fR ( Lucas & Kanade method )
-// Purpose: calculate Optical flow for 2 images using Lucas & Kanade algorithm
-// Context:
-// Parameters:
-// imgA, // pointer to first frame ROI
-// imgB, // pointer to second frame ROI
-// imgStep, // width of single row of source images in bytes
-// imgSize, // size of the source image ROI
-// winSize, // size of the averaging window used for grouping
-// velocityX, // pointer to horizontal and
-// velocityY, // vertical components of optical flow ROI
-// velStep // width of single row of velocity frames in bytes
-//
-// 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: 1.Optical flow to be computed for every pixel in ROI
-// 2.For calculating spatial derivatives we use 3x3 Sobel operator.
-// 3.We use the following border mode.
-// The last row or column is replicated for the border
-// ( IPL_BORDER_REPLICATE in IPL ).
-//
-//
-//F*/
-static CvStatus CV_STDCALL
-icvCalcOpticalFlowLK_8u32fR( uchar * imgA,
- uchar * imgB,
- int imgStep,
- CvSize imgSize,
- CvSize winSize,
- float *velocityX,
- float *velocityY, int velStep )
-{
- /* Loops indexes */
- int i, j, k;
-
- /* Gaussian separable kernels */
- float GaussX[16];
- float GaussY[16];
- float *KerX;
- float *KerY;
-
- /* Buffers for Sobel calculations */
- float *MemX[2];
- float *MemY[2];
-
- float ConvX, ConvY;
- float GradX, GradY, GradT;
-
- int winWidth = winSize.width;
- int winHeight = winSize.height;
-
- int imageWidth = imgSize.width;
- int imageHeight = imgSize.height;
-
- int HorRadius = (winWidth - 1) >> 1;
- int VerRadius = (winHeight - 1) >> 1;
-
- int PixelLine;
- int ConvLine;
-
- int BufferAddress;
-
- int BufferHeight = 0;
- int BufferWidth;
- int BufferSize;
-
- /* buffers derivatives product */
- icvDerProduct *II;
-
- /* buffers for gaussian horisontal convolution */
- icvDerProduct *WII;
-
- /* variables for storing number of first pixel of image line */
- int Line1;
- int Line2;
- int Line3;
-
- /* we must have 2*2 linear system coeffs
- | A1B2 B1 | {u} {C1} {0}
- | | { } + { } = { }
- | A2 A1B2 | {v} {C2} {0}
- */
- float A1B2, A2, B1, C1, C2;
-
- int pixNumber;
-
- /* auxiliary */
- int NoMem = 0;
-
- velStep /= sizeof(velocityX[0]);
-
- /* Checking bad arguments */
- if( imgA == NULL )
- return CV_NULLPTR_ERR;
- if( imgB == NULL )
- return CV_NULLPTR_ERR;
-
- if( imageHeight < winHeight )
- return CV_BADSIZE_ERR;
- if( imageWidth < winWidth )
- return CV_BADSIZE_ERR;
-
- if( winHeight >= 16 )
- return CV_BADSIZE_ERR;
- if( winWidth >= 16 )
- return CV_BADSIZE_ERR;
-
- if( !(winHeight & 1) )
- return CV_BADSIZE_ERR;
- if( !(winWidth & 1) )
- return CV_BADSIZE_ERR;
-
- BufferHeight = winHeight;
- BufferWidth = imageWidth;
-
- /****************************************************************************************/
- /* Computing Gaussian coeffs */
- /****************************************************************************************/
- GaussX[0] = 1;
- GaussY[0] = 1;
- for( i = 1; i < winWidth; i++ )
- {
- GaussX[i] = 1;
- for( j = i - 1; j > 0; j-- )
- {
- GaussX[j] += GaussX[j - 1];
- }
- }
- for( i = 1; i < winHeight; i++ )
- {
- GaussY[i] = 1;
- for( j = i - 1; j > 0; j-- )
- {
- GaussY[j] += GaussY[j - 1];
- }
- }
- KerX = &GaussX[HorRadius];
- KerY = &GaussY[VerRadius];
-
- /****************************************************************************************/
- /* Allocating memory for all buffers */
- /****************************************************************************************/
- for( k = 0; k < 2; k++ )
- {
- MemX[k] = (float *) cvAlloc( (imgSize.height) * sizeof( float ));
-
- if( MemX[k] == NULL )
- NoMem = 1;
- MemY[k] = (float *) cvAlloc( (imgSize.width) * sizeof( float ));
-
- if( MemY[k] == NULL )
- NoMem = 1;
- }
-
- BufferSize = BufferHeight * BufferWidth;
-
- II = (icvDerProduct *) cvAlloc( BufferSize * sizeof( icvDerProduct ));
- WII = (icvDerProduct *) cvAlloc( BufferSize * sizeof( icvDerProduct ));
-
-
- if( (II == NULL) || (WII == NULL) )
- NoMem = 1;
-
- if( NoMem )
- {
- for( k = 0; k < 2; k++ )
- {
- if( MemX[k] )
- cvFree( &MemX[k] );
-
- if( MemY[k] )
- cvFree( &MemY[k] );
- }
- if( II )
- cvFree( &II );
- if( WII )
- cvFree( &WII );
-
- return CV_OUTOFMEM_ERR;
- }
-
- /****************************************************************************************/
- /* Calculate first line of memX and memY */
- /****************************************************************************************/
- MemY[0][0] = MemY[1][0] = CONV( imgA[0], imgA[0], imgA[1] );
- MemX[0][0] = MemX[1][0] = CONV( imgA[0], imgA[0], imgA[imgStep] );
-
- for( j = 1; j < imageWidth - 1; j++ )
- {
- MemY[0][j] = MemY[1][j] = CONV( imgA[j - 1], imgA[j], imgA[j + 1] );
- }
-
- pixNumber = imgStep;
- for( i = 1; i < imageHeight - 1; i++ )
- {
- MemX[0][i] = MemX[1][i] = CONV( imgA[pixNumber - imgStep],
- imgA[pixNumber], imgA[pixNumber + imgStep] );
- pixNumber += imgStep;
- }
-
- MemY[0][imageWidth - 1] =
- MemY[1][imageWidth - 1] = CONV( imgA[imageWidth - 2],
- imgA[imageWidth - 1], imgA[imageWidth - 1] );
-
- MemX[0][imageHeight - 1] =
- MemX[1][imageHeight - 1] = CONV( imgA[pixNumber - imgStep],
- imgA[pixNumber], imgA[pixNumber] );
-
-
- /****************************************************************************************/
- /* begin scan image, calc derivatives and solve system */
- /****************************************************************************************/
-
- PixelLine = -VerRadius;
- ConvLine = 0;
- BufferAddress = -BufferWidth;
-
- while( PixelLine < imageHeight )
- {
- if( ConvLine < imageHeight )
- {
- /*Here we calculate derivatives for line of image */
- int address;
-
- i = ConvLine;
- int L1 = i - 1;
- int L2 = i;
- int L3 = i + 1;
-
- int memYline = L3 & 1;
-
- if( L1 < 0 )
- L1 = 0;
- if( L3 >= imageHeight )
- L3 = imageHeight - 1;
-
- BufferAddress += BufferWidth;
- BufferAddress -= ((BufferAddress >= BufferSize) ? 0xffffffff : 0) & BufferSize;
-
- address = BufferAddress;
-
- Line1 = L1 * imgStep;
- Line2 = L2 * imgStep;
- Line3 = L3 * imgStep;
-
- /* Process first pixel */
- ConvX = CONV( imgA[Line1 + 1], imgA[Line2 + 1], imgA[Line3 + 1] );
- ConvY = CONV( imgA[Line3], imgA[Line3], imgA[Line3 + 1] );
-
- GradY = ConvY - MemY[memYline][0];
- GradX = ConvX - MemX[1][L2];
-
- MemY[memYline][0] = ConvY;
- MemX[1][L2] = ConvX;
-
- GradT = (float) (imgB[Line2] - imgA[Line2]);
-
- II[address].xx = GradX * GradX;
- II[address].xy = GradX * GradY;
- II[address].yy = GradY * GradY;
- II[address].xt = GradX * GradT;
- II[address].yt = GradY * GradT;
- address++;
- /* Process middle of line */
- for( j = 1; j < imageWidth - 1; j++ )
- {
- ConvX = CONV( imgA[Line1 + j + 1], imgA[Line2 + j + 1], imgA[Line3 + j + 1] );
- ConvY = CONV( imgA[Line3 + j - 1], imgA[Line3 + j], imgA[Line3 + j + 1] );
-
- GradY = ConvY - MemY[memYline][j];
- GradX = ConvX - MemX[(j - 1) & 1][L2];
-
- MemY[memYline][j] = ConvY;
- MemX[(j - 1) & 1][L2] = ConvX;
-
- GradT = (float) (imgB[Line2 + j] - imgA[Line2 + j]);
-
- II[address].xx = GradX * GradX;
- II[address].xy = GradX * GradY;
- II[address].yy = GradY * GradY;
- II[address].xt = GradX * GradT;
- II[address].yt = GradY * GradT;
-
- address++;
- }
- /* Process last pixel of line */
- ConvX = CONV( imgA[Line1 + imageWidth - 1], imgA[Line2 + imageWidth - 1],
- imgA[Line3 + imageWidth - 1] );
-
- ConvY = CONV( imgA[Line3 + imageWidth - 2], imgA[Line3 + imageWidth - 1],
- imgA[Line3 + imageWidth - 1] );
-
-
- GradY = ConvY - MemY[memYline][imageWidth - 1];
- GradX = ConvX - MemX[(imageWidth - 2) & 1][L2];
-
- MemY[memYline][imageWidth - 1] = ConvY;
-
- GradT = (float) (imgB[Line2 + imageWidth - 1] - imgA[Line2 + imageWidth - 1]);
-
- II[address].xx = GradX * GradX;
- II[address].xy = GradX * GradY;
- II[address].yy = GradY * GradY;
- II[address].xt = GradX * GradT;
- II[address].yt = GradY * GradT;
- address++;
-
- /* End of derivatives for line */
-
- /****************************************************************************************/
- /* ---------Calculating horizontal convolution of processed line----------------------- */
- /****************************************************************************************/
- address -= BufferWidth;
- /* process first HorRadius pixels */
- for( j = 0; j < HorRadius; j++ )
- {
- int jj;
-
- WII[address].xx = 0;
- WII[address].xy = 0;
- WII[address].yy = 0;
- WII[address].xt = 0;
- WII[address].yt = 0;
-
- for( jj = -j; jj <= HorRadius; jj++ )
- {
- float Ker = KerX[jj];
-
- WII[address].xx += II[address + jj].xx * Ker;
- WII[address].xy += II[address + jj].xy * Ker;
- WII[address].yy += II[address + jj].yy * Ker;
- WII[address].xt += II[address + jj].xt * Ker;
- WII[address].yt += II[address + jj].yt * Ker;
- }
- address++;
- }
- /* process inner part of line */
- for( j = HorRadius; j < imageWidth - HorRadius; j++ )
- {
- int jj;
- float Ker0 = KerX[0];
-
- WII[address].xx = 0;
- WII[address].xy = 0;
- WII[address].yy = 0;
- WII[address].xt = 0;
- WII[address].yt = 0;
-
- for( jj = 1; jj <= HorRadius; jj++ )
- {
- float Ker = KerX[jj];
-
- WII[address].xx += (II[address - jj].xx + II[address + jj].xx) * Ker;
- WII[address].xy += (II[address - jj].xy + II[address + jj].xy) * Ker;
- WII[address].yy += (II[address - jj].yy + II[address + jj].yy) * Ker;
- WII[address].xt += (II[address - jj].xt + II[address + jj].xt) * Ker;
- WII[address].yt += (II[address - jj].yt + II[address + jj].yt) * Ker;
- }
- WII[address].xx += II[address].xx * Ker0;
- WII[address].xy += II[address].xy * Ker0;
- WII[address].yy += II[address].yy * Ker0;
- WII[address].xt += II[address].xt * Ker0;
- WII[address].yt += II[address].yt * Ker0;
-
- address++;
- }
- /* process right side */
- for( j = imageWidth - HorRadius; j < imageWidth; j++ )
- {
- int jj;
-
- WII[address].xx = 0;
- WII[address].xy = 0;
- WII[address].yy = 0;
- WII[address].xt = 0;
- WII[address].yt = 0;
-
- for( jj = -HorRadius; jj < imageWidth - j; jj++ )
- {
- float Ker = KerX[jj];
-
- WII[address].xx += II[address + jj].xx * Ker;
- WII[address].xy += II[address + jj].xy * Ker;
- WII[address].yy += II[address + jj].yy * Ker;
- WII[address].xt += II[address + jj].xt * Ker;
- WII[address].yt += II[address + jj].yt * Ker;
- }
- address++;
- }
- }
-
- /****************************************************************************************/
- /* Calculating velocity line */
- /****************************************************************************************/
- if( PixelLine >= 0 )
- {
- int USpace;
- int BSpace;
- int address;
-
- if( PixelLine < VerRadius )
- USpace = PixelLine;
- else
- USpace = VerRadius;
-
- if( PixelLine >= imageHeight - VerRadius )
- BSpace = imageHeight - PixelLine - 1;
- else
- BSpace = VerRadius;
-
- address = ((PixelLine - USpace) % BufferHeight) * BufferWidth;
- for( j = 0; j < imageWidth; j++ )
- {
- int addr = address;
-
- A1B2 = 0;
- A2 = 0;
- B1 = 0;
- C1 = 0;
- C2 = 0;
-
- for( i = -USpace; i <= BSpace; i++ )
- {
- A2 += WII[addr + j].xx * KerY[i];
- A1B2 += WII[addr + j].xy * KerY[i];
- B1 += WII[addr + j].yy * KerY[i];
- C2 += WII[addr + j].xt * KerY[i];
- C1 += WII[addr + j].yt * KerY[i];
-
- addr += BufferWidth;
- addr -= ((addr >= BufferSize) ? 0xffffffff : 0) & BufferSize;
- }
- /****************************************************************************************\
- * Solve Linear System *
- \****************************************************************************************/
- {
- float delta = (A1B2 * A1B2 - A2 * B1);
-
- if( delta )
- {
- /* system is not singular - solving by Kramer method */
- float deltaX;
- float deltaY;
- float Idelta = 8 / delta;
-
- deltaX = -(C1 * A1B2 - C2 * B1);
- deltaY = -(A1B2 * C2 - A2 * C1);
-
- velocityX[j] = deltaX * Idelta;
- velocityY[j] = deltaY * Idelta;
- }
- else
- {
- /* singular system - find optical flow in gradient direction */
- float Norm = (A1B2 + A2) * (A1B2 + A2) + (B1 + A1B2) * (B1 + A1B2);
-
- if( Norm )
- {
- float IGradNorm = 8 / Norm;
- float temp = -(C1 + C2) * IGradNorm;
-
- velocityX[j] = (A1B2 + A2) * temp;
- velocityY[j] = (B1 + A1B2) * temp;
-
- }
- else
- {
- velocityX[j] = 0;
- velocityY[j] = 0;
- }
- }
- }
- /****************************************************************************************\
- * End of Solving Linear System *
- \****************************************************************************************/
- } /*for */
- velocityX += velStep;
- velocityY += velStep;
- } /*for */
- PixelLine++;
- ConvLine++;
- }
-
- /* Free memory */
- for( k = 0; k < 2; k++ )
- {
- cvFree( &MemX[k] );
- cvFree( &MemY[k] );
- }
- cvFree( &II );
- cvFree( &WII );
-
- return CV_OK;
-} /*icvCalcOpticalFlowLK_8u32fR*/
-
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: cvCalcOpticalFlowLK
-// Purpose: Optical flow implementation
-// Context:
-// Parameters:
-// srcA, srcB - source image
-// velx, vely - destination image
-// Returns:
-//
-// Notes:
-//F*/
-CV_IMPL void
-cvCalcOpticalFlowLK( const void* srcarrA, const void* srcarrB, CvSize winSize,
- void* velarrx, void* velarry )
-{
- CV_FUNCNAME( "cvCalcOpticalFlowLK" );
-
- __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 ) ||
- !CV_ARE_SIZES_EQ( srcA, velx ))
- 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, "source and destination images have different step" );
-
- IPPI_CALL( icvCalcOpticalFlowLK_8u32fR( (uchar*)srcA->data.ptr, (uchar*)srcB->data.ptr,
- srcA->step, cvGetMatSize( srcA ), winSize,
- velx->data.fl, vely->data.fl, velx->step ));
-
- __END__;
-}
-
-/* End of file. */