opencv2均值漂移算法

为了方便调用,我将opencv2许多常用的函数以及功能都封装在一个类里面,所以这次的均值漂移算法也将从封装类中截取出来,供大家学习

类的代码:

class Package
{
private:

public:
	Rect MeanShitfMath(const Mat &OrgInImage, const Mat &PreInImage, Rect &ROIrect);
};

Rect Package::MeanShitfMath(const Mat &OrgInImage, const Mat &PreInImage, Rect &ROIrect)
{
	Mat orgimg = OrgInImage;
	Mat preimg = PreInImage;

	/*先对输入的原始图像进行感兴趣区域的采集*/
	//先获取感兴趣区域的图像
	Mat bgrROI = orgimg(ROIrect);

	//将感兴趣区域的BGR空间转换为HSV空间
	Mat hsvROI;
	cvtColor(bgrROI, hsvROI, CV_BGR2HSV);
	//获取感兴趣区域的HSV空间的S空间
	vector<Mat>hsvROIvector;
	split(hsvROI, hsvROIvector);
	//将S通道的阀值化
	threshold(hsvROIvector[1], hsvROIvector[1], 65, 255.0, THRESH_BINARY);
	//计算S通道的直方图
	float hranges[2];
	const float* ranges[1];
	int channels[1];
	MatND hsvROIhist;
	int histSize[1];
	hranges[0] = 0.0;
	hranges[1] = 180.0;
	ranges[0] = hranges;
	channels[0] = 0;
	histSize[0] = 256;
	calcHist(&hsvROIvector[1], 1, channels, Mat(), hsvROIhist, 1, histSize, ranges);

	//归一化直方图
	normalize(hsvROIhist, hsvROIhist, 1.0);

	/*在输入的第二幅图像中进行均值漂移算法*/
	Mat prehsv;
	cvtColor(preimg, prehsv, CV_BGR2HSV);
	vector<Mat>prehsvvector;
	split(prehsv, prehsvvector);
	/*threshold(prehsvvector[1], prehsvvector[1], 65, 255.0, THRESH_BINARY);*/
	//在第二幅图上获取感兴趣区域的直方图的反投影
	Mat result;
	calcBackProject(&(prehsvvector[1]), 1, channels, hsvROIhist, result, ranges, 255.0);
	threshold(result, result, 255 * (-1.0f), 255.0, THRESH_BINARY);
	bitwise_and(result, prehsvvector[1], result);

	/*rectangle(preimg, ROIrect, Scalar(0, 0, 255));*/
	//meanshift算法
	TermCriteria criteria(TermCriteria::MAX_ITER, 10, 0.01);
	meanShift(result, ROIrect, criteria);
	/*rectangle(preimg, ROIrect, Scalar(0, 255, 0));*/

	return ROIrect;
}


基本思路:
  1、先在输入的原始图像中找到感兴趣的区域,并将这个感兴趣区域的直方图计算出来(不过这次计算的直方图不是BGR空间下的,而是HSV空间下的,所以需要
  先转换颜色空间),也不再是得到改感兴趣区域某一个通道下的直方图信息,而是得到HSV空间的S通道的改感兴趣区域的直方图(需分解)
  2、然后就是在第二幅图像中将上一部得到的感兴趣区域的S通道的直方图进行反投影,反投影到第二幅图像中的S通道上
  3、反投影完成后就开始进行meanshift算法

返回的是一个Rect类型的矩形区域,这个矩形是通过均值漂移算法在另一张图中找到的相似的区域,在主函数中可以用rectangle函数降其显示出来


测试代码:

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/imgproc/types_c.h>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<iostream>
#include<vector>
#include<opencv2/nonfree/features2d.hpp>
#include<opencv2/legacy/legacy.hpp>
#include<opencv2/features2d/features2d.hpp>
#include<opencv2/calib3d/calib3d.hpp>
#include<opencv2/video/tracking.hpp>

using namespace cv;
using namespace std;

class Package
{
private:

public:
	Rect MeanShitfMath(const Mat &OrgInImage, const Mat &PreInImage, Rect &ROIrect);
};

Rect Package::MeanShitfMath(const Mat &OrgInImage, const Mat &PreInImage, Rect &ROIrect)
{
	Mat orgimg = OrgInImage;
	Mat preimg = PreInImage;

	/*先对输入的原始图像进行感兴趣区域的采集*/
	//先获取感兴趣区域的图像
	Mat bgrROI = orgimg(ROIrect);

	//将感兴趣区域的BGR空间转换为HSV空间
	Mat hsvROI;
	cvtColor(bgrROI, hsvROI, CV_BGR2HSV);
	//获取感兴趣区域的HSV空间的S空间
	vector<Mat>hsvROIvector;
	split(hsvROI, hsvROIvector);
	//将S通道的阀值化
	threshold(hsvROIvector[1], hsvROIvector[1], 65, 255.0, THRESH_BINARY);
	//计算S通道的直方图
	float hranges[2];
	const float* ranges[1];
	int channels[1];
	MatND hsvROIhist;
	int histSize[1];
	hranges[0] = 0.0;
	hranges[1] = 180.0;
	ranges[0] = hranges;
	channels[0] = 0;
	histSize[0] = 256;
	calcHist(&hsvROIvector[1], 1, channels, Mat(), hsvROIhist, 1, histSize, ranges);

	//归一化直方图
	normalize(hsvROIhist, hsvROIhist, 1.0);

	/*在输入的第二幅图像中进行均值漂移算法*/
	Mat prehsv;
	cvtColor(preimg, prehsv, CV_BGR2HSV);
	vector<Mat>prehsvvector;
	split(prehsv, prehsvvector);
	/*threshold(prehsvvector[1], prehsvvector[1], 65, 255.0, THRESH_BINARY);*/
	//在第二幅图上获取感兴趣区域的直方图的反投影
	Mat result;
	calcBackProject(&(prehsvvector[1]), 1, channels, hsvROIhist, result, ranges, 255.0);
	threshold(result, result, 255 * (-1.0f), 255.0, THRESH_BINARY);
	bitwise_and(result, prehsvvector[1], result);

	/*rectangle(preimg, ROIrect, Scalar(0, 0, 255));*/
	//meanshift算法
	TermCriteria criteria(TermCriteria::MAX_ITER, 10, 0.01);
	meanShift(result, ROIrect, criteria);
	/*rectangle(preimg, ROIrect, Scalar(0, 255, 0));*/

	return ROIrect;
}

Package P;


int main()
{
	Mat img1 = imread("F:\\baboon1.jpg");
	Mat img2 = imread("F:\\baboon3.jpg");

	rectangle(img1, Rect(110, 260, 35, 40), Scalar(0, 255, 255));
	namedWindow("img1");
	imshow("img1", img1);

	Rect rect = P.MeanShitfMath(img1, img2, Rect(110, 260, 35, 40));
	rectangle(img2, rect, Scalar(255, 0, 0));

	namedWindow("result");
	imshow("result", img2);

	waitKey(0);

	return 0;
}



各位博友,如果要转载的话,请注明出处!!!

谢谢各位了


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值