opencv4 学习 15 直方图均衡化和直方图匹配

1、直方图均衡化的作用,主要就是提高图像的对比度同时均衡化图像的亮度,扩展像素的分布范围,同时使像素值尽量均匀分步。

函数使用:

    Mat src = imread("lena.jpg", IMREAD_COLOR);
    cvtColor(src, src, COLOR_BGR2GRAY);
    Mat dst;
    equalizeHist(src, dst);

算法原理参考:https://docs.opencv.org/3.4/d4/d1b/tutorial_histogram_equalization.html

2、直方图的计算和绘制

normalize( 
InputArray src,
InputOutputArray dst,
double alpha = 1, 归一化的低边界的值
double beta = 0, 归一化的高边界的值
int norm_type = NORM_MINMAX, 归一化方法,本示例使用最大最小归一化
int dtype = -1, -1表示输出值类型和输入相同
InputArray mask = noArray());

calcHist( 
const Mat* images, 输入图片
int nimages, 输入图片的数量
const int* channels, InputArray mask, 选择需要的channel和channle的掩码
SparseMat& hist, int dims, 保存输出值,设置输出数组的维度
const int* histSize, 每个channel的bin的个数
const float** ranges, 每个channel的bin的范围
bool uniform = true, bool accumulate = false
);
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;


int main(int argc, char* argv[])
{
    Mat src = imread("lena.jpg", IMREAD_COLOR);
    vector<Mat> bgr_planes;
    split(src, bgr_planes);

    int histSize = 256;

    float range[] = {0, 256};
    const float* histRange = { range };

    bool uniform = true, accumulate = false;

    Mat b_hist, g_hist, r_hist;
    calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
    calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);
    calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);

    int hist_w = 512, hist_h = 400;
    int bin_w = cvRound((double)hist_w/histSize);
    Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0,0,0));

    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

    for(int i=1; i<histSize; i++){
        line(histImage, Point(bin_w*(i-1), hist_h-cvRound(b_hist.at<float>(i-1))),
             Point(bin_w*i, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255,0,0), 2, 8, 0);
        line(histImage, Point(bin_w*(i-1), hist_h-cvRound(g_hist.at<float>(i-1))),
             Point(bin_w*i, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0,255,0), 2, 8, 0);
        line(histImage, Point(bin_w*(i-1), hist_h-cvRound(r_hist.at<float>(i-1))),
             Point(bin_w*i, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0,0,255), 2, 8, 0);

    }
    imshow("Source image", src);
    imshow("calcHist Demo", histImage);
    waitKey(0);
    return 0;

}

 参看:

3、直方图匹配

函数介绍 double compareHist( InputArray H1, InputArray H2, int method );

method 的取值:

enum HistCompMethods {
    HISTCMP_CORREL        = 0,  // Correlation
    HISTCMP_CHISQR        = 1,  // Chi-Square
    HISTCMP_INTERSECT     = 2,  // Intersection
    HISTCMP_BHATTACHARYYA = 3,  // Bhattacharyya distance
    HISTCMP_HELLINGER     = HISTCMP_BHATTACHARYYA, //!< Synonym for HISTCMP_BHATTACHARYYA
    HISTCMP_CHISQR_ALT    = 4,
};
Correlation 和 Intersection 方法的返回值越大,表示越相似;另外两种方法相反。
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{    
    Mat src_base = imread("G:\\tools\\opencv4\\workspace\\opencv01\\Histogram_Comparison_Source_0.jpg");
    Mat src_test1 = imread("G:\\tools\\opencv4\\workspace\\opencv01\\Histogram_Comparison_Source_1.jpg");
    Mat src_test2 = imread("G:\\tools\\opencv4\\workspace\\opencv01\\Histogram_Comparison_Source_2.jpg");

    Mat hsv_base, hsv_test1, hsv_test2;
    cvtColor(src_base, hsv_base, COLOR_BGR2HSV);
    cvtColor(src_test1, hsv_test1, COLOR_BGR2HSV);
    cvtColor(src_test2, hsv_test2, COLOR_BGR2HSV);

    Mat hsv_half_down = hsv_base(Range(hsv_base.rows / 2, hsv_base.rows), Range(0, hsv_base.cols));

    int h_bins = 50, s_bins = 60;
    int histSize[] = { h_bins, s_bins };

    float h_ranges[] = { 0, 180 };
    float s_ranges[] = { 0, 256 };

    const float* ranges[] = { h_ranges, s_ranges };

    int channels[] = { 0, 1 };

    Mat hist_base, hist_half_down, hist_test1, hist_test2;

    calcHist(&hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false);
    normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());

    calcHist(&hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false);
    normalize(hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat());

    calcHist(&hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
    normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());

    calcHist(&hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);
    normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());

    for (int compare_method = 0; compare_method < 4; compare_method++) {
        double base_base = compareHist(hist_base, hist_base, compare_method);
        double base_half = compareHist(hist_base, hist_half_down, compare_method);
        double base_test1 = compareHist(hist_base, hist_test1, compare_method);
        double base_test2 = compareHist(hist_base, hist_test2, compare_method); 

        cout << "Method " << compare_method << " Perfect, Base-Half, Base-Test(1), Base-Test(2): "
            << base_base << " / " << base_half << " / " << base_test1 << " / " << base_test2 << endl;

    }
    cout << "Done \n";
    waitKey(0);
    return 0;
}

参考:https://docs.opencv.org/master/d8/dc8/tutorial_histogram_comparison.html


 

posted @ 2020-08-16 11:39  blackx  阅读(323)  评论(0编辑  收藏  举报