视频分析与对象跟踪(四)(CAMShift)

在介绍CAMShift算法之前,我们先了解一下meanshift(均值漂移)算法。

meanshift是一种是基于核密度估计的爬山算法,可用于聚类、图像分割、跟踪等。
在这里插入图片描述
(1)均值漂移的基本形式

给定d维空间的n个数据点集X,那么对于空间中的任意点x的mean shift向量基本形式可以表示为:
在这里插入图片描述
这个向量就是漂移向量,其中Sk表示的是数据集的点到x的距离小于球半径h的数据点。也就是:
在这里插入图片描述
而漂移的过程,说的简单一点,就是通过计算得漂移向量,然后把球圆心x的位置更新一下,更新公式为:在这里插入图片描述
其中Mh为偏移量。
总结为一句话就是:求解一个向量,使得圆心一直往数据集密度最大的方向移动。说的再简单一点,就是每次迭代的时候,都是找到圆里面点的平均位置作为新的圆心位置。
(2)加入核函数的漂移向量

这个说的简单一点就是加入一个高斯权重,最后的漂移向量计算公式为:
在这里插入图片描述
因此每次更新的圆心坐标为:
在这里插入图片描述
在原图中选定roi区域,可以得到这个roi区域的直方图,和原图像的直方图比较找到最相近的直方图区域,最后直方图反向映射,实现定位。同样的选取第二帧的图像中与roi区域最近的直方图区域(直方图取值范围相同,且需要通过归一化来避免光照带来的影响),反向映射到选取的第二帧图像中,实现第二帧图像中roi区域的定位。
在这里插入图片描述

Meanshift算法缺点,选定的rio区域的大小是不能改变的,但是图像的形状或者大小已经改变了,定位不准确,所以引入了CAMShift(持续自适应Meanshift算法)。

CAMShift可以满足窗口尺寸自适应变化及适合变形目标检测。
因为RGB图像要共有5维(考虑了变量x,y),这里用HSV空间的H来代替。其具体转化见下图:
在这里插入图片描述
流程图:
在这里插入图片描述
代码实现(opencv+c++):

#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include <iostream>
#include <math.h>

	using namespace cv;
	using namespace std;

	int smin = 15;
	int vmin = 40;
	int vmax = 256;
	int bins = 16;

	int main(int argc, char** argv) {
		VideoCapture capture;
		capture.open("D:/picture/opencv/images/video_003.avi");
		if (!capture.isOpened()) {
			printf("could not find video data file...\n");
			return -1;
		}
		namedWindow("CAMShift Tracking", CV_WINDOW_AUTOSIZE);
		namedWindow("ROI Histogram", CV_WINDOW_AUTOSIZE);

		bool firstRead = true;
		float hrange[] = { 0, 180 };
		const float* hranges = hrange;
		Rect selection;
		Mat frame, hsv, hue, mask, hist, backprojection;
		Mat drawImg = Mat::zeros(300, 300, CV_8UC3);
		while (capture.read(frame)) {
			if (firstRead) {
				Rect2d first = selectROI("CAMShift Tracking", frame);
				selection.x = first.x;
				selection.y = first.y;
				selection.width = first.width;
				selection.height = first.height;
				printf("ROI.x= %d, ROI.y= %d, width = %d, height= %d", selection.x, selection.y, selection.width, selection.height);
			}
			// convert to HSV
			cvtColor(frame, hsv, COLOR_BGR2HSV);
			inRange(hsv, Scalar(0, smin, vmin), Scalar(180, vmax, vmax), mask);
			hue = Mat(hsv.size(), hsv.depth());
			int channels[] = { 0, 0 };
			mixChannels(&hsv, 1, &hue, 1, channels, 1);

			if (firstRead) {
				// ROI 直方图计算
				Mat roi(hue, selection);
				Mat maskroi(mask, selection);
				calcHist(&roi, 1, 0, maskroi, hist, 1, &bins, &hranges);
				normalize(hist, hist, 0, 255, NORM_MINMAX);

				// show histogram
				int binw = drawImg.cols / bins;
				Mat colorIndex = Mat(1, bins, CV_8UC3);
				for (int i = 0; i < bins; i++) {
					colorIndex.at<Vec3b>(0, i) = Vec3b(saturate_cast<uchar>(i * 180 / bins), 255, 255);
				}
				cvtColor(colorIndex, colorIndex, COLOR_HSV2BGR);
				for (int i = 0; i < bins; i++) {
					int  val = saturate_cast<int>(hist.at<float>(i)*drawImg.rows / 255);
					rectangle(drawImg, Point(i*binw, drawImg.rows), Point((i + 1)*binw, drawImg.rows - val), Scalar(colorIndex.at<Vec3b>(0, i)), -1, 8, 0);
				}
			}

			// back projection
			calcBackProject(&hue, 1, 0, hist, backprojection, &hranges);
			// CAMShift tracking
			backprojection &= mask;
			RotatedRect trackBox = CamShift(backprojection, selection, TermCriteria((TermCriteria::COUNT | TermCriteria::EPS), 10, 1));

			// draw location on frame;
			ellipse(frame, trackBox, Scalar(0, 0, 255), 3, 8);

			if (firstRead) {
				firstRead = false;
			}
			imshow("CAMShift Tracking", frame);
			imshow("ROI Histogram", drawImg);
			char c = waitKey(50);// ESC
			if (c == 27) {
				break;
			}
		}

		capture.release();
		waitKey(0);
		return 0;
	}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Camshift算法(Continuously Adaptive Mean Shift)是一种在视频跟踪特定对象的算法。下面是如何使用Camshift算法跟踪视频中的对象的步骤: 1. 首先,从视频中选择一个初始的感兴趣区域(Region of Interest,ROI),该区域内包含要跟踪对象。可以通过人工手动选择或使用计算机自动选择。 2. 接下来,将ROI转换为HSV(色调、饱和度、亮度)颜色空间。HSV颜色空间相对于RGB颜色空间更容易进行颜色跟踪。 3. 计算从初始帧到当前帧的直方图,并使用Mean Shift算法迭代更新直方图。这可以通过使用当前帧在ROI区域内的像素进行计算。 4. 使用Camshift公式将Mean Shift算法的迭代结果转化为跟踪窗口的新位置和大小。这个公式会根据直方图的峰值,计算出新的位置和大小。 5. 更新ROI的位置和大小,将其作为下一个帧的初始区域。这可以保持跟踪窗口在对象的周围。 6. 重复步骤3到5,直到视频结束或者对象移出画面。 Camshift算法的优点是它可以自适应跟踪目标的形状和大小,在对象发生变化时能够及时适应。它的性能在对比度低或光照变化较大的情况下也比较稳定。然而,它对于出现部分遮挡的情况可能不能很好地处理。 在实际应用中,可以使用计算机视觉库(如OpenCV)来实现Camshift算法。通过读取视频流,在每个视频帧中使用Camshift算法进行目标跟踪,并将跟踪结果显示在视频中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值