在图像处理中,灰度直方图能反映一幅图像的灰度级信息。灰度直方图是图像灰度级的函数,用来描述该幅图像中像素个数或者占有率。
C++:
#include
#include
using namespace std;
using namespace cv;
//计算图像灰度直方图
Mat calcgrayhist(const Mat&image)
{
Mat histogram = Mat::zeros(Size(256, 1), CV_32SC1);
//图像宽高
int rows = image.rows;
int cols = image.cols;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < rows; j++)
{
int index = int(image.at<uchar>(i, j));
histogram.at<int>(0, index) += 1;
}
}
return histogram;
};
//直方图均衡化
Mat equalhist(Mat image)
{
int rows = image.rows;
int cols = image.cols;
//1.计算图像灰度直方图
Mat grayhist = calcgrayhist(image);
//2.计算累加灰度直方图
Mat accumulate_hist = Mat::zeros(Size(256, 1), CV_32SC1);
for (int p = 0; p < 256; p++)
{
if (p == 0)
accumulate_hist.at<int>(0, p) = grayhist.at<int>(0, 0);
else
accumulate_hist.at<int>(0, p)= accumulate_hist.at<int>(0, p-1)+
grayhist.at<int>(0, p);
}
//3.映射
Mat out_p=Mat::zeros(Size(256, 1), CV_8UC1);
float cofficient = 256.0 / (rows*cols);
for (int p = 0; p < 256; p++)
{
float q = cofficient*accumulate_hist.at<int>(0, p) - 1;
if (q >= 0)
out_p.at<uchar>(0, p) = uchar(floor(q));
else
out_p.at<uchar>(0, p) = 0;
}
Mat equalhistimage= Mat::zeros(image.size(), CV_8UC1);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
int p = image.at<uchar>(i, j);
equalhistimage.at<uchar>(i, j) =out_p.at<uchar>(0, p);
}
}
return equalhistimage;
};
//自适应直方图均衡化
Mat adapt_equalhist(Mat image)
{
Ptr<CLAHE>clahe = createCLAHE(2.0, Size(8, 8));
Mat dst;
clahe->apply(image, dst);
//imshow("original image", image);
//imshow("adapt image", dst);
//waitKey(0);
return dst;
};
int main()
{
Mat img, gray_img,src,dst;
img = imread("D:/testimage/scenery.jpg");
cvtColor(img, gray_img, COLOR_BGR2GRAY);
src = equalhist(gray_img);
dst=adapt_equalhist(gray_img);
imshow("equal image", src);
imshow("adapt equalimage", dst);
waitKey(0);
return 0;
};
结果:
彩色直方图:
直方图均衡化:
自适应直方图均衡化:
在这张图像上,两者看不出明显的变化,除了在天空云层的那一块,自适应一般是为了保留一些细节,防止整个图像都按照原函数处理,可能达不到要求。
Python:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import math
def calc_grayhist(image):
#图像宽高
rows,cols=image.shape
grayhist=np.zeros([256],np.uint64)
for i in range(rows):
for j in range(cols):
grayhist[image[i][j]]+=1
return grayhist
#彩色图像支方图
def calc_colorhist(src):
channels=cv.split(src);
colors=('B','G','R')
plt.xlabel=("grays level")
plt.ylabel=("pixels")
for (channel,color) in zip(channels,colors):
hist=cv.calcHist([channel],[0], None, [256], [0, 256])
plt.plot(hist, color=color)
plt.xlim([0, 256])
plt.show()
#直方图均衡化
def equalhist(image):
# 图像宽高
rows, cols = image.shape
grayhist=calc_grayhist(image)
# 计算累加灰度直方图
Accumulate_histogram=np.zeros([256],np.uint32)
for p in range (256):
if p ==0:
Accumulate_histogram[p]=grayhist[0]
else:
Accumulate_histogram[p]=Accumulate_histogram[p-1]+grayhist[p]
#根据累加直方图得到输入灰度级和输出灰度级之间的映射关系
out_q=np.zeros([256],np.uint8)
cofficient=256.0/(rows*cols)
for p in range(256):
q=cofficient*float(Accumulate_histogram[p])-1
if q>=0:
out_q[p]=math.floor(q)
else:
out_q[p]=0
#直方图均衡图像
equalhist_image=np.zeros(image.shape,np.uint8)
for i in range(rows):
for j in range(cols):
equalhist_image[i][j]=out_q[image[i][j]]
return equalhist_image
#自适应直方图均衡化
def adapt_equalhist(image):
#clipLimit参数表示对比度的大小。
#tileGridSize参数表示每次处理块的大小
clahe=cv.createCLAHE(clipLimit=2,tileGridSize=(8,8))
dst=clahe.apply(image)
return dst
if __name__=="__main__":
img=cv.imread("D:/testimage/scenery.jpg")
gray_dst = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
calc_grayhist(gray_dst)
calc_colorhist(img)
equal_dst=equalhist(gray_dst)
adapt_equaldst=adapt_equalhist(gray_dst)
cv.imshow("gray dst",gray_dst)
cv.imshow("equal dst", equal_dst)
cv.imshow("adapt equaldst", adapt_equaldst)
cv.waitKey(0)
cv.destroyAllWindows()
今日头条-witnesS