opencv直方图均衡化

实验内容:

1、计算灰度图像的归一化直方图。
具体内容:利用 OpenCV 对图像像素进行操作,计算归一化直方图.并在 窗口中以图形的方式显示出来

2、灰度图像直方图均衡处理

具体内容:通过计算归一化直方图,设计算法实现直方图均衡化处理。

3、彩色图像直方图均衡处理
具体内容: 在灰度图像直方图均衡处理的基础上实现彩色直方图均衡

实验原理:

算法过程:

img

完整课程PPT和实验要求戳:https://github.com/MintLucas/Digital_image_process

讲解用注释标注在代码中

#include "Lab02_hisBalance.hpp"
#include<iostream>
#include<string>
#include<vector>

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

using namespace std;
using namespace cv;

Mat equalize_hist(Mat& input)
{
    int gray[256] = { 0 };
    double gray_prob[256] = { 0 };
    double gray_distribution[256] = { 0 };
    int gray_equal[256] = { 0 };
    
    int MN = 0;
    Mat output = input.clone();
    MN = input.cols * input.rows;
    
    Mat_<uchar>::iterator it = output.begin<uchar>();
    Mat_<uchar>::iterator end = output.end<uchar>();
    
    for (; it < end; it++)
        gray[*it]++;//统计像素值出现次数
    
    it = output.begin<uchar>();
    for(; it < end; it++)
        gray_prob[*it] = ((double)gray[*it]/MN);//计算PDF

    it = output.begin<uchar>();
    gray_distribution[0] = gray_prob[0];
    for (int i = 1; i < 256; i++)
        //计算cdf
        gray_distribution[i] = gray_distribution[i - 1] + gray_prob[i];
    
    //映射后的像素值
    for (int i = 0; i < 256; i++)
        gray_equal[i] = (uchar)(255 * gray_distribution[i]);
    
    it = output.begin<uchar>();
    for(; it < end; it++)
        *it = gray_equal[*it];
    
    return output;
}

Mat color_equalize_hist(Mat input)
{
    vector<Mat> channels;
    split(input, channels);
    
    for (int i = 0; i < channels.size(); i++)
        channels[i] = equalize_hist(channels[i]);

    Mat res;
    merge(channels, res);
    return res;
}

int drawHisRGB(Mat image)
{
    int bins = 256;
    int hist_size[] = { bins };
    float range[] = { 0, 256 };
    const float* ranges[] = { range };
    
    MatND hist_r, hist_g, hist_b;
    int channels_r[] = { 0 };
    calcHist(&image, 1, channels_r, Mat(), // do not use mask
             hist_r, 1, hist_size, ranges,
             true, // the histogram is uniform
             false);
    
    int channels_g[] = { 1 };
    calcHist(&image, 1, channels_g, Mat(), // do not use mask
             hist_g, 1, hist_size, ranges,
             true, // the histogram is uniform
             false);
    
    int channels_b[] = { 2 };
    calcHist(&image, 1, channels_b, Mat(), // do not use mask
             hist_b, 1, hist_size, ranges,
             true, // the histogram is uniform
             false);
    
    double max_val_r, max_val_g, max_val_b;
    minMaxLoc(hist_r, 0, &max_val_r, 0, 0);
    minMaxLoc(hist_g, 0, &max_val_g, 0, 0);
    minMaxLoc(hist_b, 0, &max_val_b, 0, 0);
    int scale = 1;
    
    int hist_height = 256;
    Mat colorHis = Mat::zeros(hist_height, bins * 3, CV_8UC3);
    for (int i = 0; i < bins; i++)
    {
        float bin_val_r = hist_r.at<float>(i);
        float bin_val_g = hist_g.at<float>(i);
        float bin_val_b = hist_b.at<float>(i);
        int intensity_r = cvRound(bin_val_r*hist_height / max_val_r);  //“™ªÊ÷∆µƒ∏fl∂»
        int intensity_g = cvRound(bin_val_g*hist_height / max_val_g);  //“™ªÊ÷∆µƒ∏fl∂»
        int intensity_b = cvRound(bin_val_b*hist_height / max_val_b);  //“™ªÊ÷∆µƒ∏fl∂»
        rectangle(colorHis, Point(i*scale, hist_height - 1),
                  Point((i + 1)*scale - 1, hist_height - intensity_r),
                  CV_RGB(255, 0, 0));
        
        rectangle(colorHis, Point((i + bins)*scale, hist_height - 1),
                  Point((i + bins + 1)*scale - 1, hist_height - intensity_g),
                  CV_RGB(0, 255, 0));
        
        rectangle(colorHis, Point((i + bins * 2)*scale, hist_height - 1),
                  Point((i + bins * 2 + 1)*scale - 1, hist_height - intensity_b),
                  CV_RGB(0, 0, 255));
        
    }
    imgShow(colorHis, "colorHis");
    return 0;
    
}

int drawHisGray(Mat image)
{
    int bins = 256;
    int hist_size[] = { bins };
    float range[] = { 0, 256 };
    const float* ranges[] = { range };
    
    MatND hist;
    int channels[] = { 0 };
    calcHist(&image, 1, channels, Mat(), // do not use mask
             hist, 1, hist_size, ranges,
             true, // the histogram is uniform
             false);
    
    double max_val;
    minMaxLoc(hist, 0, &max_val, 0, 0);
    
    int scale = 2;
    int hist_height = 256;
    Mat hist_img = Mat::zeros(hist_height, bins*scale, CV_8UC3);
    for (int i = 0; i < bins; i++)
    {
        float bin_val = hist.at<float>(i);
        int intensity = cvRound(bin_val*hist_height / max_val);
        
        rectangle(hist_img, Point(i*scale, hist_height - 1),
                  Point((i + 1)*scale - 1, hist_height - intensity),
                  CV_RGB(255, 255, 255));
    }
    
    imgShow(hist_img, "histOfImg");
    return 0;
}

int drawHis2D(Mat image)
{
    int hbins = 256, sbins = 256;
    int histSize[] = { hbins, sbins };
    
    float hranges[] = { 0, 256 };
    float sranges[] = { 0, 256 };
    const float* ranges[] = { hranges, sranges };
    MatND hist;
    
    int channels[] = { 0, 1 };
    calcHist(&image, 1, channels, Mat(), // do not use mask
             hist, 2, histSize, ranges,
             true, // the histogram is uniform
             false);
    double maxVal = 0;
    minMaxLoc(hist, 0, &maxVal, 0, 0);
    int scale = 2;
    Mat histImg = Mat::zeros(sbins*scale, hbins*scale, CV_8UC3);
    for (int h = 0; h < hbins; h++)
        for (int s = 0; s < sbins; s++)
        {
            float binVal = hist.at<float>(h, s);
            int intensity = cvRound(binVal * 255 / maxVal);
            rectangle(histImg, Point(h*scale, s*scale),
                      Point((h + 1)*scale - 1, (s + 1)*scale - 1),
                      Scalar::all(intensity),
                      FILLED);
        }
    imgShow(histImg, "2Dhist");
    return 0;
}

//int main()
//{
//    // 以黑白方式载入图像
//    Mat img = imread("/Users/zhipeng/ustc_term2/Opencv/Opencv/Opencv/Digital_imgae_process/CSet12/lena.png", 0);
//    Mat colorImg = imread("/Users/zhipeng/ustc_term2/Opencv/Opencv/Opencv/Digital_imgae_process/CSet12/lena.png", 1);
//    // 检测图像是否真的被载入
//    if(img.empty() || colorImg.empty())
//        return -1;
//    drawHisGray(img);
//    Mat gray_equalized = equalize_hist(img);
//    drawHisGray(gray_equalized);
//
//    drawHisRGB(colorImg);
//    Mat color_equalized = color_equalize_hist(colorImg);
//    drawHisRGB(color_equalized);
//
//    imgShow(colorImg, "colorImg");
//    imgShow(color_equalized, "color_equalized");
//    return 0;
//}
```
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值