- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
找到物体的中心、大小和方向。
CamShift(Continuously Adaptive Mean Shift)是 OpenCV 中的一种目标跟踪算法,广泛应用于视频中对象的跟踪。CamShift 算法结合了 Mean Shift 算法和颜色直方图,通过迭代寻找目标区域的颜色分布中心,从而实现目标的跟踪。
基本原理
- 颜色直方图:首先,根据目标区域的颜色信息构建颜色直方图。颜色直方图描述了目标区域中各颜色的分布情况。
- Mean Shift:Mean Shift 算法通过迭代寻找目标区域的颜色分布中心,逐步调整目标区域的位置和大小。
- 适应性调整:CamShift 算法不仅调整目标区域的位置,还根据目标区域的颜色分布调整其大小和方向,从而实现更精确的跟踪。
代码示例
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
Rect selection;
bool selecting = false;
bool trackObject = false;
Point origin;
Mat frame; // 声明一个全局变量来存储当前帧
void onMouse( int event, int x, int y, int, void* )
{
if ( selecting )
{
selection.x = MIN( x, origin.x );
selection.y = MIN( y, origin.y );
selection.width = abs( x - origin.x );
selection.height = abs( y - origin.y );
selection &= Rect( 0, 0, frame.cols, frame.rows ); // 使用全局变量 frame
}
switch ( event )
{
case EVENT_LBUTTONDOWN:
selecting = true;
origin = Point( x, y );
selection = Rect( x, y, 0, 0 );
break;
case EVENT_LBUTTONUP:
selecting = false;
if ( selection.width > 0 && selection.height > 0 )
{
trackObject = true;
}
break;
}
}
int main()
{
VideoCapture cap(0);
if ( !cap.isOpened() )
{
cerr << "Error opening video file" << endl;
return -1;
}
namedWindow( "CamShift Tracker", WINDOW_NORMAL );
setMouseCallback( "CamShift Tracker", onMouse );
while ( true )
{
cap >> frame;
if ( frame.empty() )
break;
Mat hsv_frame, hue_frame, mask, backproj;
cvtColor( frame, hsv_frame, COLOR_BGR2HSV );
if ( trackObject )
{
// 提取 H(色调)通道
vector< Mat > hsv_channels;
split( hsv_frame, hsv_channels );
Mat hue_channel = hsv_channels[ 0 ];
// 计算颜色直方图
Mat roi = hue_channel( selection );
Mat hsv_hist;
int histSize[] = { 32 };
float hranges[] = { 0, 180 };
const float* ranges[] = { hranges };
calcHist( &roi, 1, 0, Mat(), hsv_hist, 1, histSize, ranges, true, false );
normalize( hsv_hist, hsv_hist, 0, 255, NORM_MINMAX );
// 计算反投影
calcBackProject( &hue_channel, 1, 0, hsv_hist, backproj, ranges, 1, true );
// 使用 CamShift 进行跟踪
TermCriteria term_crit( TermCriteria::COUNT | TermCriteria::EPS, 10, 1 );
RotatedRect track_box = CamShift( backproj, selection, term_crit );
// 绘制跟踪结果
ellipse( frame, track_box, Scalar( 0, 255, 0 ), 2 );
}
// 绘制选择区域
if ( selecting )
{
rectangle( frame, selection, Scalar( 255, 0, 0 ), 2 );
}
imshow( "CamShift Tracker", frame );
char c = waitKey( 30 );
if ( c == 27 )
break; // 按下 ESC 键退出
}
cap.release();
destroyAllWindows();
return 0;
}