[opencv][cpp] 学习手册1:直方图均衡化

[opencv][cpp] 学习手册1:直方图均衡化




1. 概念

  • 直方图均衡化是一种简单有效的图像增强技术,通过改变图像的直方图来改变图像中各像素的灰度,主要用于增强动态范围偏小的图像的对比度。
  • 换言之,直方图均衡化的基本原理是:对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而增大对比度,使图像清晰,达到增强的目的。
  • 参考:直方图均衡化

2. 绘制直方图

绘制直方图流程(cpp)

  1. 计算图像直方图:calcHist()
  2. 对直方图进行归一化处理:normalizeResult()
  3. 定义画布,循环绘制条形图:for() + line()

1. 代码

common.h


#ifndef STUDYOPENCV001_COMMON_H
#define STUDYOPENCV001_COMMON_H

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;


void showHistogram(string title, Mat &gray) {
    // 定义直方图大小
    int histSize = 256;
    // 定义直方图的范围
    float range[] = {0, 255};
    const float *histRange[] = {range};
    Mat hist;
    calcHist(&gray, 1, 0, Mat(), hist, 1, &histSize, histRange);

    // 想要将直方图绘制到 600,400 图片中去 0~3000  0-400
    // 数据的归一化处理
    Mat normalizeResult;
    normalize(hist, normalizeResult, 0, 400, NORM_MINMAX);
    cout << normalizeResult << endl;


    int hist_height = 400;
    int hist_width = 512;
    // 定义一个画布出来
    Mat dst(hist_height, hist_width, CV_8UC3);

    // 水平方向上的偏移量
    int offsetX = hist_width / 256;

    // 绘制直方图
    for (int i = 0; i < 256; ++i) {
        // 计算最终需要的高度
        int y = normalizeResult.at<float>(i);
        // 计算起始点
        Point pt1(i * offsetX, hist_height);
        // 计算线条的结束点
        Point pt2(i * offsetX, hist_height - y);
        // 绘制直线
        line(dst, pt1, pt2, Scalar(0, 255, 255), 1, LINE_AA);

    }

    imshow(title, dst);
}


#endif //STUDYOPENCV001_COMMON_H

main.h

//
// Created by jacob on 12/21/20.
//

#include <iostream>
#include <opencv2/opencv.hpp>
#include "common.h"

using namespace std;
using namespace cv;

int main() {
	// 读取图片
    Mat src = imread("../img/lena.jpg");

    // 将彩色图像转成灰度图像
    Mat gray;	// 相当于是传入了一个容器
    cvtColor(src, gray, COLOR_BGR2GRAY);
    imshow("gray", gray);

    showHistogram("histogram", gray);

    waitKey();
    return 0;
}

2. 调试验证

在这里插入图片描述


3. 直方图均衡化

1. 代码

05_直方图均衡化.cpp

//
// Created by jacob on 12/21/20.
//

#include <iostream>
#include <opencv2/opencv.hpp>
#include "common.h"


using namespace std;
using namespace cv;


void getHistogram(Mat &gray, Mat &hist);

void getAccumulateRatios(const Mat &gray, const Mat &hist, Mat &sumRatios);

void doEqualization(Mat &gray, Mat &sumRatios);


/**
 * 直方图均衡化
 *  1. 计算直方图
 *  2. 灰度值出现的次数
 *  3. 将出现的次数,转成出现的概率
 *  4. 计算累积概率
 *  5. 通过累积的概率,进行直方图均衡化
 */

int main() {
    Mat src = imread("../img/lena.jpg");
    imshow("src", src);

    //1. 将图像转成灰度图像
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    imshow("gray", gray);

    showHistogram("gray hist", gray);

    //2. 计算直方图
    Mat hist;   // 接收结果 里面存放的是 每一个灰度值出现的次数
    getHistogram(gray, hist);   // gray--input, hist--output

    //3-4. 次数转成出现的概率, 计算累积概率
    Mat sumRatios(256, 1, CV_32FC1);    // 用于存放累积概率
    getAccumulateRatios(gray, hist, sumRatios);

    // 5. 根据累积概率 进行直方图均衡化处理
    doEqualization(gray, sumRatios);

    showHistogram("result hist", gray);
    imshow("result", gray);


    waitKey();
    return 0;
}

/**
 * 进行直方图均衡化
 * @param gray: 输入的灰度图
 * @param sumRatios: 输入的直方图累积概率
 */
void doEqualization(Mat &gray, Mat &sumRatios) {
    for (int row = 0; row < gray.rows; ++row) {
        for (int col = 0; col < gray.cols; ++col) {
            // 获取当前位置的灰度值
            uchar color = gray.at<uchar>(row, col);
            // 根据这个color获取它的累积概率
            float ratio = sumRatios.at<float>(color);
            // 根据比例算一个新的灰度值
            gray.at<uchar>(row, col) = 255 * ratio;
        }
    }
}

/**
 * 计算累积概率直方图
 * @param gray: 输入的灰度图
 * @param hist: 输入的直方图
 * @param sumRatios: 计算的直方图累积概率
 */
void getAccumulateRatios(const Mat &gray, const Mat &hist, Mat &sumRatios) {
    //3. 将次数转成出现的概率
    Mat ratios = hist / (gray.rows * gray.cols);
    //cout<<"出现的概率:"<<ratios<<endl;

    //4. 计算累积概率
    float sum1 = 0;
    for (int i = 0; i < 256; ++i) {
        float ratio = ratios.at<float>(i);
        // 计算当前灰度值的累积概率
        sum1 += ratio;
        // 存起来
        sumRatios.at<float>(i) = sum1;
    }

    cout << "累积概率:" << sumRatios << endl;
}

/**
 * 计算灰度图的直方图
 * @param gray: 输入的灰度图
 * @param hist: 计算出来的直方图
 */
void getHistogram(Mat &gray, Mat &hist) {
    const int histSize = 256;
    // 范围
    float range[] = {0, 256};
    const float *ranges[] = {range};
    calcHist(&gray, 1, 0, Mat(), hist, 1, &histSize, ranges);
}



2. 调试验证

在这里插入图片描述
在这里插入图片描述


*. 参考

  1. 参考:直方图均衡化

*. 问题解决


*. rough

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值