关闭

OpenCV2 cookbook source code analyse - histogram match

1060人阅读 评论(0) 收藏 举报
分类:

1.  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

 

2.  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


 

 

3.  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("C:/images/baboon1.jpg");
	if (!image.data)
		return 0;
 
        // 从image中得到一块ROI区域, 并用红色在image上用红色标出ROI
   	// 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));
        
        // 显示image及其标出的ROI(红色方框)
	// Display image
   	cv::namedWindow("Image");
	cv::imshow("Image",image);
 
        // 得到imageROI的色度直方图
	// Get the Hue histogram
	int minSat=65;
	ColorHistogram hc;
	// cv::MatND colorhist= hc.getHueHistogram(imageROI, minSat);
	cv::MatND colorhist= hc.getHueHistogram(imageROI);

	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);
 
        //v[0] - Hue,  v[1] - Saturation,  v[2] - Value
	// 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("C:/images/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;
}



 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:806474次
    • 积分:12978
    • 等级:
    • 排名:第1025名
    • 原创:414篇
    • 转载:665篇
    • 译文:0篇
    • 评论:44条
    最新评论