直方图均衡化
函数实现的灰度直方图均衡化算法,即将直方图的每个灰度值进行归一化处理,求各个灰度的累积分布,接着得到一个映射的灰度映射表,然后根据相应的灰度值来修正原图中的每个像素。
函数原型
void equalizeHist(InputArray src,
OutputArray dst
)
实例
Mat img = imread("F:\\desktop\\OpenCV_study\\my.jpg", IMREAD_GRAYSCALE);
Mat dst;
equalizeHist(img, dst);
imshow("img", img);
imshow("dst", dst);
// 使用C++绘制灰度直方图
// 分通道显示
vector<Mat> bgr_planes;
split(src, bgr_planes);
//imshow("single channel demo", bgr_planes[0]);
// 计算直方图
int histSize = 256;
float range[] = { 0, 256 };
const float *histRanges = { range };
Mat b_hist, g_hist, r_hist;
calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);
// 归一化
int hist_h = 400;
int hist_w = 512;
int bin_w = hist_w / histSize;
Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
// 绘制表格
for (int i = 1; i < histSize; i++) {
// hist_h - cvRound(b_hist.at<float>(i - 1)) 的目的是让直方图看起来y轴方向朝上
line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);
/************************************画矩形***************************************************/
/**
两种方式画出的矩形相同,只有细微的差别
rectangle(histImage, Rect((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1)),
(i)*bin_w, hist_h), Scalar(255, 0, 0), 2, LINE_AA);
rectangle(histImage1, Rect((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1)),
(i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
**/
}
imshow(OUTPUT_T, histImage);
# 对于python来说可以使用matplotlib.pyplot.hist()计算
def plyHist_demo(self):
'''
nt,bins,patchesplt=matplotlib.pyplot.hist(x,bins=None,density=None,bottom=None,
histtype='bar',align='mid',log=False,color=None,label=None,stacked=False,normed=Node)
bins : 统计的区间分布
range : tuple,显示区间
density : 显示/不显示频率统计结果,频率统计结果=区间数目/(总数*区间宽度)
histtype : ['bar','barstacked','step','stepfilled]
align : ['left','middle','right'] , 控制柱状图水平分布,默认'middle'
log : Y坐标轴是否选择指数刻度
stacked :是否为堆积状图
nt : 返回每个bins元素的数量
bins : 返回每个bin区间的范围
patched : 返回每个bin里面包含的数据,list
'''
rows, cols, channels = self._img.shape
img = cv.cvtColor(self._img, cv.COLOR_BGR2GRAY)
cv.imshow("_img", self._img)
cv.imshow("img", img)
pixelSequence = img.reshape([img.shape[0]*img.shape[1], ])
numBins = 256
histData, bins, patched = plt.hist(
pixelSequence, numBins, facecolor='red')
# 设置标签
plt.xlabel("gray level")
plt.ylabel("number of pixels")
# 设置范围
yMaxVal = np.max(histData)
plt.axis([0, 255, 0, yMaxVal])
plt.show()
return