博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
运动目标跟踪与检测的源代码(CAMSHIFT 算法)
阅读量:6594 次
发布时间:2019-06-24

本文共 6256 字,大约阅读时间需要 20 分钟。

2004年09月07日 15:25:00

采用 CAMSHIFT 算法快速跟踪和检测运动目标的 C/C++ 源代码,OPENCV BETA 4.0 版本在其 SAMPLE 中给出了这个例子。算法的简单描述如下(英文):

This application demonstrates a fast, simple color tracking algorithm that can be used to track faces, hands . The CAMSHIFT algorithm is a modification of the Meanshift algorithm which is a robust statistical method of finding the mode (top) of a probability distribution. Both CAMSHIFT and Meanshift algorithms exist in the library. While it is a very fast and simple method of tracking, because CAMSHIFT tracks the center and size of the probability distribution of an object, it is only as good as the probability distribution that you produce for the object. Typically the probability distribution is derived from color via a histogram, although it could be produced from correlation, recognition scores or bolstered by frame differencing or motion detection schemes, or joint probabilities of different colors/motions etc.

In this application, we use only the most simplistic approach: A 1-D Hue histogram is sampled from the object in an HSV color space version of the image. To produce the probability image to track, histogram "back projection" (we replace image pixels by their histogram hue value) is used.

算法的详细情况,请看论文:

关于OPENCV B4.0 库的使用方法以及相关问题,请查阅下面的相关文章:

运行文件下载:

该运行文件在VC6.0环境下编译通过,是一个 stand-alone 运行程序,不需要OPENCV的DLL库支持。在运行之前,请先连接好USB接口的摄像头。然后可以用鼠标选定欲跟踪目标。

=====

#ifdef _CH_

#pragma package <opencv>
#endif

#ifndef _EiC

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <ctype.h>
#endif

IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;

CvHistogram *hist = 0;

int backproject_mode = 0;

int select_object = 0;
int track_object = 0;
int show_hist = 1; 
CvPoint origin;
CvRect selection;
CvRect track_window;
CvBox2D track_box;  // tracking 返回的区域 box,带角度
CvConnectedComp track_comp;
int hdims = 48;     // 划分HIST的个数,越高越精确
float hranges_arr[] = {0,180};
float* hranges = hranges_arr;
int vmin = 10, vmax = 256, smin = 30;

void on_mouse( int event, int x, int y, int flags )

{
    if( !image )
        return;

    if( image->origin )

        y = image->height - y;

    if( select_object )

    {
        selection.x = MIN(x,origin.x);
        selection.y = MIN(y,origin.y);
        selection.width = selection.x + CV_IABS(x - origin.x);
        selection.height = selection.y + CV_IABS(y - origin.y);
       
        selection.x = MAX( selection.x, 0 );
        selection.y = MAX( selection.y, 0 );
        selection.width = MIN( selection.width, image->width );
        selection.height = MIN( selection.height, image->height );
        selection.width -= selection.x;
        selection.height -= selection.y;

    }

    switch( event )

    {
    case CV_EVENT_LBUTTONDOWN:
        origin = cvPoint(x,y);
        selection = cvRect(x,y,0,0);
        select_object = 1;
        break;
    case CV_EVENT_LBUTTONUP:
        select_object = 0;
        if( selection.width > 0 && selection.height > 0 )
            track_object = -1;
#ifdef _DEBUG
    printf("\n # 鼠标的选择区域:");
    printf("\n   X = %d, Y = %d, Width = %d, Height = %d",
        selection.x, selection.y, selection.width, selection.height);
#endif
        break;
    }
}

CvScalar hsv2rgb( float hue )
{
    int rgb[3], p, sector;
    static const int sector_data[][3]=
        {
{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
    hue *= 0.033333333333333333333333333333333f;
    sector = cvFloor(hue);
    p = cvRound(255*(hue - sector));
    p ^= sector & 1 ? 255 : 0;

    rgb[sector_data[sector][0]] = 255;

    rgb[sector_data[sector][1]] = 0;
    rgb[sector_data[sector][2]] = p;

#ifdef _DEBUG

    printf("\n # Convert HSV to RGB:");
    printf("\n   HUE = %f", hue);
    printf("\n   R = %d, G = %d, B = %d", rgb[0],rgb[1],rgb[2]);
#endif

    return cvScalar(rgb[2], rgb[1], rgb[0],0);

}

int main( int argc, char** argv )

{
    CvCapture* capture = 0;
    IplImage* frame = 0;
   
    if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
    else if( argc == 2 )
        capture = cvCaptureFromAVI( argv[1] );

    if( !capture )

    {
        fprintf(stderr,"Could not initialize capturing...\n");
        return -1;
    }

    printf( "Hot keys: \n"

        "\tESC - quit the program\n"
        "\tc - stop the tracking\n"
        "\tb - switch to/from backprojection view\n"
        "\th - show/hide object histogram\n"
        "To initialize tracking, select the object with mouse\n" );

    //cvNamedWindow( "Histogram", 1 );

    cvNamedWindow( "CamShiftDemo", 1 );
    cvSetMouseCallback( "CamShiftDemo", on_mouse ); // on_mouse 自定义事件
    cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
    cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
    cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );

    for(;;)

    {
        int i, bin_w, c;

        frame = cvQueryFrame( capture );

        if( !frame )
            break;

        if( !image )

        {
           
            image = cvCreateImage( cvGetSize(frame), 8, 3 );
            image->origin = frame->origin;
            hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
            hue = cvCreateImage( cvGetSize(frame), 8, 1 );
            mask = cvCreateImage( cvGetSize(frame), 8, 1 );
            backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
            hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );  // 计算直方图
            histimg = cvCreateImage( cvSize(320,200), 8, 3 );
            cvZero( histimg );
        }

        cvCopy( frame, image, 0 );

        cvCvtColor( image, hsv, CV_BGR2HSV );  // 彩色空间转换 BGR to HSV

        if( track_object )

        {
            int _vmin = vmin, _vmax = vmax;

            cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),

                        cvScalar(180,256,MAX(_vmin,_vmax),0), mask );  // 得到二值的MASK
            cvSplit( hsv, hue, 0, 0, 0 );  // 只提取 HUE 分量

            if( track_object < 0 )

            {
                float max_val = 0.f;
                cvSetImageROI( hue, selection );  // 得到选择区域 for ROI
                cvSetImageROI( mask, selection ); // 得到选择区域 for mask
                cvCalcHist( &hue, hist, 0, mask ); // 计算直方图
                cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );  // 只找最大值
                cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); // 缩放 bin 到区间 [0,255]
                cvResetImageROI( hue );  // remove ROI
                cvResetImageROI( mask );
                track_window = selection;
                track_object = 1;

                cvZero( histimg );

                bin_w = histimg->width / hdims;  // hdims: 条的个数,则 bin_w 为条的宽度
               
                // 画直方图
                for( i = 0; i < hdims; i++ )
                {
                    int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
                    CvScalar color = hsv2rgb(i*180.f/hdims);
                    cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
                                 cvPoint((i+1)*bin_w,histimg->height - val),
                                 color, -1, 8, 0 );
                }
            }

            cvCalcBackProject( &hue, backproject, hist );  // 使用 back project 方法

            cvAnd( backproject, mask, backproject, 0 );

本文转自feisky博客园博客,原文链接:http://www.cnblogs.com/feisky/archive/2008/04/11/1586560.html,如需转载请自行联系原作者

你可能感兴趣的文章
第二课:第四讲02_04_Linux文件管理命令详解
查看>>
SCI论文写作技巧
查看>>
学习中的简略笔记小结。
查看>>
我最喜欢的五款手机APP 简直就是生活的小帮手
查看>>
智能硬件、移动内容生态成两大引擎,从百度年报看其多元化发
查看>>
UC伯克利发布一个低成本家居机器人,会叠衣服、会泡咖啡
查看>>
理解孩子的游戏世界
查看>>
通过python-ldap操作管理AD/LDAP用户及组织结构
查看>>
Java面试题总结
查看>>
IOS学习资源收集--开发UI控件相关
查看>>
python大数据之spark:linux上配置ssh无验证登录
查看>>
实验:基于YUM安装的多实例
查看>>
权限用户和文本处理。
查看>>
Apache
查看>>
Eclispe中Jetty中文乱码问题
查看>>
linux下PXE+Kickstart无人值守安装操作系统
查看>>
关于线程Thread中断
查看>>
JavaScript操作Table和动态生成Table
查看>>
ORACLE解决高水位线问题
查看>>
70行代码实现的神经网络算法
查看>>