赞
踩
对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度,进而比较图像本身的相似程度。
Opencv提供的比较方法有四种:
其中N是直方图的BIN个数, H ˉ \bar{H} Hˉ 为均值,H1,H2分别表示两个图像的直方图数据





头文件 quick_opencv.h:声明类与公共函数
#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;
class QuickDemo {
public:
...
void compareHist_Demo(Mat& image1, Mat& image2, Mat& image3);
void backProjection_Demo(Mat& image1);
};
主函数调用该类的公共成员函数
#include <opencv2\opencv.hpp> #include <quick_opencv.h> #include <iostream> using namespace cv; int main(int argc, char** argv) { Mat src1 = imread("D:\\Desktop\\pandas_small22.png"); Mat src2 = imread("D:\\Desktop\\pandas_small22_test1.png"); Mat src3 = imread("D:\\Desktop\\pandas_small22_test2.png"); if (src1.empty()) { printf("Could not load images src1...\n"); return -1; } if (src2.empty()) { printf("Could not load images src2...\n"); return -1; } if (src3.empty()) { printf("Could not load images src3...\n"); return -1; } QuickDemo qk; qk.compareHist_Demo(src1, src2, src3); qk.backProjection_Demo(src1); waitKey(0); destroyAllWindows(); return 0; }
源文件 quick_demo.cpp:实现类与公共函数
void QuickDemo::compareHist_Demo(Mat& image, Mat& test1, Mat& test2) { Mat hsv_dst1, hsv_dst2, hsv_dst3; cvtColor(image, hsv_dst1, COLOR_BGR2HSV); cvtColor(test1, hsv_dst2, COLOR_BGR2HSV); cvtColor(test2, hsv_dst3, COLOR_BGR2HSV); Mat hsv_src1 = hsv_dst1.clone(); Mat hsv_src2 = hsv_dst2.clone(); Mat hsv_src3 = hsv_dst3.clone(); int h_bins = 50; int s_bins = 60; int histSize[] = { h_bins, s_bins }; //h = [0-179] s=[0,255] float h_ranges[] = { 0,180 }; float s_ranges[] = { 0,256 }; const float* ranges[] = { h_ranges, s_ranges }; // Use the o-th and 1-st channels int channels[] = { 0,1 }; MatND hist_base; MatND hist_test1; MatND hist_test2; calcHist(&hsv_dst1, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false); normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&hsv_dst2, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false); normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat()); calcHist(&hsv_dst3, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false); normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat()); int method[4] = { HISTCMP_CORREL ,HISTCMP_CHISQR, HISTCMP_INTERSECT,HISTCMP_BHATTACHARYYA }; for (int i = 0; i < 4; i++) { double basebase = compareHist(hist_base, hist_base, method[i]); double basetest1 = compareHist(hist_base, hist_test1, method[i]); double basetest2 = compareHist(hist_base, hist_test2, method[i]); putText(hsv_dst1, to_string(basebase), Point(20, image.rows - 20), FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 2, 8); putText(hsv_dst2, to_string(basetest1), Point(20, image.rows - 20), FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 2, 8); putText(hsv_dst3, to_string(basetest2), Point(20, image.rows - 20), FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 2, 8); imshow("src", hsv_dst1); imshow("dst1", hsv_dst2); imshow("dst2", hsv_dst3); // 清空图片文字 hsv_src1.copyTo(hsv_dst1); hsv_src2.copyTo(hsv_dst2); hsv_src3.copyTo(hsv_dst3); waitKey(0); } }
对测试图片进行光影调整后分别保存为test1,test2副本后测试:
比较方法:HISTCMP_CORREL

比较方法:HISTCMP_CHISQR

比较方法:HISTCMP_INTERSECT
比较方法:HISTCMP_BHATTACHARYYA

反向投影是反映直方图模型在目标图像中的分布情况
简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型。
一般检查流程
共三个重载函数,我这里只列出一个
void QuickDemo::backProjection_Demo(Mat& image, Mat& test1) { Mat hsv,h_mat; cvtColor(image, hsv, COLOR_BGR2HSV); h_mat = Mat::zeros(hsv.size(), hsv.depth()); int nchannels[] = { 0,0 }; mixChannels(&hsv,1, &h_mat, 1, nchannels, 1); int binSize = 12; float range[] = { 0,180 }; const float* histRange{ range }; Mat h_hist; calcHist(&h_mat, 1, 0, Mat(), h_hist, 1, &binSize, &histRange, true, false); normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat()); Mat backProjectImage; calcBackProject(&h_mat, 1,0, h_hist, backProjectImage, &histRange, 1, true); imshow("backPro", backProjectImage); int hist_h = 400; int hist_w = 400; Mat hist_Image = Mat::zeros(hist_w, hist_h, CV_8UC3); int bin_w = hist_w / binSize; for (int i = 0; i < binSize; i++) { rectangle(hist_Image, Point((i - 1) * bin_w, hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255))), Point(i* bin_w, hist_h), Scalar(255, 255, 0), -1); } imshow("histogram", hist_Image); }
使用效果:

使用 trackbar 详情
使用trackbar, 代码有问题,请教大佬。
static void on_bin_hist(int binSize_, void* h_mat_) { Mat h_hist; Mat h_mat = *((Mat*)h_mat_); int binSize = MAX(binSize_, 2); float range[] = { 0,180 }; const float* histRange{ range }; calcHist(&h_mat, 1, 0, Mat(), h_hist, 1, &binSize, &histRange, true, false); normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat()); Mat backProjectImage; calcBackProject(&h_mat, 1, 0, h_hist, backProjectImage, &histRange, 1, true); imshow("backPro", backProjectImage); int hist_h = 400; int hist_w = 400; Mat hist_Image = Mat::zeros(hist_w, hist_h, CV_8UC3); int bin_w = cvRound((double)hist_w / binSize); for (int i = 0; i < binSize; i++) { rectangle(hist_Image, Point((i - 1) * bin_w, hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255))), Point(i * bin_w, hist_h), Scalar(255, 255, 0), -1); } imshow("histogram", hist_Image); } void QuickDemo::backProjection_track_bar_Demo(Mat& image) { namedWindow("histogram", WINDOW_NORMAL); namedWindow("backPro", WINDOW_NORMAL); int binSize = 12; Mat hsv, h_mat; cvtColor(image, hsv, COLOR_BGR2HSV); h_mat = Mat::zeros(hsv.size(), hsv.depth()); int nchannels[] = { 0,0 }; mixChannels(&hsv, 1, &h_mat, 1, nchannels, 1); createTrackbar("hist_bins", "histogram", &binSize, 180, on_bin_hist, &h_mat); on_bin_hist(binSize, &h_mat); }
if (image.empty() || image.cols != 150 || image.rows != 70) return; cv::Mat Image2; int chanels = image.channels(); if (4 == chanels) cv::cvtColor(image, image, cv::COLOR_BGRA2GRAY); else if (3 == chanels) cv::cvtColor(image, image, cv::COLOR_BGR2GRAY); cv::threshold(image, image, 250, 255, cv::THRESH_BINARY); cv::bitwise_not(image, image); int height = image.rows; int width = image.cols; // 水平投影:统计并存储每一行的和 std::vector<int> horizontal(height); for (size_t h = 0; h < height; h++) { uchar* row_ptr = image.ptr<uchar>(h); for (size_t w = 0; w < width; w++) { horizontal[h] += *row_ptr++; } } cv::transpose(image, Image2); // 垂直投影:统计并存储每一列的和 std::vector<int> vertical(width); for (size_t h = 0; h < width; h++) { uchar* row_ptr = Image2.ptr<uchar>(h); for (size_t w = 0; w < height; w++) { vertical[h] += *row_ptr++; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。