opecv2 MeanShift 使用均值漂移算法查找物体
阅读原文时间:2023年07月08日阅读:1

#if !defined OFINDER
#define OFINDER

#include
#include

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
#include
#include
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::vectorv;
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
#include
#include
#include
#include
#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;

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章