来让均匀化直方图吧!
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;
}
输入:
输出:
直方图: