OpenCV 均值漂移(Mean Shift)算法查找物体

 Mean shift 算法是基于核密度估计的爬山算法,可用于聚类、图像分割、跟踪等。本文利用OpenCV进行图片种物体识别。

1.确认类函数是否正确:

cv::MatND ColorHistogram::getHueHistogram(const cv::Mat &image, int minSaturation = 0)
{

	cv::MatND hist;

	// Convert to Lab color space
	cv::Mat hue;
	cv::cvtColor(image, hue, CV_BGR2HSV);

	

	cv::Mat mask;
	if (minSaturation >0)
	{
		std::vector<cv::Mat>v;
		cv::split(hue, v);
		cv::threshold(v[1], mask, minSaturation, 255, cv::THRESH_BINARY);
	}

	// Prepare arguments for a 1D hue histogram
	hranges[0] = 0.0;
	hranges[1] = 180.0;
	channels[0] = 0; // the hue channel 
					 // Compute histogram
	cv::calcHist(&hue,
		1,			// histogram of 1 image only
		channels,	// the channel used
		mask,		// no mask is used
		hist,		// the resulting histogram
		1,			// it is a 1D histogram
		histSize,	// number of bins
		ranges		// pixel value range
	);

	return hist;
}



/***************************************************************/
void ContentFinder::setThreshold(float t)
{
	threshold = t;
}

float ContentFinder::getThreshold()
{
	return threshold;
}

void ContentFinder::setHistogram(const cv::MatND &h)
{
	histogram = h;
	cv::normalize(histogram, histogram, 1.0);
}

cv::Mat ContentFinder::find(const cv::Mat& image, float minValue, float maxValue, int *channels, int dim)
{
	cv::Mat result;
	hranges[0] = minValue;
	hranges[1] = maxValue;
	for (int i = 0; i < dim; i++)
	{
		this->channels[i] = channels[i];
	}
	cv::calcBackProject(&image,
		1,
		channels,
		histogram,
		result,
		ranges,
		255.0
	);
	if (threshold > 0.0)
	{
		cv::threshold(result, result, 255 * threshold, 255, cv::THRESH_BINARY);
	}
	return result;
}

2.进行过程处理:

void OpenCVQtGui::MeanShift_clicked()
{
	cv::Mat Result;

	cv::Mat ImageROI;

	cv::Mat colors = cv::imread("Cup.jpg");	//Put Girl.jpg into the same pat

	ImageROI = colors(cv::Rect(120, 80, 100, 120));

	cv::rectangle(colors, cv::Rect(120, 80, 100, 120), cv::Scalar(0, 0, 255));

	/*显示第一张图片*/
	cv::imshow("1.ImageROI1", colors);

	//获取色调通道直方图
	int minSat = 30;

	cv::MatND hist = Chist.getHueHistogram(ImageROI,minSat);


	finder.setHistogram(hist);

	/*处理第二张图片*/
	cv::Mat image2 = image.clone();
	cv::Mat hsv;

	cv::cvtColor(image2, hsv, CV_BGR2HSV);
	
	/*分离图像通道*/
	std::vector<cv::Mat>v;
	cv::split(hsv, v);

	/*消除饱和度较低的像素点*/
	cv::threshold(v[1], v[1], minSat, 255, cv::THRESH_BINARY);

	cv::imshow("2.消除饱和度较低的像素点", v[1]);

	/*进行直方图反投影*/
	finder.setHistogram(hist);

	finder.setThreshold(0.3f);

	int ch[1] = { 0};
	Result = finder.find(hsv, 0.0f, 180.0f, ch, 1);

	cv::imshow("3.进行直方图反投影", Result);

	/*利用位运算消除低饱和度像素*/
	cv::bitwise_and(Result, v[1], Result);
	cv::imshow("4.利用位运算消除低饱和度像素", Result);

	/*得到反投影直方图概率图像*/
	finder.setThreshold(-0.1f);
	Result = finder.find(hsv, 0.0f, 180.0f, ch, 1);
	cv::bitwise_and(Result, v[1], Result);
	cv::imshow("5.利用位运算消除低饱和度像素", Result);


	cv::Rect rect(120, 80, 100, 120);

	cv::rectangle(image2, rect, cv::Scalar(0,0,255));

	cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);

	cv::meanShift(Result, rect, criteria);

	cv::rectangle(image2, rect, cv::Scalar(0, 255, 0));


	Result = image2;

	cvtColor(Result, Result, CV_BGR2RGB);

	QImage img1 = QImage((const unsigned char*)(Result.data), Result.cols, Result.rows, QImage::Format_RGB888);

	ui.label_2->setPixmap(QPixmap::fromImage(img1));

	ui.label_2->resize(QSize(img1.width(), img1.height()));

3.处理效果:

原图

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值