来让均匀化直方图吧!
Opencv 直方图均衡化是使直方图变得平坦的操作,是不需要计算上面的问题中的平均值、标准差等数据使直方图的值变得均衡的操作。
均衡化操作由以下式子定义。S是总的像素数;Z_{max}是像素点的最大取值(在这里是255);h(z)表示取值为z的累积分布函数:
Z’ = \frac{Z_{max}}{S} \  \sum\limits_{i=0}^z\ h(i)
python实现:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# histogram equalization
def hist_equal(img, z_max=255):
    H, W, C = img.shape
    S = H * W * C * 1.
    out = img.copy()
    sum_h = 0.
    for i in range(1, 255):
        ind = np.where(img == i)
        sum_h += len(img[ind])
        z_prime = z_max / S * sum_h
        out[ind] = z_prime
    out = out.astype(np.uint8)
    return out
# Read image
img = cv2.imread("imori.jpg").astype(np.float)
# histogram normalization
out = hist_equal(img)
# Display histogram
plt.hist(out.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.savefig("out_his.png")
plt.show()
# Save result
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.imwrite("out.jpg", out)
c++实现:
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <math.h>
// histogram equalization
cv::Mat histogram_equalization(cv::Mat img){
  // get height and width
  int width = img.cols;
  int height = img.rows;
  int channel = img.channels();
  // output image
  cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3);
  // histogram equalization hyper-parameters
  double Zmax = 255;
  double hist[255];
  double S = height * width * channel;
  int val;
  double hist_sum = 0;
  // histogram initialization
  for (int i = 0; i < 255; i++){
     hist[i] = 0;
  }
  // get histogram sum
  for (int y = 0; y < height; y++){
    for (int x = 0; x < width; x++){
      for (int c = 0; c < channel; c++){
        val = (int)img.at<cv::Vec3b>(y, x)[c];
        hist[val] ++;
      }
    }
  }
  // histogram equalization
  for (int y = 0; y < height; y++){
    for (int x = 0; x < width; x++){
      for (int c = 0; c < channel; c++){
        val = (int)img.at<cv::Vec3b>(y, x)[c];
        // get histogram sum <= current pixel value
        hist_sum = 0;
        for (int l = 0; l < val; l++){
          hist_sum += hist[l];
        }
        // assign equalized value
        out.at<cv::Vec3b>(y, x)[c] = (uchar)(Zmax / S * hist_sum);
      }
    }
  }
  return out;
}
int main(int argc, const char* argv[]){
  // read image
  cv::Mat img = cv::imread("imori.jpg", cv::IMREAD_COLOR);
  // histogram equalization
  cv::Mat out = histogram_equalization(img);
  //cv::imwrite("out.jpg", out);
  cv::imshow("answer", out);
  cv::waitKey(0);
  cv::destroyAllWindows();
  return 0;
}
输入:

输出:

直方图:

极客教程