让直方图的平均值m_0=128,标准差s_0=52吧!
这里并不是变更直方图的动态范围,而是让直方图变得平坦。
可以使用下式将平均值为m标准差为s的直方图变成平均值为m_0标准差为s_0的直方图:
x_{out}=\frac{s_0}{s}\ (x_{in}-m)+m_0
python实现:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# histogram manipulation
def hist_mani(img, m0=128, s0=52):
m = np.mean(img)
s = np.std(img)
out = img.copy()
# normalize
out = s0 / s * (out - m) + m0
out[out < 0] = 0
out[out > 255] = 255
out = out.astype(np.uint8)
return out
# Read image
img = cv2.imread("imori_dark.jpg").astype(np.float)
out = hist_mani(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 transform
cv::Mat histogram_transform(cv::Mat img, int m0, int s0){
// get height and width
int width = img.cols;
int height = img.rows;
int channel = img.channels();
// histogram transformation hyper-parameters
double m, s;
double sum = 0., squared_sum = 0.;
double val;
// output image
cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3);
// get sum
for (int y = 0; y < height; y++){
for (int x = 0; x < width; x++){
for (int c = 0; c < 3; c++){
val = (float)img.at<cv::Vec3b>(y, x)[c];
sum += val;
squared_sum += (val * val);
}
}
}
// get standard deviation
m = sum / (height * width * channel);
s = sqrt(squared_sum / (height * width * channel) - m * m);
// histogram transformation
for (int y = 0; y < height; y++){
for ( int x = 0; x < width; x++){
for ( int c = 0; c < 3; c++){
val = img.at<cv::Vec3b>(y, x)[c];
out.at<cv::Vec3b>(y, x)[c] = (uchar)(s0 / s * (val - m) + m0);
}
}
}
return out;
}
int main(int argc, const char* argv[]){
// read image
cv::Mat img = cv::imread("imori_dark.jpg", cv::IMREAD_COLOR);
// histogram transform
cv::Mat out = histogram_transform(img, 128, 52);
//cv::imwrite("out.jpg", out);
cv::imshow("answer", out);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
输入:
输出:
直方图: