【Opencv测试用例(二)】


Chapter03

1、colorDetection.cpp

结果

在这里插入图片描述

测试代码

头文件colordetector.h

#if !defined COLORDETECT
#define COLORDETECT
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
class ColorDetector {
private:
	// minimum acceptable distance
	int maxDist;
	// target color
	cv::Vec3b target;
	// image containing color converted image
	cv::Mat converted;
	bool useLab;
	// image containing resulting binary map
	cv::Mat result;
public:
	// empty constructor
	// default parameter initialization here
	ColorDetector() : maxDist(100), target(0, 0, 0), useLab(false) {}
	// extra constructor for Lab color space example
	ColorDetector(bool useLab) : maxDist(100), target(0, 0, 0), useLab(useLab) {}
	// full constructor
	ColorDetector(uchar blue, uchar green, uchar red, int mxDist = 100, bool useLab = false) : maxDist(mxDist), useLab(useLab) {
		// target color
		setTargetColor(blue, green, red);
	}
	// Computes the distance from target color.
	int getDistanceToTargetColor(const cv::Vec3b& color) const {
		return getColorDistance(color, target);
	}
	// Computes the city-block distance between two colors.
	int getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const {
		return abs(color1[0] - color2[0]) +
			abs(color1[1] - color2[1]) +
			abs(color1[2] - color2[2]);
		// Or:
		// return static_cast<int>(cv::norm<int,3>(cv::Vec3i(color[0]-color2[0],color[1]-color2[1],color[2]-color2[2])));
		// Or:
		// cv::Vec3b dist;
		// cv::absdiff(color,color2,dist);
		// return cv::sum(dist)[0];
	}
	// Processes the image. Returns a 1-channel binary image.
	cv::Mat process(const cv::Mat &image);
	cv::Mat operator()(const cv::Mat &image) {
		cv::Mat input;
		if (useLab) { // Lab conversion
			cv::cvtColor(image, input, cv::COLOR_BGR2Lab);
		}
		else {
			input = image;
		}
		cv::Mat output;
		// compute absolute difference with target color
		cv::absdiff(input, cv::Scalar(target), output);
		// split the channels into 3 images
		std::vector<cv::Mat> images;
		cv::split(output, images);
		// add the 3 channels (saturation might occurs here)
		output = images[0] + images[1] + images[2];
		// apply threshold
		cv::threshold(output,  // input image
			output,  // output image
			maxDist, // threshold (must be < 256)
			255,     // max value
			cv::THRESH_BINARY_INV); // thresholding type

		return output;
	}

	// Getters and setters
	// Sets the color distance threshold.
	// Threshold must be positive, otherwise distance threshold
	// is set to 0.
	void setColorDistanceThreshold(int distance) {
		if (distance < 0)
			distance = 0;
		maxDist = distance;
	}
	// Gets the color distance threshold
	int getColorDistanceThreshold() const {

		return maxDist;
	}

	// Sets the color to be detected
	// given in BGR color space
	void setTargetColor(uchar blue, uchar green, uchar red) {
		// BGR order
		target = cv::Vec3b(blue, green, red);
		if (useLab) {
			// Temporary 1-pixel image
			cv::Mat tmp(1, 1, CV_8UC3);
			tmp.at<cv::Vec3b>(0, 0) = cv::Vec3b(blue, green, red);
			// Converting the target to Lab color space 
			cv::cvtColor(tmp, tmp, cv::COLOR_BGR2Lab);
			target = tmp.at<cv::Vec3b>(0, 0);
		}
	}

	// Sets the color to be detected
	void setTargetColor(cv::Vec3b color) {
		target = color;
	}
	// Gets the color to be detected
	cv::Vec3b getTargetColor() const {
		return target;
	}
};
#endif

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "colordetector.h"
static int test()
{
    // 1. Create image processor object
	ColorDetector cdetect;

    // 2. Read input image
	std::string path_boldt = "F:/images/boldt.jpg";
	cv::Mat image= cv::imread(path_boldt);
	if (image.empty())
		return 0; 
	cv::namedWindow("Original Image");
	cv::imshow("Original Image", image);

    // 3. Set input parameters
	cdetect.setTargetColor(230,190,130); // here blue sky

    // 4. Process the image and display the result
	cv::namedWindow("result");
	cv::Mat result = cdetect.process(image);
	cv::imshow("result",result);

	// or using functor
	// here distance is measured with the Lab color space
	ColorDetector colordetector(230, 190, 130,  // color
		                             45, true); // Lab threshold
	cv::namedWindow("result (functor)");
	result = colordetector(image);
	cv::imshow("result (functor)",result);

	// testing floodfill
	cv::floodFill(image,            // input/ouput image
		cv::Point(100, 50),         // seed point
		cv::Scalar(255, 255, 255),  // repainted color
		(cv::Rect*)0,  // bounding rectangle of the repainted pixel set
		cv::Scalar(35, 35, 35),     // low and high difference threshold
		cv::Scalar(35, 35, 35),     // most of the time will be identical
		cv::FLOODFILL_FIXED_RANGE); // pixels are compared to seed color

	cv::namedWindow("Flood Fill result");
	result = colordetector(image);
	cv::imshow("Flood Fill result", image);

	// Creating artificial images to demonstrate color space properties
	cv::Mat colors(100, 300, CV_8UC3, cv::Scalar(100, 200, 150));
	cv::Mat range= colors.colRange(0, 100);
	range = range + cv::Scalar(10, 10, 10);
	range = colors.colRange(200, 300);
	range = range + cv::Scalar(-10, -10, 10);

	cv::namedWindow("3 colors");
	cv::imshow("3 colors", colors);

	cv::Mat labImage(100, 300, CV_8UC3, cv::Scalar(100, 200, 150));
	cv::cvtColor(labImage, labImage, cv::COLOR_RGB2Lab);
	range = colors.colRange(0, 100);
	range = range + cv::Scalar(10, 10, 10);
	range = colors.colRange(200, 300);
	range = range + cv::Scalar(-10, -10, 10);
	cv::cvtColor(labImage, labImage, cv::COLOR_Lab2BGR);

	cv::namedWindow("3 colors (Lab)");
	cv::imshow("3 colors (Lab)", colors);

	// brightness versus luminance
	cv::Mat grayLevels(100, 256, CV_8UC3);
	for (int i = 0; i < 256; i++) {
		grayLevels.col(i) = cv::Scalar(i, i, i);
	}

	range = grayLevels.rowRange(50, 100);
	cv::Mat channels[3];
	cv::split(range, channels);
	channels[1] = 128;
	channels[2] = 128;
	cv::merge(channels, 3, range);
	cv::cvtColor(range, range, cv::COLOR_Lab2BGR);
	cv::namedWindow("Luminance vs Brightness");
	cv::imshow("Luminance vs Brightness", grayLevels);
	cv::waitKey();
	return 0;
}

int main()
{
	test();
	system("pause");
	return 0;
}

2、extractObject.cpp

结果

在这里插入图片描述

测试代码

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>


static int test()
{
	// Read input image
	std::string path_boldt = "F:/images/boldt.jpg";
	cv::Mat image= cv::imread(path_boldt);
	if (!image.data)
		return 0; 
    // Display the image
	cv::namedWindow("Original Image");
	cv::imshow("Original Image",image);
	// define bounding rectangle 
	cv::Rect rectangle(50,25,210,180);
	// the models (internally used)
	cv::Mat bgModel,fgModel; 
	// segmentation result
	cv::Mat result; // segmentation (4 possible values)
	// GrabCut segmentation
	cv::grabCut(image,    // input image
		result,   // segmentation result
		rectangle,// rectangle containing foreground 
		bgModel, fgModel, // models
		5,        // number of iterations
		cv::GC_INIT_WITH_RECT); // use rectangle
	// Get the pixels marked as likely foreground
	cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
	// or:
    //	result= result&1;
	// create a white image
	cv::Mat foreground(image.size(), CV_8UC3,
	          	       cv::Scalar(255, 255, 255));
	image.copyTo(foreground,result); // bg pixels not copied
	// draw rectangle on original image
	cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1);
	cv::namedWindow("Image with rectangle");
	cv::imshow("Image with rectangle",image);
	// display result
	cv::namedWindow("Foreground object");
	cv::imshow("Foreground object",foreground);
	cv::waitKey();
	return 0;
}

int main()
{
	test();
	system("pause");
	return 0;
}

3、huesaturation.cpp

结果

在这里插入图片描述

测试代码

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <vector>

void detectHScolor(const cv::Mat& image,		// input image 
	double minHue, double maxHue,	// Hue interval 
	double minSat, double maxSat,	// saturation interval
	cv::Mat& mask) {				// output mask

	// convert into HSV space
	cv::Mat hsv;
	cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);

	// split the 3 channels into 3 images
	std::vector<cv::Mat> channels;
	cv::split(hsv, channels);
	// channels[0] is the Hue
	// channels[1] is the Saturation
	// channels[2] is the Value

	// Hue masking
	cv::Mat mask1; // below maxHue
	cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
	cv::Mat mask2; // over minHue
	cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);

	cv::Mat hueMask; // hue mask
	if (minHue < maxHue)
		hueMask = mask1 & mask2;
	else // if interval crosses the zero-degree axis
		hueMask = mask1 | mask2;

	// Saturation masking
	// below maxSat
	cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);
	// over minSat
	cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);

	cv::Mat satMask; // saturation mask
	satMask = mask1 & mask2;

	// combined mask
	mask = hueMask&satMask;
}

static int test()
{
	// read the image
	std::string path_boldt = "F:/images/boldt.jpg";
	cv::Mat image= cv::imread(path_boldt);
	if (!image.data)
		return 0; 

	// show original image
	cv::namedWindow("Original image");
	cv::imshow("Original image",image);

	// convert into HSV space
	cv::Mat hsv;
	cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);

	// split the 3 channels into 3 images
	std::vector<cv::Mat> channels;
	cv::split(hsv,channels);
	// channels[0] is the Hue
	// channels[1] is the Saturation
	// channels[2] is the Value

	// display value
	cv::namedWindow("Value");
	cv::imshow("Value",channels[2]);

	// display saturation
	cv::namedWindow("Saturation");
	cv::imshow("Saturation",channels[1]);

	// display hue
	cv::namedWindow("Hue");
	cv::imshow("Hue",channels[0]);

	// image with fixed value
	cv::Mat newImage;
	cv::Mat tmp(channels[2].clone());
	// Value channel will be 255 for all pixels
	channels[2]= 255;  
	// merge back the channels
	cv::merge(channels,hsv);
	// re-convert to BGR
	cv::cvtColor(hsv,newImage, cv::COLOR_HSV2BGR);

	cv::namedWindow("Fixed Value Image");
	cv::imshow("Fixed Value Image",newImage);

	// image with fixed saturation
	channels[1]= 255;
	channels[2]= tmp;
	cv::merge(channels,hsv);
	cv::cvtColor(hsv,newImage, cv::COLOR_HSV2BGR);

	cv::namedWindow("Fixed saturation");
	cv::imshow("Fixed saturation",newImage);

	// image with fixed value and fixed saturation
	channels[1]= 255;
	channels[2]= 255;
	cv::merge(channels,hsv);
	cv::cvtColor(hsv,newImage, cv::COLOR_HSV2BGR);

	cv::namedWindow("Fixed saturation/value");
	cv::imshow("Fixed saturation/value",newImage);

	// artificial image shown the all possible HS colors
	cv::Mat hs(128, 360, CV_8UC3);  
	for (int h = 0; h < 360; h++) {
		for (int s = 0; s < 128; s++) {
			hs.at<cv::Vec3b>(s, h)[0] = h/2;     // all hue angles
			hs.at<cv::Vec3b>(s, h)[1] = 255-s*2; // from high saturation to low
			hs.at<cv::Vec3b>(s, h)[2] = 255;     // constant value
		}
	}

	cv::cvtColor(hs, newImage, cv::COLOR_HSV2BGR);

	cv::namedWindow("Hue/Saturation");
	cv::imshow("Hue/Saturation", newImage);

	// Testing skin detection

	// read the image
	std::string path_girl = "F:/images/renwu1.jpg";
	image= cv::imread(path_girl);
	if (!image.data)
		return 0; 

	// show original image
	cv::namedWindow("Original image");
	cv::imshow("Original image",image);

	// detect skin tone
	cv::Mat mask;
	detectHScolor(image, 
		160, 10, // hue from 320 degrees to 20 degrees 
		25, 166, // saturation from ~0.1 to 0.65
		mask);

	// show masked image
	cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0));
	image.copyTo(detected, mask);
	cv::imshow("Detection result",detected);

	// A test comparing luminance and brightness

	// create linear intensity image
	cv::Mat linear(100,256,CV_8U);
	for (int i=0; i<256; i++) {

		linear.col(i)= i;
	}

	// create a Lab image
	linear.copyTo(channels[0]);
	cv::Mat constante(100,256,CV_8U,cv::Scalar(128));
	constante.copyTo(channels[1]);
	constante.copyTo(channels[2]);
	cv::merge(channels,image);

	// convert back to BGR
	cv::Mat brightness;
	cv::cvtColor(image,brightness, cv::COLOR_Lab2BGR);
	cv::split(brightness, channels);

	// create combined image
	cv::Mat combined(200,256, CV_8U);
	cv::Mat half1(combined,cv::Rect(0,0,256,100));
	linear.copyTo(half1);
	cv::Mat half2(combined,cv::Rect(0,100,256,100));
	channels[0].copyTo(half2);

	cv::namedWindow("Luminance vs Brightness");
	cv::imshow("Luminance vs Brightness",combined);

	cv::waitKey();
}


int main()
{
	test();
	system("pause");
	return 0;
}

Chapter04

1、contentFinder.cpp

结果

在这里插入图片描述

测试代码

#include <iostream>
using namespace std;
#include<opencv2/opencv.hpp>
#include "histogram.h"
#include "contentFinder.h"
#include "colorhistogram.h"

static int test()
{
	// Read input image
	std::string path_waves = "F:/images/waves.jpg";
	cv::Mat image = cv::imread(path_waves, 0);
	if (!image.data)
		return 0;

	// define image ROI
	cv::Mat imageROI;
	imageROI = image(cv::Rect(216, 33, 24, 30)); // Cloud region

	// Display reference patch
	cv::namedWindow("Reference");
	cv::imshow("Reference", imageROI);

	// Find histogram of reference
	Histogram1D h;
	cv::Mat hist = h.getHistogram(imageROI);
	cv::namedWindow("Reference Hist");
	cv::imshow("Reference Hist", h.getHistogramImage(imageROI));

	// Create the content finder
	ContentFinder finder;

	// set histogram to be back-projected
	finder.setHistogram(hist);
	finder.setThreshold(-1.0f);

	// Get back-projection
	cv::Mat result1;
	result1 = finder.find(image);

	// Create negative image and display result
	cv::Mat tmp;
	result1.convertTo(tmp, CV_8U, -1.0, 255.0);
	cv::namedWindow("Backprojection result");
	cv::imshow("Backprojection result", tmp);

	// Get binary back-projection
	finder.setThreshold(0.12f);
	result1 = finder.find(image);

	// Draw a rectangle around the reference area
	cv::rectangle(image, cv::Rect(216, 33, 24, 30), cv::Scalar(0, 0, 0));

	// Display image
	cv::namedWindow("Image");
	cv::imshow("Image", image);

	// Display result
	cv::namedWindow("Detection Result");
	cv::imshow("Detection Result", result1);

	// Load color image
	ColorHistogram hc;
	cv::Mat color = cv::imread(path_waves);

	// extract region of interest
	imageROI = color(cv::Rect(0, 0, 100, 45)); // blue sky area

	// Get 3D colour histogram (8 bins per channel)
	hc.setSize(8); // 8x8x8
	cv::Mat shist = hc.getHistogram(imageROI);

	// set histogram to be back-projected
	finder.setHistogram(shist);
	finder.setThreshold(0.05f);

	// Get back-projection of color histogram
	result1 = finder.find(color);

	cv::namedWindow("Color Detection Result");
	cv::imshow("Color Detection Result", result1);

	// Second color image
	std::string path_dog = "F:/images/dog.jpg";
	cv::Mat color2 = cv::imread(path_dog);

	cv::namedWindow("Second Image");
	cv::imshow("Second Image", color2);

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

	cv::namedWindow("Result color (2)");
	cv::imshow("Result color (2)", result2);

	// Get ab color histogram
	hc.setSize(256); // 256x256
	cv::Mat colorhist = hc.getabHistogram(imageROI);

	// display 2D histogram
	colorhist.convertTo(tmp, CV_8U, -1.0, 255.0);
	cv::namedWindow("ab histogram");
	cv::imshow("ab histogram", tmp);

	// set histogram to be back-projected
	finder.setHistogram(colorhist);
	finder.setThreshold(0.05f);

	// Convert to Lab space
	cv::Mat lab;
	cv::cvtColor(color, lab, cv::COLOR_BGR2Lab);

	// Get back-projection of ab histogram
	int ch[2] = { 1,2 };
	result1 = finder.find(lab, 0, 256.0f, ch);

	cv::namedWindow("Result ab (1)");
	cv::imshow("Result ab (1)", result1);

	// Second colour image
	cv::cvtColor(color2, lab, cv::COLOR_BGR2Lab);

	// Get back-projection of ab histogram
	result2 = finder.find(lab, 0, 256.0, ch);

	cv::namedWindow("Result ab (2)");
	cv::imshow("Result ab (2)", result2);

	// Draw a rectangle around the reference sky area
	cv::rectangle(color, cv::Rect(0, 0, 100, 45), cv::Scalar(0, 0, 0));
	cv::namedWindow("Color Image");
	cv::imshow("Color Image", color);


	// Get Hue colour histogram
	hc.setSize(180); // 180 bins
	colorhist = hc.getHueHistogram(imageROI);

	// set histogram to be back-projected
	finder.setHistogram(colorhist);

	// Convert to HSV space
	cv::Mat hsv;
	cv::cvtColor(color, hsv, cv::COLOR_BGR2HSV);

	// Get back-projection of hue histogram
	ch[0] = 0;
	result1 = finder.find(hsv, 0.0f, 180.0f, ch);

	cv::namedWindow("Result Hue (1)");
	cv::imshow("Result Hue (1)", result1);

	// Second colour image
	color2 = cv::imread(path_dog);

	// Convert to HSV space
	cv::cvtColor(color2, hsv, cv::COLOR_BGR2HSV);

	// Get back-projection of hue histogram
	result2 = finder.find(hsv, 0.0f, 180.0f, ch);

	cv::namedWindow("Result Hue (2)");
	cv::imshow("Result Hue (2)", result2);

	cv::waitKey();
	return 0;
}

int main()
{
	test();
	system("pause");
	return 0;
}

histogram.h



#if !defined HISTOGRAM
#define HISTOGRAM

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

// To create histograms of gray-level images
class Histogram1D {

  private:

    int histSize[1];         // number of bins in histogram
	float hranges[2];        // range of values
    const float* ranges[1];  // pointer to the different value ranges
    int channels[1];         // channel number to be examined

  public:

	Histogram1D() {

		// Prepare default arguments for 1D histogram
		histSize[0]= 256;   // 256 bins
		hranges[0]= 0.0;    // from 0 (inclusive)
		hranges[1]= 256.0;  // to 256 (exclusive)
		ranges[0]= hranges; 
		channels[0]= 0;     // we look at channel 0
	}

	// Sets the channel on which histogram will be calculated.
	// By default it is channel 0.
	void setChannel(int c) {

		channels[0]= c;
	}

	// Gets the channel used.
	int getChannel() {

		return channels[0];
	}

	// Sets the range for the pixel values.
	// By default it is [0,256[
	void setRange(float minValue, float maxValue) {

		hranges[0]= minValue;
		hranges[1]= maxValue;
	}

	// Gets the min pixel value.
	float getMinValue() {

		return hranges[0];
	}

	// Gets the max pixel value.
	float getMaxValue() {

		return hranges[1];
	}

	// Sets the number of bins in histogram.
	// By default it is 256.
	void setNBins(int nbins) {

		histSize[0]= nbins;
	}

	// Gets the number of bins in histogram.
	int getNBins() {

		return histSize[0];
	}

	// Computes the 1D histogram.
	cv::Mat getHistogram(const cv::Mat &image) {

		cv::Mat hist;

		// Compute 1D histogram with calcHist
		cv::calcHist(&image, 
			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;
	}


    // Computes the 1D histogram and returns an image of it.
	cv::Mat getHistogramImage(const cv::Mat &image, int zoom = 1){

		// Compute histogram first
		cv::Mat hist = getHistogram(image);

		// Creates image
        return Histogram1D::getImageOfHistogram(hist, zoom);
	}

    // Stretches the source image using min number of count in bins.
    cv::Mat stretch(const cv::Mat &image, int minValue = 0) {

        // Compute histogram first
        cv::Mat hist = getHistogram(image);

        // find left extremity of the histogram
        int imin = 0;
        for (; imin < histSize[0]; imin++) {
            // ignore bins with less than minValue entries
            if (hist.at<float>(imin) > minValue)
                break;
        }

        // find right extremity of the histogram
        int imax = histSize[0] - 1;
        for (; imax >= 0; imax--) {

            // ignore bins with less than minValue entries
            if (hist.at<float>(imax) > minValue)
                break;
        }

        // Create lookup table
        int dims[1] = { 256 };
        cv::Mat lookup(1, dims, CV_8U);

        for (int i = 0; i<256; i++) {

            if (i < imin) lookup.at<uchar>(i) = 0;
            else if (i > imax) lookup.at<uchar>(i) = 255;
            else lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin));
        }

        // Apply lookup table
        cv::Mat result;
        result = applyLookUp(image, lookup);

        return result;
    }

    // Stretches the source image using percentile.
    cv::Mat stretch(const cv::Mat &image, float percentile) {

        // number of pixels in percentile
        float number= image.total()*percentile;

        // Compute histogram first
        cv::Mat hist = getHistogram(image);

        // find left extremity of the histogram
        int imin = 0;
        for (float count=0.0; imin < 256; imin++) {
            // number of pixel at imin and below must be > number
            if ((count+=hist.at<float>(imin)) >= number)
                break;
        }

        // find right extremity of the histogram
        int imax = 255;
        for (float count=0.0; imax >= 0; imax--) {
            // number of pixel at imax and below must be > number
            if ((count += hist.at<float>(imax)) >= number)
                break;
        }

        // Create lookup table
        int dims[1] = { 256 };
        cv::Mat lookup(1, dims, CV_8U);

        for (int i = 0; i<256; i++) {

            if (i < imin) lookup.at<uchar>(i) = 0;
            else if (i > imax) lookup.at<uchar>(i) = 255;
            else lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin));
        }

        // Apply lookup table
        cv::Mat result;
        result = applyLookUp(image, lookup);

        return result;
    }

    // static methods

    // Create an image representing a histogram
    static cv::Mat getImageOfHistogram(const cv::Mat &hist, int zoom) {

        // Get min and max bin values
        double maxVal = 0;
        double minVal = 0;
        cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);

        // get histogram size
        int histSize = hist.rows;

        // Square image on which to display histogram
        cv::Mat histImg(histSize*zoom, histSize*zoom, CV_8U, cv::Scalar(255));

        // set highest point at 90% of nbins (i.e. image height)
        int hpt = static_cast<int>(0.9*histSize);

        // Draw vertical line for each bin
        for (int h = 0; h < histSize; h++) {

            float binVal = hist.at<float>(h);
            if (binVal>0) {
                int intensity = static_cast<int>(binVal*hpt / maxVal);
                cv::line(histImg, cv::Point(h*zoom, histSize*zoom),
                    cv::Point(h*zoom, (histSize - intensity)*zoom), cv::Scalar(0), zoom);
            }
        }

        return histImg;
    }

    // Equalizes the source image.
    static cv::Mat equalize(const cv::Mat &image) {

		cv::Mat result;
		cv::equalizeHist(image,result);

		return result;
	}


	// Applies a lookup table transforming an input image into a 1-channel image
    static cv::Mat applyLookUp(const cv::Mat& image, // input image
      const cv::Mat& lookup) { // 1x256 uchar matrix

      // the output image
      cv::Mat result;

      // apply lookup table
      cv::LUT(image,lookup,result);

      return result;
    }

	// Applies a lookup table transforming an input image into a 1-channel image
	// this is a test version with iterator; always use function cv::LUT
    static cv::Mat applyLookUpWithIterator(const cv::Mat& image, const cv::Mat& lookup) {

		// Set output image (always 1-channel)
		cv::Mat result(image.rows,image.cols,CV_8U);
		cv::Mat_<uchar>::iterator itr= result.begin<uchar>();

		// Iterates over the input image
		cv::Mat_<uchar>::const_iterator it= image.begin<uchar>();
		cv::Mat_<uchar>::const_iterator itend= image.end<uchar>();

		// Applies lookup to each pixel
		for ( ; it!= itend; ++it, ++itr) {

			*itr= lookup.at<uchar>(*it);
		}

		return result;
	}
};

#endif

contentFinder.h


#if !defined OFINDER
#define OFINDER
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

class ContentFinder {

private:

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

	float threshold;           // decision threshold
	cv::Mat histogram;         // histogram can be sparse 
	cv::SparseMat shistogram;  // or not
	bool isSparse;

public:

	ContentFinder() : threshold(0.1f), isSparse(false) {

		// in this class,
		// all channels have the same range
		ranges[0] = hranges;
		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::Mat& h) {

		isSparse = false;
		cv::normalize(h, histogram, 1.0);
	}

	// Sets the reference histogram
	void setHistogram(const cv::SparseMat& h) {

		isSparse = true;
		cv::normalize(h, shistogram, 1.0, cv::NORM_L2);
	}

	// Simplified version in which
	// all channels used, with range [0,256[
	cv::Mat find(const cv::Mat& image) {

		cv::Mat result;

		hranges[0] = 0.0;	// default range [0,256[
		hranges[1] = 256.0;
		channels[0] = 0;		// the three channels 
		channels[1] = 1;
		channels[2] = 2;

		return find(image, hranges[0], hranges[1], channels);
	}

	// Finds the pixels belonging to the histogram
	cv::Mat find(const cv::Mat& image, float minValue, float maxValue, int *channels) {

		cv::Mat result;

		hranges[0] = minValue;
		hranges[1] = maxValue;

		if (isSparse) { // call the right function based on histogram type

			for (int i = 0; i < shistogram.dims(); i++)
				this->channels[i] = channels[i];

			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 {

			for (int i = 0; i < histogram.dims; i++)
				this->channels[i] = channels[i];

			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.0*threshold, 255.0, cv::THRESH_BINARY);

		return result;
	}

};
#endif

colorhistogram.h


#if !defined COLHISTOGRAM
#define COLHISTOGRAM

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

class ColorHistogram {
private:
	int histSize[3];        // size of each dimension
	float hranges[2];       // range of values (same for the 3 dimensions)
	const float* ranges[3]; // array of ranges for each dimension
	int channels[3];        // channel to be considered
public:
	ColorHistogram() {
		// Prepare default arguments for a color histogram
		// each dimension has equal size and range
		histSize[0] = histSize[1] = histSize[2] = 256;
		hranges[0] = 0.0;    // BRG range from 0 to 256
		hranges[1] = 256.0;
		ranges[0] = hranges; // in this class,  
		ranges[1] = hranges; // all channels have the same range
		ranges[2] = hranges;
		channels[0] = 0;		// the three channels: B
		channels[1] = 1;     // G
		channels[2] = 2;     // R
	}
	// set histogram size for each dimension
	void setSize(int size) {
		// each dimension has equal size 
		histSize[0] = histSize[1] = histSize[2] = size;
	}
	// Computes the histogram.
	cv::Mat getHistogram(const cv::Mat &image) {
		cv::Mat hist;
		// BGR color histogram
		hranges[0] = 0.0;    // BRG range
		hranges[1] = 256.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,        // number of dimensions
			histSize, // size of each dimension
			CV_32F);
		// BGR color histogram
		hranges[0] = 0.0;    // BRG range
		hranges[1] = 256.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.
	// BGR source image is converted to HSV
	// Pixels with low saturation are ignored
	cv::Mat getHueHistogram(const cv::Mat &image,
		int minSaturation = 0) {
		cv::Mat hist;
		// Convert to HSV colour space
		cv::Mat hsv;
		cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);
		// Mask to be used (or not)
		cv::Mat mask;
		// creating the mask if required
		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;    // range is from 0 to 180
		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;
	}
	// Computes the 2D ab histogram.
	// BGR source image is converted to Lab
	cv::Mat getabHistogram(const cv::Mat &image) {
		cv::Mat hist;
		// Convert to Lab color space
		cv::Mat lab;
		cv::cvtColor(image, lab, cv::COLOR_BGR2Lab);
		// Prepare arguments for a 2D color histogram
		hranges[0] = 0;
		hranges[1] = 256.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;
	}
};

#endif

2、finder.cpp

结果

在这里插入图片描述

测试代码


#include <iostream>
#include <vector>
using namespace std;

#include<opencv2/opencv.hpp>
#include "contentFinder.h"
#include "colorhistogram.h"

static int test()
{
	// Read reference image
	std::string path_baboon01 = "F:/images/baboon01.jpg";
	cv::Mat image = cv::imread(path_baboon01);
	if (!image.data)
		return 0;
	// initial window position
	cv::Rect rect(110, 45, 35, 45);
	cv::rectangle(image, rect, cv::Scalar(0, 0, 255));
	// Baboon's face ROI
	cv::Mat imageROI = image(rect);
	cv::namedWindow("Image 1");
	cv::imshow("Image 1", image);
	// Get the Hue histogram of the Baboon's face
	int minSat = 65;
	ColorHistogram hc;
	cv::Mat colorhist = hc.getHueHistogram(imageROI, minSat);
	ContentFinder finder;
	finder.setHistogram(colorhist);
	finder.setThreshold(0.2f);
	// Convert to HSV space (just for display)
	cv::Mat hsv;
	cv::cvtColor(image, hsv, cv::COLOR_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 mask");
	cv::imshow("Saturation mask", v[1]);
	//--------------
	// Second image
	std::string path_baboon02 = "F:/images/baboon02.jpg";
	image = cv::imread(path_baboon02);
	cv::namedWindow("Image 2");
	cv::imshow("Image 2", image);
	// Convert to HSV space
	cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);
	// Get back-projection of hue histogram
	int ch[1] = { 0 };
	finder.setThreshold(-1.0f); // no thresholding
	cv::Mat result = finder.find(hsv, 0.0f, 180.0f, ch);
	// Display back projection result
	cv::namedWindow("Backprojection on second image");
	cv::imshow("Backprojection on second image", result);
	// initial window position
	cv::rectangle(image, rect, cv::Scalar(0, 0, 255));
	// search objet with mean shift
	cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS,
		10,     // iterate max 10 times
		1);     // or until the change in centroid position is less than 1px
	cout << "meanshift= " << cv::meanShift(result, rect, criteria) << endl;
	// draw output window
	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;
}

int main()
{
	test();
	system("pause");
	return 0;
}

#include "contentFinder.h"头文件


#if !defined OFINDER
#define OFINDER
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

class ContentFinder {
private:
	// histogram parameters
	float hranges[2];
	const float* ranges[3];
	int channels[3];
	float threshold;           // decision threshold
	cv::Mat histogram;         // histogram can be sparse 
	cv::SparseMat shistogram;  // or not
	bool isSparse;
public:
	ContentFinder() : threshold(0.1f), isSparse(false) {
		// in this class,
		// all channels have the same range
		ranges[0] = hranges;
		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::Mat& h) {
		isSparse = false;
		cv::normalize(h, histogram, 1.0);
	}
	// Sets the reference histogram
	void setHistogram(const cv::SparseMat& h) {
		isSparse = true;
		cv::normalize(h, shistogram, 1.0, cv::NORM_L2);
	}
	// Simplified version in which
	// all channels used, with range [0,256[
	cv::Mat find(const cv::Mat& image) {
		cv::Mat result;
		hranges[0] = 0.0;	// default range [0,256[
		hranges[1] = 256.0;
		channels[0] = 0;		// the three channels 
		channels[1] = 1;
		channels[2] = 2;

		return find(image, hranges[0], hranges[1], channels);
	}

	// Finds the pixels belonging to the histogram
	cv::Mat find(const cv::Mat& image, float minValue, float maxValue, int *channels) {
		cv::Mat result;
		hranges[0] = minValue;
		hranges[1] = maxValue;
		if (isSparse) { // call the right function based on histogram type
			for (int i = 0; i < shistogram.dims(); i++)
				this->channels[i] = channels[i];
			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 {

			for (int i = 0; i < histogram.dims; i++)
				this->channels[i] = channels[i];
			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.0*threshold, 255.0, cv::THRESH_BINARY);
		return result;
	}
};

#endif

#include "colorhistogram.h"头文件


#if !defined COLHISTOGRAM
#define COLHISTOGRAM

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

class ColorHistogram {
private:
	int histSize[3];        // size of each dimension
	float hranges[2];       // range of values (same for the 3 dimensions)
	const float* ranges[3]; // array of ranges for each dimension
	int channels[3];        // channel to be considered
public:
	ColorHistogram() {
		// Prepare default arguments for a color histogram
		// each dimension has equal size and range
		histSize[0] = histSize[1] = histSize[2] = 256;
		hranges[0] = 0.0;    // BRG range from 0 to 256
		hranges[1] = 256.0;
		ranges[0] = hranges; // in this class,  
		ranges[1] = hranges; // all channels have the same range
		ranges[2] = hranges;
		channels[0] = 0;		// the three channels: B
		channels[1] = 1;     // G
		channels[2] = 2;     // R
	}
	// set histogram size for each dimension
	void setSize(int size) {
		// each dimension has equal size 
		histSize[0] = histSize[1] = histSize[2] = size;
	}
	// Computes the histogram.
	cv::Mat getHistogram(const cv::Mat &image) {
		cv::Mat hist;
		// BGR color histogram
		hranges[0] = 0.0;    // BRG range
		hranges[1] = 256.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,        // number of dimensions
			histSize, // size of each dimension
			CV_32F);
		// BGR color histogram
		hranges[0] = 0.0;    // BRG range
		hranges[1] = 256.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.
	// BGR source image is converted to HSV
	// Pixels with low saturation are ignored
	cv::Mat getHueHistogram(const cv::Mat &image,
		int minSaturation = 0) {
		cv::Mat hist;
		// Convert to HSV colour space
		cv::Mat hsv;
		cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);
		// Mask to be used (or not)
		cv::Mat mask;
		// creating the mask if required
		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;    // range is from 0 to 180
		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;
	}
	// Computes the 2D ab histogram.
	// BGR source image is converted to Lab
	cv::Mat getabHistogram(const cv::Mat &image) {
		cv::Mat hist;
		// Convert to Lab color space
		cv::Mat lab;
		cv::cvtColor(image, lab, cv::COLOR_BGR2Lab);
		// Prepare arguments for a 2D color histogram
		hranges[0] = 0;
		hranges[1] = 256.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;
	}
};

#endif

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值