⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camshift.cpp

📁 微软的基于HMM的人脸识别原代码, 非常经典的说
💻 CPP
字号:
/*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 <windows.h>
#include <CvCVcpp.h>
#include <math.h>
#include "CamShift.h"

//
// Constructor
//
CCamShift::CCamShift()
{
    m_trackFace.m_ShowBackProject = 0;
    m_trackFace.m_Track = 0;

    m_Size.width = 0;
    m_Size.height = 0;

    m_Window.x = 0;
    m_Window.y = 0;
    m_Window.width = 10;
    m_Window.height = 10;

    m_Histogram = 0;
    m_trackFace.m_Pins = 10;
    m_trackFace.m_Threshold = 0;

    m_BackProject = 0;
    m_Colour = 0;
    m_Stride = 0;
    m_StrideProject = 0;

    m_CalcHist = 0;

    m_Criteria.epsilon = 2;
    m_Criteria.maxIter = 10;
    m_Criteria.type    = CVL_TERMCRIT_ITER | CVL_TERMCRIT_EPS;

    m_Lenght = 0;
    m_Width = 0;
    m_Orientation = 0;
} // CamShift


//
// Transform
//
// 'In place' adjust the CamShift of this sample
//
void CCamShift::TrackFace( BYTE* pData, CvSize size, int stride )
{
    RGBQUAD* prgb;            // Holds a pointer to the current pixel

    // Get the image properties from the BITMAPINFOHEADER
    int cxImage    = size.width;
    int cyImage    = size.height;
    int x, y;

    PrepareData( cxImage, cyImage );
    calc_hue_image( pData, cxImage, cyImage, stride, m_Colour, m_Stride );
    if( m_CalcHist )
    {
        int temp = ((m_Stride >> 2) * m_Window.y) + m_Window.x;
        m_CalcHist = 0;
        ippiClearOutAllDataHist1D( m_Histogram );
        ippiCalcHist1D32fC1( m_Colour + temp,
                            m_Window.width,
                            m_Window.height,
                            m_Stride,
                            m_Histogram );
        ippiNormHist1D( m_Histogram );
    }

    ippiBackProject1D8uC1R( m_Histogram,
                           m_Colour,
                           m_Size,
                           m_Stride,
                           m_BackProject,
                           m_StrideProject );
    ippiThreshold8uC1S( m_BackProject,
                       m_trackFace.m_Threshold,
                       m_Size.width * sizeof( *m_BackProject ) * m_Size.height,
                       IPPI_THRESH_TOZERO );

    if( m_trackFace.m_ShowBackProject )
    {
        for( y = 0; y < cyImage; y++ )
        {
            prgb = (RGBQUAD*)(pData + y * stride);
            for( x = 0; x < cxImage; x++ )
            {
                prgb[x].rgbBlue = prgb[x].rgbGreen = prgb[x].rgbRed =
                    max( *(m_BackProject + y * m_StrideProject + x), 0 );
            }
        }
    }

    if( m_trackFace.m_Track )
    {
        if( m_Histogram->inputcount > 0 )
        {
            ippiCamShift8uC1R( m_BackProject,
                              m_Size,
                              m_StrideProject,
                              m_Window,
                              m_Criteria,
                              &m_Window,
                              &m_Orientation,
                              &m_Lenght,
                              &m_Width,
                              0,
                              0 );
            x = m_Window.x + m_Window.width / 2;
            y = m_Window.y + m_Window.height / 2;

            line( pData,
                  cxImage * sizeof( *prgb ),
                  (int)(x + m_Lenght * cos( m_Orientation ) / 2),
                  (int)(y + m_Lenght * sin( m_Orientation ) / 2),
                  (int)(x - m_Lenght * cos( m_Orientation ) / 2),
                  (int)(y - m_Lenght * sin( m_Orientation ) / 2),
                  -1 );
            line( pData,
                  cxImage * sizeof( *prgb ),
                  (int)(x + m_Width * sin( m_Orientation ) / 2),
                  (int)(y - m_Width * cos( m_Orientation ) / 2),
                  (int)(x - m_Width * sin( m_Orientation ) / 2),
                  (int)(y + m_Width * cos( m_Orientation ) / 2),
                  -1 );
        }
        else
        {
            box( pData,
                 cxImage * sizeof( *prgb ),
                 max( m_Window.x, 0 ),
                 max( m_Window.y, 0 ),
                 max( m_Window.x + m_Window.width, 0 ),
                 max( m_Window.y + m_Window.height, 0 ),
                 -1 );
        }
    }

    return;
}


void CCamShift::GetTrackingParams(CamShiftParam* trackFace)
{
    *trackFace = m_trackFace;
    return;
}

void CCamShift::SetTrackingParams(CamShiftParam  trackFace)
{
    m_trackFace = trackFace;
    return;
}

void CCamShift::SetRecalcHistogramFlag()
{
    m_CalcHist = 1;
    return;
}

void CCamShift::ResetHistogram()
{
    ippiClearOutAllDataHist1D( m_Histogram );
    return;
}

void CCamShift::SetWindow( CvRect window )
{
    m_Window = window;

    m_Window.x = max( 0, min( m_Size.width - 1, m_Window.x ) );
    m_Window.y = max( 0, min( m_Size.height - 1, m_Window.y ) );
    m_Window.width = max( 0, min( m_Size.width - 1 - m_Window.x, m_Window.width ) );
    m_Window.height = max( 0, min( m_Size.height - 1 - m_Window.y, m_Window.height ) );
    return;
}

void CCamShift::GetWindow( CvRect* window )
{
    *window = m_Window;
    return;
}


void CCamShift::PrepareData( int cx, int cy )
{
    if( cx != m_Size.width ||
        cy != m_Size.height )
    {
        m_Stride = cx * sizeof( *m_Colour );
        m_StrideProject = (cx + 8) & (int)(-8);
        m_Size.width  = cx;
        m_Size.height = cy;
        m_Colour = (float*)realloc( (void*)m_Colour, m_Stride * cy);
        m_BackProject = (BYTE*)realloc( (void*)m_BackProject, m_StrideProject * cy );
    }

    if( m_Histogram == NULL )
    {
        ippiCreateHist1D( m_trackFace.m_Pins, &m_Histogram );
        for( int i = 0; i < m_trackFace.m_Pins; i++ )
            m_Histogram->thresh[i] = (float)i * 255 / m_trackFace.m_Pins;
        m_Histogram->thresh[m_trackFace.m_Pins] = 255;
        ippiClearOutAllDataHist1D( m_Histogram );


    } else if( m_trackFace.m_Pins != m_Histogram->len )
    {
        ippiReleaseHist1D( &m_Histogram );
        ippiCreateHist1D( m_trackFace.m_Pins, &m_Histogram );
        for( int i = 0; i < m_trackFace.m_Pins; i++ )
            m_Histogram->thresh[i] = (float)i * 255 / m_trackFace.m_Pins;
        m_Histogram->thresh[m_trackFace.m_Pins] = 255;
        ippiClearOutAllDataHist1D( m_Histogram );
    }
}


void CCamShift::line( BYTE* src,
                      int stride,
                      int x1,
                      int y1,
                      int x2,
                      int y2,
                      int colour )
{
    x1 = max( 0, min( m_Size.width - 1, x1 ) );
    x2 = max( 0, min( m_Size.width - 1, x2 ) );
    y1 = max( 0, min( m_Size.height - 1, y1 ) );
    y2 = max( 0, min( m_Size.height - 1, y2 ) );

    int*  array;
    float size;
    int   vx = x2 - x1;
    int   vy = y2 - y1;

    if( vx ==0 && vy == 0 ) return;

    float step = 1.0f / max( abs(vx), abs(vy) );

    int   x, y;

    for( size = 0; size <= 1; size += step )
    {
        x = (int)(x1 + vx * size);
        y = (int)(y1 + vy * size);
        array = (int*)(src + y * stride);
        array[x] = colour;
    }
}


void   CCamShift::box( BYTE* src,
                       int stride,
                       int x1,
                       int y1,
                       int x2,
                       int y2,
                       int colour )
{
    line( src, stride, x1, y1, x2, y1, colour ); // up
    line( src, stride, x2, y1, x2, y2, colour ); // right
    line( src, stride, x1, y2, x2, y2, colour ); // down
    line( src, stride, x1, y1, x1, y2, colour ); // left
}
////////////////////  conversion ///////////////////////

#define SHIFT 12

static const int div_table[] =
{
       0, 1044480,  522240,  348160,  261120,  208896,  174080,  149211,
  130560,  116053,  104448,   94953,   87040,   80345,   74606,   69632,
   65280,   61440,   58027,   54973,   52224,   49737,   47476,   45412,
   43520,   41779,   40172,   38684,   37303,   36017,   34816,   33693,
   32640,   31651,   30720,   29842,   29013,   28229,   27486,   26782,
   26112,   25475,   24869,   24290,   23738,   23211,   22706,   22223,
   21760,   21316,   20890,   20480,   20086,   19707,   19342,   18991,
   18651,   18324,   18008,   17703,   17408,   17123,   16846,   16579,
   16320,   16069,   15825,   15589,   15360,   15137,   14921,   14711,
   14507,   14308,   14115,   13926,   13743,   13565,   13391,   13221,
   13056,   12895,   12738,   12584,   12434,   12288,   12145,   12006,
   11869,   11736,   11605,   11478,   11353,   11231,   11111,   10995,
   10880,   10768,   10658,   10550,   10445,   10341,   10240,   10141,
   10043,    9947,    9854,    9761,    9671,    9582,    9495,    9410,
    9326,    9243,    9162,    9082,    9004,    8927,    8852,    8777,
    8704,    8632,    8561,    8492,    8423,    8356,    8290,    8224,
    8160,    8097,    8034,    7973,    7913,    7853,    7795,    7737,
    7680,    7624,    7569,    7514,    7461,    7408,    7355,    7304,
    7253,    7203,    7154,    7105,    7057,    7010,    6963,    6917,
    6872,    6827,    6782,    6739,    6695,    6653,    6611,    6569,
    6528,    6487,    6447,    6408,    6369,    6330,    6292,    6254,
    6217,    6180,    6144,    6108,    6073,    6037,    6003,    5968,
    5935,    5901,    5868,    5835,    5803,    5771,    5739,    5708,
    5677,    5646,    5615,    5585,    5556,    5526,    5497,    5468,
    5440,    5412,    5384,    5356,    5329,    5302,    5275,    5249,
    5222,    5196,    5171,    5145,    5120,    5095,    5070,    5046,
    5022,    4998,    4974,    4950,    4927,    4904,    4881,    4858,
    4836,    4813,    4791,    4769,    4748,    4726,    4705,    4684,
    4663,    4642,    4622,    4601,    4581,    4561,    4541,    4522,
    4502,    4483,    4464,    4445,    4426,    4407,    4389,    4370,
    4352,    4334,    4316,    4298,    4281,    4263,    4246,    4229,
    4212,    4195,    4178,    4161,    4145,    4128,    4112,    4096
};

#define mmax(a,b)    ((b) + (((a)-(b))&((a)>(b)?-1:0)))
#define mmin(a,b)    ((a) - (((a)-(b))&((a)>(b)?-1:0)))


void CCamShift::calc_hue_image( BYTE *src,
                                int w,
                                int hh,
                                int src_pitch,
                                float *dst,
                                int dst_pitch )
{
    const planes = 4;
    int   x, y, x1;

    dst_pitch >>= 2;

    //for( int i = 0; i < dst_pitch * h; i++ ) dst[i] = -1;

    for( y = 0; y < hh; y++, src += src_pitch, dst += dst_pitch )
        for( x = 0, x1 = 0; x < w * planes; x+=planes, x1++ )
        {
            int b, g, r;

            b = src[x];
            g = src[x+1];
            r = src[x+2];

            // convert rgb->hsv
            int h, s, v;
            {
            int vmin, diff;
            int vr, vg;

            v    = mmax(r,g);
            v    = mmax(v,b);
            vmin = mmin(r,g);
            vmin = mmin(vmin,b);

            diff = v - vmin;
            vr = v == r ? -1 : 0;
            vg = v == g ? -1 : 0;

            s  = diff*div_table[v]>>SHIFT;
            h  = (vr&(g-b)) + (~vr&((vg&(b-r+2*diff)) + ((~vg)&(r-g+4*diff))));
            h  = ((h*div_table[diff]*15+(1<<(SHIFT+6)))>>(7+SHIFT)) + (h < 0 ? 30*6 : 0);
            }

            if( s > 30 && v > 10 /*&& v < 220*/ )
                dst[x1] = (float)h;
            else
                dst[x1] = -1;
        }
}


⌨️ 快捷键说明

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