• Learning OpenCV Lecture 3 (Counting the Pixels with Histograms)


    In this chapter, we will cover:
    • Computing the image histogram
    • Applying look-up tables to modify image appearance
    • Equalizing the image histogram
    • Backprojecting a histogram to detect specific image content
    • Using the mean shift algorithm to find an object
    • Retrieving similar images using histogram comparison
    Computing the image histogram
    Using the cv::calcHist function.
    Caculate 1D Histogram
    Histogram1D.h
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    
    class Histogram1D {
    private:
    
          int histSize[1]; // number of bins
          float hranges[2]; // min and max pixel value
          const float* ranges[1];
          int channels[1]; // only 1 channel used here
    
    public:
         Histogram1D() {
    
                // Prepare arguments for 1D histogram
                histSize[0] = 256;
                hranges[0] = 0.0;
                hranges[1] = 255.0;
                ranges[0] = hranges;
                channels[0] = 0; // by default, we look at channel 0
    
         }
    
          // Computes the 1D histogram
         cv::MatND getHistogram(const cv::Mat &image);
    
          // Computes the 1D histogram and returns an image of it.
         cv::MatND getHistogramImage(const cv::Mat &image);
    
    };
    
    Histogram.cpp
    #include "Histgram1D.h"
    
    // Computes the 1D histogram
    cv::MatND Histogram1D::getHistogram(const cv::Mat &image) {
         cv::MatND hist;
    
          // Compute histogram
         cv::calcHist(&image,
                1,               // histogram from 1 image only
                channels,  // the channel used
                cv::Mat(), // no mask is used
                hist,      // the resulting histogram
                1,               // it is a 1D histgram
                histSize,  // number of bins
                ranges           // pixel value range
         );
    
          return hist;
    }
    
    cv::Mat Histogram1D::getHistogramImage(const cv::Mat &image) {
         
          // Compute histogram first
         cv::MatND hist = getHistogram(image);
    
          // Get min and max bin values
          double maxVal = 0;
          double minVal = 0;
         cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);
    
          // Image on which to display histogram
         cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255));
    
          // Set highest point at 90% of nbins
          int hpt = static_cast <int >(0.9 * histSize[0]);
    
          // Draw a vertical line for each bin
          for ( int h = 0; h < histSize[0]; h++ ) {
                float binVal = hist.at<float>(h);
                int intensity = static_cast <int >(binVal * hpt / maxVal);
    
                // This function draws a line between 2 points
                cv::line(histImg, cv::Point(h, histSize[0]),
                                          cv::Point(h, histSize[0] - intensity),
                                          cv::Scalar::all(0));
         }
    
          return histImg;
    }
    

      main.cpp

      

    #include <iostream>
    
    #include "Histgram1D.h"
    
    int main() {
    
          // Read input image
         cv::Mat image = cv::imread( "group.jpg", 0); // open in b&w
    
          // The histogram object
         Histogram1D h;
    
          // Compute the histogram
         cv::MatND histo = h.getHistogram(image);
    
          // Loop over each bin
          for (int i = 0; i < 256; i++) {
                std::cout << "Value " << i << " = " <<
                     histo.at<float >(i) << std::endl;
         }
    
          // Draw histogram image
         cv::Mat histoImage = h.getHistogramImage(image);
         cv::namedWindow( "histogram", CV_WINDOW_AUTOSIZE);
         cv::imshow( "histogram", histoImage);
    
          // threshold the image
         cv::Mat thresholded;
         cv::threshold(image, thresholded, 60, 255, cv::THRESH_BINARY);
         cv::namedWindow( "Binary image", CV_WINDOW_AUTOSIZE);
         cv::imshow( "Binary image", thresholded);
    
         cv::waitKey(0);
    
          return 0;
    }
    

      the result as follows:

    Caculate Color image histogram
    ColoHistogram.h
    #include <iostream>
    
    #include "Histgram1D.h"
    
    int main() {
    
          // Read input image
         cv::Mat image = cv::imread( "group.jpg", 0); // open in b&w
    
          // The histogram object
         Histogram1D h;
    
          // Compute the histogram
         cv::MatND histo = h.getHistogram(image);
    
          // Loop over each bin
          for (int i = 0; i < 256; i++) {
                std::cout << "Value " << i << " = " <<
                     histo.at<float >(i) << std::endl;
         }
    
          // Draw histogram image
         cv::Mat histoImage = h.getHistogramImage(image);
         cv::namedWindow( "histogram", CV_WINDOW_AUTOSIZE);
         cv::imshow( "histogram", histoImage);
    
          // threshold the image
         cv::Mat thresholded;
         cv::threshold(image, thresholded, 60, 255, cv::THRESH_BINARY);
         cv::namedWindow( "Binary image", CV_WINDOW_AUTOSIZE);
         cv::imshow( "Binary image", thresholded);
    
         cv::waitKey(0);
    
          return 0;
    }
    

      ColorHistogram.cpp

    #include "ColorHistogram.h"
    
    // Computes the 1D histogram
    cv::MatND ColorHistogram::getHistogram(const cv::Mat &image) {
         cv::MatND hist;
    
          // Compute histogram
         cv::calcHist(&image,
                1,               // histogram from 1 image only
                channels,  // the channel used
                cv::Mat(), // no mask is used
                hist,      // the resulting histogram
                3,               // it is a 3D histgram
                histSize,  // number of bins
                ranges           // pixel value range
                );
    
          return hist;
    }
    
    cv::SparseMat ColorHistogram::getSpareHistogram(const cv::Mat &image) {
    
          // Compute histogram first
         cv::SparseMat hist(3, histSize, CV_32F);
    
          // Compute histogram
         cv::calcHist(&image,
                1,               // histogram from 1 image only
                channels,  // the channel used
                cv::Mat(), // no mask is used
                hist,      // the resulting histogram
                3,               // it is a 3D histgram
                histSize,  // number of bins
                ranges           // pixel value range
                );
    
          return hist;
    }
    

      

    Applying look-up tables to modify image appearance
    A look-up table is a simple one-to-one (or many-to-one) function that defines how pixel values are transformed into new values. It is a 1D array with, in the case of regular gray-level images, 256 entries. Entry i of the table gives the new intensity value of the corresponding gray level, that is:
    newIntensity= lookup[oldIntensity];
    Function cv::LUT in OpenCV applies a look-up table to an image in order to produce a new image. We can add this function to our Histogram1D class:
    cv::Mat Histogram1D::applyLookUp(const cv::Mat& image,  // input image
          const cv::Mat& lookup) { // 1*256 uchar matrix
    
          // the output image
         cv::Mat result;
    
          // apply the lookup table
         cv::LUT(image, lookup, result);
    
          return result;
    }
    cv::Mat Histogram1D::strech(const cv::Mat &image, int minValue /* = 0 */) {
    
          // Compute histogram first
         cv::MatND hist = getHistogram(image);
          // find left extremity of the histogram
          int imin = 0;
          for ( ; imin < histSize[0]; imin ++) {
                std::cout << hist.at<float>(imin) << std::endl;
                if (hist.at<float >(imin) > minValue) {
                     break;
                }
    
         }
    
          // find right extremity of the histogram
          int imax = histSize[0] - 1;
          for ( ; imax >= 0; imax --) {
                if (hist.at<float >(imax) > minValue)
                     break;
         }
    
          // Create lookup table
          int dim(256);
         cv::Mat lookup(1,     // 1 dimension
                &dim,            // 256 entries
                CV_8U            // uchar
                );
    
          // Build lookup table
          for (int i = 0; i < 256; i++) {
    
                // stretch between imin and imax
                if (i < imin) lookup.at<uchar>(i) = 0;
                else if (i > imax) lookup.at<uchar>(i) = 255;
                //linear mapping
                else lookup.at<uchar>(i) = static_cast <uchar>(255.0 * (i - imin) / (imax - imin) + 0.5);
         }
    
          // Apply lookup table
         cv::Mat result;
         result = applyLookUp(image, lookup);
          return result;
    }
    

      Using the function as follows:

        
         cv::Mat streched = h.strech(image, 100);
         cv::namedWindow( "streched image", CV_WINDOW_AUTOSIZE);
         cv::imshow( "streched image", streched);
         cv::Mat strechedHistoImage = h.getHistogramImage(streched);
         cv::namedWindow( "strechedHistoImage", CV_WINDOW_AUTOSIZE);
         cv::imshow( "strechedHistoImage", strechedHistoImage);
    

      results as follows:

    Equalizing the image histogram
    OpenCV offers an easy-to-use function that performs histogram equalization. It can be called as follows:
    cv::Mat Histogram1D::equalize(const cv::Mat &image) {
         cv::Mat result;
         cv::equalizeHist(image, result);
          return result;
    }
    

      result as follows:

    Backprojecting a histogram to detect specific image content
    ContentFinder.h
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    
    class ContentFinder {
    private:
    
          float hranges[2];
          const float* ranges[3];
          int channels[3];
    
          float threshold;
         cv::MatND histogram;
    
    public:
         ContentFinder() : threshold(-1.0f) {
                ranges[0] = hranges; // all channels have 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) {
                histogram = h;
                cv::normalize(histogram, histogram, 1.0);
         }
    
         cv::Mat find(const cv::Mat &image, float minValue, float maxValue, int *channels, int dim);
    };
    

      ContentFinder.cpp

    #include "ContentFinder.h"
    
    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,   // input image
                channels,                        // list of channels used
                histogram,                       // the histogram we are using
                result,                               // the resulting backprojection
                ranges,                               // the range of values
                255.0                            // the scaling factor
                );
    
          // Threshold back projection to obtain a binary image
          if (threshold > 0.0)
                cv::threshold(result, result, 255 * threshold, 255, cv::THRESH_BINARY);
          return result;
    }
    

      

    Let's now use a BGR histogram on the color version of the image we used above. This time,  we will try to detect the blue sky area. We will first load the color image, reduce the number of color using the color reduction function of Chapter 2, and define the region of interest: ColorHistogram hc;

         ColorHistogram hc;
          // load color image
         cv::Mat color = cv::imread( "waves.jpg");
          //reduce colors
         color = hc.colorReduce(color, 32);
          // blue sky area
         cv::Mat imageROI = color(cv::Rect(0, 0, 165, 75));

    Next, you compute the histogram and use the findmethod to detect the sky portion
    of the image:

         cv::MatND 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( "original image", CV_WINDOW_AUTOSIZE);
         cv::imshow( "original image", color);
         cv::namedWindow( "color back projection result", CV_WINDOW_AUTOSIZE);
         cv::imshow( "color back projection result", result);

    The result of the detection on the color version of the image, of the previous section is seen
    here:
     
    Using the mean shift algorithm to find an object
    colorhistogram.h
    #if !defined COLHISTOGRAM
    #define COLHISTOGRAM
    
    #include <opencv2corecore.hpp>
    #include <opencv2imgprocimgproc.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;
    }
    
          // Computes the 1D Hue histogram with a mask.
          // BGR source image is converted to HSV
          // Pixels with low saturation are ignored
         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);
                     }
                     // 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
                          mask, // binary mask
                          hist, // the resulting histogram
                          1, // it is a 1D histogram
                          histSize, // number of bins
                          ranges // pixel value range
                          );
                     return hist;
         }
    
    };
    
    
    #endif
    

      bojectFinder.h

    #if !defined OFINDER
    #define OFINDER
    
    #include <opencv2corecore.hpp>
    #include <opencv2imgprocimgproc.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

    #include <iostream>
    #include <vector>
    using namespace std;
    
    #include <opencv2corecore.hpp>
    #include <opencv2highguihighgui.hpp>
    #include <opencv2imgprocimgproc.hpp>
    #include <opencv2video	racking.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;
    }
    

       results:

    Retrieving similar images using histogram comparison
    imageComparator.h
    #if !defined ICOMPARATOR
    #define ICOMPARATOR
    
    #include <opencv2corecore.hpp>
    #include <opencv2imgprocimgproc.hpp>
    #include "colorhistogram.h"
    
    class ImageComparator {
    
      private:
    
         cv::Mat reference;
         cv::Mat input;
         cv::MatND refH;
         cv::MatND inputH;
    
         ColorHistogram hist;
          int div;
    
      public:
    
         ImageComparator() : div(32) {
    
         }
    
          // Color reduction factor
          // The comparaison will be made on images with
          // color space reduced by this factor in each dimension
          void setColorReduction( int factor) {
    
                div= factor;
         }
    
          int getColorReduction() {
    
                return div;
         }
    
          void setReferenceImage(const cv::Mat& image) {
    
                reference= hist.colorReduce(image,div);
                refH= hist.getHistogram(reference);
         }
    
          double compare(const cv::Mat& image) {
    
                input= hist.colorReduce(image,div);
                inputH= hist.getHistogram(input);
    
                return cv::compareHist(refH,inputH,CV_COMP_INTERSECT);
         }
    };
    
    #endif
    

      retrieve.cpp

    #include <iostream>
    using namespace std;
    
    #include <opencv2corecore.hpp>
    #include <opencv2highguihighgui.hpp>
    
    #include "imageComparator.h"
    
    int main()
    {
          // Read reference image
         cv::Mat image= cv::imread("../waves.jpg" );
          if (!image.data)
                return 0;
    
          // Display image
         cv::namedWindow( "Query Image");
         cv::imshow( "Query Image",image);
    
         ImageComparator c;
         c.setReferenceImage(image);
    
          // Read an image and compare it with reference
         cv::Mat input= cv::imread("../dog.jpg" );
         cout << "waves vs dog: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../marais.jpg");
         cout << "waves vs marais: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../bear.jpg");
         cout << "waves vs bear: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../beach.jpg");
         cout << "waves vs beach: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../polar.jpg");
         cout << "waves vs polar: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../moose.jpg");
         cout << "waves vs moose: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../lake.jpg");
         cout << "waves vs lake: " << c.compare(input) << endl;
    
          // Read an image and compare it with reference
         input= cv::imread("../fundy.jpg");
         cout << "waves vs fundy: " << c.compare(input) << endl;
    
         cv::waitKey();
          return 0;
    } 
    

      results:

  • 相关阅读:
    du
    date
    echo
    redis的多实例
    redis相关配置
    mariadb的安装与主从复制
    11.Flask-钩子函数
    Python之Linux下的virtualenv&&virtualenvwrapper
    Linux的防火墙概念
    安装ipython解释器
  • 原文地址:https://www.cnblogs.com/starlitnext/p/3861364.html
Copyright © 2020-2023  润新知