您的位置:首页 > 运维架构

OpenCV2用均值漂移(Mean Shift)查找物体

2015-12-10 10:30 267 查看
参考《opecv2计算机视觉》

//在image1中找一块作为样本,在image2中找出和image1中样本相近的区域

colorhistogram.h

#if !defined COLHISTOGRAM
#define COLHISTOGRAM

#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

class ColorHistogram {

private:

int histSize[3];
float hranges[2];
const float* ranges[3];
int channels[3];

public:

ColorHistogram() {

// Prepare arguments for a color histogram
histSize[0]= histSize[1]= histSize[2]= 256;
hranges[0]= 0.0;    // BRG range
hranges[1]= 255.0;
ranges[0]= hranges; // all channels have the same range
ranges[1]= hranges;
ranges[2]= hranges;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;
}

// Computes the histogram.
cv::MatND getHistogram(const cv::Mat &image) {

cv::MatND hist;

// BGR color histogram
hranges[0]= 0.0;    // BRG range
hranges[1]= 255.0;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;

// Compute histogram
cv::calcHist(&image,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
3,			// it is a 3D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

// Computes the histogram.
cv::SparseMat getSparseHistogram(const cv::Mat &image) {

cv::SparseMat hist(3,histSize,CV_32F);

// BGR color histogram
hranges[0]= 0.0;    // BRG range
hranges[1]= 255.0;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;

// Compute histogram
cv::calcHist(&image,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
3,			// it is a 3D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

// Computes the 2D ab histogram.
// BGR source image is converted to Lab
cv::MatND getabHistogram(const cv::Mat &image) {

cv::MatND hist;

// Convert to Lab color space
cv::Mat lab;
cv::cvtColor(image, lab, CV_BGR2Lab);

// Prepare arguments for a 2D color histogram
hranges[0]= -128.0;
hranges[1]= 127.0;
channels[0]= 1; // the two channels used are ab
channels[1]= 2;

// Compute histogram
cv::calcHist(&lab,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
2,			// it is a 2D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

// Computes the 1D Hue histogram with a mask.
// BGR source image is converted to HSV
cv::MatND getHueHistogram(const cv::Mat &image) {

cv::MatND hist;

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

// 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
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
1,			// it is a 1D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

cv::Mat colorReduce(const cv::Mat &image, int div=64) {

int n= static_cast<int>(log(static_cast<double>(div))/log(2.0));
// mask used to round the pixel value
uchar mask= 0xFF<<n; // e.g. for div=16, mask= 0xF0

cv::Mat_<cv::Vec3b>::const_iterator it= image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>();

// Set output image (always 1-channel)
cv::Mat result(image.rows,image.cols,image.type());
cv::Mat_<cv::Vec3b>::iterator itr= result.begin<cv::Vec3b>();

for ( ; it!= itend; ++it, ++itr) {

(*itr)[0]= ((*it)[0]&mask) + div/2;
(*itr)[1]= ((*it)[1]&mask) + div/2;
(*itr)[2]= ((*it)[2]&mask) + div/2;
}

return result;
}

};

#endif


error C2660: “ColorHistogram::getHueHistogram”: 函数不接受 2 个参数.

修改后的

#if !defined COLHISTOGRAM
#define COLHISTOGRAM

#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

class ColorHistogram {

private:

int histSize[3];
float hranges[2];
const float* ranges[3];
int channels[3];

public:

ColorHistogram() {

// Prepare arguments for a color histogram
histSize[0]= histSize[1]= histSize[2]= 256;
hranges[0]= 0.0;    // BRG range
hranges[1]= 255.0;
ranges[0]= hranges; // all channels have the same range
ranges[1]= hranges;
ranges[2]= hranges;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;
}

// Computes the histogram.
cv::MatND getHistogram(const cv::Mat &image) {

cv::MatND hist;

// BGR color histogram
hranges[0]= 0.0;    // BRG range
hranges[1]= 255.0;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;

// Compute histogram
cv::calcHist(&image,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
3,			// it is a 3D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

// Computes the histogram.
cv::SparseMat getSparseHistogram(const cv::Mat &image) {

cv::SparseMat hist(3,histSize,CV_32F);

// BGR color histogram
hranges[0]= 0.0;    // BRG range
hranges[1]= 255.0;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;

// Compute histogram
cv::calcHist(&image,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
3,			// it is a 3D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

// Computes the 2D ab histogram.
// BGR source image is converted to Lab
cv::MatND getabHistogram(const cv::Mat &image) {

cv::MatND hist;

// Convert to Lab color space
cv::Mat lab;
cv::cvtColor(image, lab, CV_BGR2Lab);

// Prepare arguments for a 2D color histogram
hranges[0]= -128.0;
hranges[1]= 127.0;
channels[0]= 1; // the two channels used are ab
channels[1]= 2;

// Compute histogram
cv::calcHist(&lab,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
2,			// it is a 2D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

// Computes the 1D Hue histogram with a mask.
// BGR source image is converted to HSV
// Pixels with low saturation are ignored
<span style="background-color: rgb(255, 255, 0);">cv::MatND getHueHistogram(const cv::Mat &image,
int minSaturation=0) {

cv::MatND hist;
// Convert to HSV color space
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);
// Mask to be used (or not)
cv::Mat mask;
if (minSaturation>0) {
// Spliting the 3 channels into 3 images
std::vector<cv::Mat> v;
cv::split(hsv,v);
// Mask out the low saturated pixels
cv::threshold(v[1],mask,minSaturation,255,
cv::THRESH_BINARY);
}</span>

// 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(&hsv,
1,			// histogram of 1 image only
channels,	// the channel used
cv::Mat(),	// no mask is used
hist,		// the resulting histogram
1,			// it is a 1D histogram
histSize,	// number of bins
ranges		// pixel value range
);

return hist;
}

cv::Mat colorReduce(const cv::Mat &image, int div=64) {

int n= static_cast<int>(log(static_cast<double>(div))/log(2.0));
// mask used to round the pixel value
uchar mask= 0xFF<<n; // e.g. for div=16, mask= 0xF0

cv::Mat_<cv::Vec3b>::const_iterator it= image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>();

// Set output image (always 1-channel)
cv::Mat result(image.rows,image.cols,image.type());
cv::Mat_<cv::Vec3b>::iterator itr= result.begin<cv::Vec3b>();

for ( ; it!= itend; ++it, ++itr) {

(*itr)[0]= ((*it)[0]&mask) + div/2;
(*itr)[1]= ((*it)[1]&mask) + div/2;
(*itr)[2]= ((*it)[2]&mask) + div/2;
}

return result;
}

};

#endif


objectfinder.h

#if !defined OFINDER
#define OFINDER

#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

class ObjectFinder {

private:

float hranges[2];
const float* ranges[3];
int channels[3];

float threshold;
cv::MatND histogram;
cv::SparseMat shistogram;
bool isSparse;

public:

ObjectFinder() : threshold(0.1f), isSparse(false) {

ranges[0]= hranges; // all channels have the same range
ranges[1]= hranges;
ranges[2]= hranges;
}

// Sets the threshold on histogram values [0,1]
void setThreshold(float t) {

threshold= t;
}

// Gets the threshold
float getThreshold() {

return threshold;
}

// Sets the reference histogram
void setHistogram(const cv::MatND& h) {

isSparse= false;
histogram= h;
cv::normalize(histogram,histogram,1.0);
}

// Sets the reference histogram
void setHistogram(const cv::SparseMat& h) {

isSparse= true;
shistogram= h;
cv::normalize(shistogram,shistogram,1.0,cv::NORM_L2);
}

// Finds the pixels belonging to the histogram
cv::Mat find(const cv::Mat& image) {

cv::Mat result;

hranges[0]= 0.0;	// range [0,255]
hranges[1]= 255.0;
channels[0]= 0;		// the three channels
channels[1]= 1;
channels[2]= 2;

if (isSparse) { // call the right function based on histogram type

cv::calcBackProject(&image,
1,            // one image
channels,     // vector specifying what histogram dimensions belong to what image channels
shistogram,   // the histogram we are using
result,       // the resulting back projection image
ranges,       // the range of values, for each dimension
255.0         // the scaling factor is chosen such that a histogram value of 1 maps to 255
);

} else {

cv::calcBackProject(&image,
1,            // one image
channels,     // vector specifying what histogram dimensions belong to what image channels
histogram,    // the histogram we are using
result,       // the resulting back projection image
ranges,       // the range of values, for each dimension
255.0         // the scaling factor is chosen such that a histogram value of 1 maps to 255
);
}

// Threshold back projection to obtain a binary image
if (threshold>0.0)
cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY);

return result;
}

cv::Mat 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];

if (isSparse) { // call the right function based on histogram type

cv::calcBackProject(&image,
1,            // we only use one image at a time
channels,     // vector specifying what histogram dimensions belong to what image channels
shistogram,   // the histogram we are using
result,       // the resulting back projection image
ranges,       // the range of values, for each dimension
255.0         // the scaling factor is chosen such that a histogram value of 1 maps to 255
);

} else {

cv::calcBackProject(&image,
1,            // we only use one image at a time
channels,     // vector specifying what histogram dimensions belong to what image channels
histogram,    // the histogram we are using
result,       // the resulting back projection image
ranges,       // the range of values, for each dimension
255.0         // the scaling factor is chosen such that a histogram value of 1 maps to 255
);
}

// Threshold back projection to obtain a binary image
if (threshold>0.0)
cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY);

return result;
}

};

#endif


finder.cpp

/*------------------------------------------------------------------------------------------*\
This file contains material supporting chapter 4 of the cookbook:
Computer Vision Programming using the OpenCV Library.
by Robert Laganiere, Packt Publishing, 2011.

This program is free software; permission is hereby granted to use, copy, modify,
and distribute this source code, or portions thereof, for any purpose, without fee,
subject to the restriction that the copyright notice may not be removed
or altered from any source or altered source distribution.
The software is released on an as-is basis and without any warranties of any kind.
In particular, the software is not guaranteed to be fault-tolerant or free from failure.
The author disclaims all warranties with regard to this software, any use,
and any consequent failure, is purely the responsibility of the user.

Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name
\*------------------------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
using namespace std;

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\video\tracking.hpp>

#include "objectFinder.h"
#include "colorhistogram.h"

int main()
{
// Read reference image
cv::Mat image= cv::imread("baboon1.jpg");
if (!image.data)
return 0;

// Define ROI
cv::Mat imageROI= image(cv::Rect(110,260,35,40));
cv::rectangle(image, cv::Rect(110,260,35,40),cv::Scalar(0,0,255));

// Display image
cv::namedWindow("Image");
cv::imshow("Image",image);

// Get the Hue histogram
int minSat=65;
ColorHistogram hc;
cv::MatND colorhist= hc.getHueHistogram(imageROI,minSat);

ObjectFinder finder;
finder.setHistogram(colorhist);
finder.setThreshold(0.2f);

// Convert to HSV space
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);

// Split the image
vector<cv::Mat> v;
cv::split(hsv,v);

// Eliminate pixels with low saturation
cv::threshold(v[1],v[1],minSat,255,cv::THRESH_BINARY);
cv::namedWindow("Saturation");
cv::imshow("Saturation",v[1]);

// Get back-projection of hue histogram
int ch[1]={0};
cv::Mat result= finder.find(hsv,0.0f,180.0f,ch,1);

cv::namedWindow("Result Hue");
cv::imshow("Result Hue",result);

cv::bitwise_and(result,v[1],result);
cv::namedWindow("Result Hue and");
cv::imshow("Result Hue and",result);

// Second image
image= cv::imread("baboon3.jpg");

// Display image
cv::namedWindow("Image 2");
cv::imshow("Image 2",image);

// Convert to HSV space
cv::cvtColor(image, hsv, CV_BGR2HSV);

// Split the image
cv::split(hsv,v);

// Eliminate pixels with low saturation
cv::threshold(v[1],v[1],minSat,255,cv::THRESH_BINARY);
cv::namedWindow("Saturation");
cv::imshow("Saturation",v[1]);

// Get back-projection of hue histogram
result= finder.find(hsv,0.0f,180.0f,ch,1);

cv::namedWindow("Result Hue");
cv::imshow("Result Hue",result);

// Eliminate low stauration pixels
cv::bitwise_and(result,v[1],result);
cv::namedWindow("Result Hue and");
cv::imshow("Result Hue and",result);

// Get back-projection of hue histogram
finder.setThreshold(-1.0f);
result= finder.find(hsv,0.0f,180.0f,ch,1);
cv::bitwise_and(result,v[1],result);
cv::namedWindow("Result Hue and raw");
cv::imshow("Result Hue and raw",result);

cv::Rect rect(110,260,35,40);
cv::rectangle(image, rect, cv::Scalar(0,0,255));

cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);
cout << "meanshift= " << cv::meanShift(result,rect,criteria) << endl;

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

// Display image
cv::namedWindow("Image 2 result");
cv::imshow("Image 2 result",image);

cv::waitKey();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: