#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 #if !defined COLHISTOGRAM #define COLHISTOGRAM #include <opencv2\core\core.hpp> #include <opencv2\imgproc\imgproc.hpp> #include<opencv2/highgui/highgui.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 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::MatND getHueHistogram(const cv::Mat &image,int minSaturation) { cv::MatND hist; cv::Mat hsv; cv::cvtColor(image,hsv,CV_BGR2HSV); cv::Mat mask; if(minSaturation>0) { std::vector<cv::Mat>v; cv::split(hsv,v); cv::threshold(v[1],mask,minSaturation,255,cv::THRESH_BINARY); } hranges[0]=0.0; hranges[1]=180.0; channels[0]=0; calcHist(&hsv,1,channels,mask,hist,1,histSize,ranges); return hist; } }; #endif #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/video/video.hpp> #include<iostream> #include"colorhistogram.h" #include"ContentFinder.h" using namespace std; using namespace cv; int main() { Mat image=imread("d:/test/opencv/baboon1.jpg"); Mat imageROI=image(Rect(110,260,35,40)); int minSat=65; ColorHistogram hc; MatND colorhist=hc.getHueHistogram(imageROI,minSat); namedWindow("image 1"); imshow("image 1",image); ContentFinder finder; finder.setHistogram(colorhist); Mat hsv; image=imread("d:/test/opencv/baboon3.jpg"); namedWindow("image 2"); imshow("image 2",image); cvtColor(image,hsv,CV_BGR2HSV); vector<Mat>v; split(hsv,v); threshold(v[1],v[1],minSat,255,THRESH_BINARY); cv::namedWindow("Saturation"); cv::imshow("Saturation",v[1]); int channel[1]={0}; Mat result=finder.find(hsv,0.0f,180.0f,channel,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); finder.setThreshold(-1.0f);// result= finder.find(hsv,0.0f,180.0f,channel,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; }