1. 程式人生 > >通過直方圖比較影象相似度

通過直方圖比較影象相似度

#pragma once
using namespace cv;
using namespace std;

class histogram{
private:
	int histsize;
	float range[2];
	const float *histrange;
	int channels[1];
	float threshold;
public:
	histogram() {
		histsize = 256;
		range[0] = 0;
		range[1] = 256;
		histrange = range;
		channels[0] = 0;
		threshold = 0;
	}
	Mat changeImg(const Mat& img) {        //忽略低於邊界值的畫素值
		Mat hsv;
		cvtColor(img, hsv, CV_BGR2HSV);  //轉換成HSV
		vector<Mat> channel;
		split(hsv, channel);


		int minVal = 0;
		int maxVal = 256;
		float Val = 0;
		cout << "請輸入邊界值:" << endl;
		cin >> Val;

		for (; minVal < 256; minVal++) {        //劃定一個值尋找到新的邊界範圍
			if (channel[0].at<uchar>(minVal) > Val)
				break;
			channel[0].at<uchar>(minVal) = 0;     //把邊界之外的畫素值忽略
		}
		for (; maxVal >= 0; maxVal--) {
			if (channel[0].at<uchar>(maxVal) > Val)
				break;
			channel[0].at<uchar>(maxVal) = 255;
		}
		imshow("channel[0]", channel[0]);
		Mat result;
		merge(channel,result);     //這裡只改變了H通道的值,而輸出的是3通道的,所以輸出的變化效果不是很明顯
		return result;
	}
	Mat*  colhistgram(const Mat & img,const Mat& im) {    //計算直方圖
		Mat result, res;
		calcHist(&img, 1, channels, Mat(), result, 1, &histsize, &histrange);
		calcHist(&im, 1, channels, Mat(), res, 1, &histsize, &histrange);

		Mat *m = new Mat[2];
		m[0] = result;
		m[1] = res;
		return m;          //利用指標同時返回兩個值

	}
	Mat colhistgram(const Mat& img) {
		Mat result;
		calcHist(&img, 1, channels, Mat(), result, 1, &histsize, &histrange);
		return result;
	}
	void showhistogram(const Mat& img) {      //顯示直方圖
		Mat gray;
		cvtColor(img, gray, CV_BGR2GRAY);    //轉換成灰度圖
		Mat result(img.size(), img.depth(), Scalar(0, 0, 0));     //畫最後結果的圖

		colhistgram(gray);
		int bin_w = img.cols / histsize;   //繪製的箱子的寬度與高度
		int bin_h = img.rows;
		for (int i = 0; i < 256; i++) {
			uchar p = gray.at<uchar>(i);
			line(result, Point(bin_w*i,bin_h), Point(bin_w*i,bin_h - p), Scalar(123, 123, 0));
		}
		imshow("result",result);
	}
	Mat setthreshold(float num) {    //設定閾值
		threshold = num;
	}
};
class comparatorimg {
private:
	Mat sethist;
	Mat inputhist;
	histogram hist;
	int bins;
public:
	void setbins(int num) {
		bins = num;
	}
	double compatator(const Mat& img, const Mat& im) {     //把輸入影象和標準參考影象直方圖比較,相似累加

		//Mat h1, h2;
		//cvtColor(img, h1, CV_BGR2GRAY);
		//cvtColor(im, h2, CV_BGR2GRAY);     //轉為灰度影象對比,值也會相對大很多

		//Mat *m = hist.colhistgram(h1, h2);
		Mat *m = hist.colhistgram(img, im);
		sethist = m[0];
		inputhist = m[1];

		return compareHist(sethist, inputhist, CV_COMP_INTERSECT);
	}
};

/*
根據直方圖尋找相似圖片
*/
#include<opencv2\opencv.hpp>
#include<iostream>
#include"Histogram.h"
using namespace cv;
using namespace std;

int main() {
	Mat img = imread("D://圖片//5.jpg");
	Mat img_com = imread("D://圖片//0.jpg");        //當此圖片大小大於img時相似值是固定的敏感區域的乘積
	if (img.empty() || img_com.empty())
		return -1;

	Mat imgROI = img(Rect(0, 0, 120, 100));
	comparatorimg h1;
	histogram h2;

	double v = h1.compatator(imgROI,img_com);      //比較相似度
	cout << "相似度為:" << v << endl;

	Mat tem = h2.changeImg(img);  //忽略固定值一下的值處理
	imshow("tem",tem);      //顯示變換後的影象總體效果
	h2.showhistogram(tem);     //顯示變換後的影象的直方圖
	waitKey(0);
	destroyAllWindows;
	return 0;
}

執行結果:

灰度比較:


彩色單通道: