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

opencv2在直方图反投影算法中使用颜色信息

2014-04-22 21:58 369 查看
#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

#if !defined OFINDER
#define OFINDER

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

class ContentFinder {

private:

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

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

public:

ContentFinder() : 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);
}

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

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include"colorhistogram.h"
#include"ContentFinder.h"

using namespace std;
using namespace cv;

int main()
{
// Load color image
ColorHistogram hc;
cv::Mat color= cv::imread("d:/test/opencv/waves.jpg");
color= hc.colorReduce(color,32);
cv::namedWindow("Color Image");
cv::imshow("Color Image",color);

cv::Mat imageROI= color(cv::Rect(0,0,165,75)); // blue sky area

cv::Mat hist=hc.getHistogram(imageROI);
ContentFinder finder;
finder.setHistogram(hist);
finder.setThreshold(0.05f);

// Get back-projection of color histogram
cv::Mat result= finder.find(color);

cv::namedWindow("Color Backproject Result");
cv::imshow("Color Backproject Result",result);

cv::waitKey();
return 0;
}


 

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