OpenCV 4.11.0
开源计算机视觉库
加载中…
搜索中…
未找到匹配项
自定义 CN Tracker

目标

在本教程中,您将学习如何:

  • 为 CN Tracker 设置自定义参数。
  • 为 CN Tracker 使用您自己的特征提取函数。

本文档包含 cv::TrackerKCF 的教程。

源代码

3#include <opencv2/videoio.hpp>
4#include <opencv2/highgui.hpp>
5#include <iostream>
6#include <cstring>
7#include "samples_utility.hpp"
8
9using namespace std;
10using namespace cv;
11
12// 特征提取函数原型
13void sobelExtractor(const Mat img, const Rect roi, Mat& feat);
14
15int main( int argc, char** argv ){
16 // 显示帮助信息
17 if(argc<2){
18 cout<<
19 " 用法:tracker <视频名称>\n"
20 " 示例:\n"
21 " example_tracking_kcf Bolt/img/%04d.jpg\n"
22 " example_tracking_kcf faceocc2.webm\n"
23 << endl;
24 return 0;
25 }
26
27 // 声明所有需要的变量
28 Rect roi;
29 Mat frame;
30
33 param.desc_pca = TrackerKCF::GRAY | TrackerKCF::CN;
34 param.desc_npca = 0;
35 param.compress_feature = true;
36 param.compressed_size = 2;
38
39 // 创建追踪器对象
41 Ptr<TrackerKCF> tracker = TrackerKCF::create(param);
43
45 tracker->setFeatureExtractor(sobelExtractor);
47
48 // 设置输入视频
49 std::string video = argv[1];
50 VideoCapture cap(video);
51
52 // 获取边界框
53 cap >> frame;
54 roi=selectROI("tracker",frame);
55
56 // 如果未选择 ROI,则退出
57 if(roi.width==0 || roi.height==0)
58 return 0;
59
60 // 初始化追踪器
61 tracker->init(frame,roi);
62
63 // 执行追踪过程
64 printf("开始追踪过程,按 ESC 键退出。\n");
65 for ( ;; ){
66 // 从视频中获取帧
67 cap >> frame;
68
69 // 如果没有更多图像,则停止程序
70 if(frame.rows==0 || frame.cols==0)
71 break;
72
73 // 更新追踪结果
74 tracker->update(frame,roi);
75
76 // 绘制追踪到的对象
77 rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );
78
79 // 显示包含追踪对象的图像
80 imshow("tracker",frame);
81
82 // 按 ESC 键退出
83 if(waitKey(1)==27)break;
84 }
85
86 return 0;
87}
88
89void sobelExtractor(const Mat img, const Rect roi, Mat& feat){
90 Mat sobel[2];
91 Mat patch;
92 Rect region=roi;
93
95 // 从图像中提取区域块
96 if(roi.x<0){region.x=0;region.width+=roi.x;}
97 if(roi.y<0){region.y=0;region.height+=roi.y;}
98 if(roi.x+roi.width>img.cols)region.width=img.cols-roi.x;
99 if(roi.y+roi.height>img.rows)region.height=img.rows-roi.y;
100 if(region.width>img.cols)region.width=img.cols;
101 if(region.height>img.rows)region.height=img.rows;
103
104 patch=img(region).clone();
105 cvtColor(patch,patch, COLOR_BGR2GRAY);
106
108 // 添加填充以补偿区域块超出图像边界的区域
109 int addTop,addBottom, addLeft, addRight;
110 addTop=region.y-roi.y;
111 addBottom=(roi.height+roi.y>img.rows?roi.height+roi.y-img.rows:0);
112 addLeft=region.x-roi.x;
113 addRight=(roi.width+roi.x>img.cols?roi.width+roi.x-img.cols:0);
114
115 copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
117
119 Sobel(patch, sobel[0], CV_32F,1,0,1);
120 Sobel(patch, sobel[1], CV_32F,0,1,1);
121
122 merge(sobel,2,feat);
124
126 feat=feat/255.0-0.5; // 归一化到 -0.5 .. 0.5 的范围
128}
n维密集数组类
定义 mat.hpp:829
CV_NODISCARD_STD Mat clone() const
创建数组和底层数据的完整副本。
int cols
定义 mat.hpp:2155
int rows
行和列的数量,当矩阵的维度大于2时为(-1, -1)
定义 mat.hpp:2155
二维矩形的模板类。
定义 types.hpp:444
_Tp x
左上角的x坐标
定义 types.hpp:487
_Tp y
左上角的y坐标
定义 types.hpp:488
_Tp width
矩形的宽度
定义 types.hpp:489
_Tp height
矩形的高度
定义 types.hpp:490
用于从视频文件、图像序列或摄像机捕获视频的类。
定义 videoio.hpp:766
void copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar &value=Scalar())
在图像周围形成边界。
void merge(const Mat *mv, size_t count, OutputArray dst)
从多个单通道数组创建一个多通道数组。
std::shared_ptr< _Tp > Ptr
定义 cvstd_wrapper.hpp:23
#define CV_32F
定义 interface.h:78
void sobel(InputArray _src, OutputArray _dx, OutputArray _dy, int kernel_size, int borderType, int borderValue)
从源亮度数据创建二维梯度图像,无需归一化。计算X方向1…
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0, AlgorithmHint hint=cv::ALGO_HINT_DEFAULT)
将图像从一个颜色空间转换为另一个颜色空间。
void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
使用扩展的Sobel算子计算图像的一阶、二阶、三阶或混合导数。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
定义 core.hpp:107
STL 命名空间。
定义 tracking.hpp:118
bool compress_feature
激活 pca 方法来压缩特征
定义 tracking.hpp:130
int desc_pca
TrackerKCF::MODE 的压缩描述符
定义 tracking.hpp:133
int desc_npca
TrackerKCF::MODE 的非压缩描述符
定义 tracking.hpp:134
int compressed_size
压缩后的特征大小
定义 tracking.hpp:132

解释

本部分解释如何设置自定义参数以及为 CN 跟踪器使用您自己的特征提取器函数。如果您需要有关使用cv::Tracker 的更多详细信息,请参考OpenCV 跟踪器简介

  1. 设置自定义参数

    param.desc_pca = TrackerKCF::GRAY | TrackerKCF::CN;
    param.desc_npca = 0;
    param.compress_feature = true;
    param.compressed_size = 2;

    要设置自定义参数,应创建一个对象。每个跟踪器算法都有其自己的参数格式。因此,在这种情况下,我们应该使用来自cv::TrackerKCF 的参数,因为我们感兴趣的是修改此跟踪器算法的参数。

    cv::TrackerKCF::Params 中所述,可以配置多个参数。在本教程中,我们重点关注特征提取器函数。

    cv::TrackerKCF 中可以使用几种特征类型。在这种情况下,灰度值(1 维)和颜色名称特征(10 维)将合并为 11 维特征,然后如代码中指定的压缩为 2 维。

    如果要使用另一种预定义的特征提取器函数,可以在cv::TrackerKCF::MODE 中查看。我们将非压缩特征保留为 0,因为我们想要使用自定义函数。

  2. 使用自定义函数

    您可以为 CN 跟踪器定义自己的特征提取器函数。但是,您需要注意以下几点

    • 提取的特征应与给定边界框的大小(宽度和高度)相同。对于通道数,您可以检查cv::Mat 中的限制。
    • 您只能使用可以使用欧几里得距离进行比较的特征。像局部二值模式 (LBP) 这样的特征可能不适合,因为它应该使用汉明距离进行比较。

    由于提取的特征的大小应与给定边界框的大小相同,因此每当给定边界框部分超出范围时,我们都需要注意。在这种情况下,我们可以复制边界框中包含的图像的一部分,如下面的代码段所示。

    // 提取图像内的块
    如果(roi.x<0){region.x=0;region.width+=roi.x;}
    如果(roi.y<0){region.y=0;region.height+=roi.y;}
    如果(roi.x+roi.width>img.cols)region.width=img.cols-roi.x;
    如果(roi.y+roi.height>img.rows)region.height=img.rows-roi.y;
    如果(region.width>img.cols)region.width=img.cols;
    如果(region.height>img.rows)region.height=img.rows;

    每当复制的图像小于给定的边界框时,应在边界框部分超出框架的侧面添加填充。

    // 添加一些填充以补偿块在图像边界之外的情况
    int addTop,addBottom, addLeft, addRight;
    addTop=region.y-roi.y;
    addBottom=(roi.height+roi.y>img.rows?roi.height+roi.y-img.rows:0);
    addLeft=region.x-roi.x;
    addRight=(roi.width+roi.x>img.cols?roi.width+roi.x-img.cols:0);
    copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
  3. 定义特征

    在本教程中,提取的特征是 x 和 y 方向上 Sobel 滤波器的响应。这些 Sobel 滤波器响应被连接起来,形成一个具有 2 个通道的特征。

    Sobel(patch, sobel[0], CV_32F,1,0,1);
    Sobel(patch, sobel[1], CV_32F,0,1,1);
    merge(sobel,2,feat);
  4. 后处理

    确保将特征归一化到 -0.5 到 0.5 的范围内

    feat=feat/255.0-0.5; // 归一化到 -0.5 .. 0.5 范围