(1)图像直方图理论知识
灰度直方图是灰度级的函数,描述的是图像中每种灰度级像素的个数,反映图像中每种灰度出现的频率,可以通过归一化化为到(0,1)之间。
(2)OpenCV绘制直方图
使用calcHist()函数计算直方图,计算完成之后采用OpenCV中的绘制函数,如绘制矩形的rectangle()函数,绘制线段的line()函数来完成。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
#读取图像
src=cv2.imread('lena-hd.png')
#计算256灰度级的图像直方图
hist = cv2.calcHist([src], [0], None, [256], [0,255])
#输出直方图大小、形状、数量
print(hist.size)
print(hist.shape)
print(hist)
#设置字体
matplotlib.rcParams['font.sans-serif']=['SimHei']
#显示原始图像和绘制的直方图
plt.subplot(121)
plt.imshow(src, 'gray')
plt.axis('off')
plt.title("(a)Lena 灰度图像")
plt.subplot(122)
plt.plot(hist, color='r')
plt.xlabel("x")
plt.ylabel("y")
plt.title("(b)直方图曲线")
plt.show()
# 彩色图像绘制直方图
#读取图像
src = cv2.imread('lena.png')
#转换为 RGB 图像
img_rgb = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
#计算直方图
histb = cv2.calcHist([src], [0], None, [256], [0,255])
histg = cv2.calcHist([src], [1], None, [256], [0,255])
histr = cv2.calcHist([src], [2], None, [256], [0,255])
#设置字体
matplotlib.rcParams['font.sans-serif']=['SimHei']
#显示原始图像和绘制的直方图
plt.subplot(121)
plt.imshow(img_rgb, 'gray')
plt.axis('off')
plt.title("(a)Lena 原始图像")
plt.subplot(122)
plt.plot(histb, color='b')
plt.plot(histg, color='g')
plt.plot(histr, color='r')
plt.xlabel("x")
plt.ylabel("y")
plt.title("(b)直方图曲线")
plt.show()
(3)Matplotlib绘制直方图
Python 绘制直方图主要调用 matplotlib.pyplot 库中 hist()函数实现,它会根据数据源和像素级绘制直方图,通常需要通过
函数 ravel()拉直图像将图片转为一维
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图像
src=cv2.imread('lena-hd.png')
#绘制直方图
plt.hist(src.ravel(),256)
plt.xlabel('x')
plt.ylable('y')
plt.show()
plt.hist(src.ravel(), bins=256, density=1, facecolor='green', alpha=0.75)
# 绘制彩色图像的彩色直方图(三维)
import cv2
import numpy as np
import matplotlib.pyplot as plt
src=cv2.imread('lena.png')
b,g,r=cv2.split(src)
#绘制直方图
plt.figure('lena')
#蓝色分量
plt.hist(b.ravel(),bins=256,density=1,facecolor='b',edgecolor='b',alpha=0.75)
#绿色分量
plt.hist(g.ravel(), bins=256, density=1, facecolor='g', edgecolor='g', alpha=0.75)
#红色分量
plt.hist(r.ravel(), bins=256, density=1, facecolor='r', edgecolor='r', alpha=0.75)
plt.xlable('x')
plt.ylable('y')
#绘制多张图片
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
src=cv2.imread('lena.png')
img_rgb=cv2.cvtColor(src,cv2.COLOR_BGR2RGB)
b,g,r=cv2.split(src)
plt.figure(figsize=(8,6))
matplotlib.rcParams['font.sans-serif']=['SimHei']
#原始图像
plt.subplot(221)
plt.imshow(img_rgb)
plt.axis('off')
plt.title('(a)原图像‘)
#绘制蓝色分量直方图
plt.subplot(222)
plt.hist(b.ravel(), bins=256, density=1, facecolor='b', edgecolor='b', alpha=0.75)
plt.xlabel("x")
plt.ylabel("y")
plt.title("(b)蓝色分量直方图")
#绘制绿色分量直方图
plt.subplot(223)
plt.hist(g.ravel(), bins=256, density=1, facecolor='g', edgecolor='g',alpha=0.75)
plt.xlabel("x")
plt.ylabel("y")
plt.title("(c)绿色分量直方图")
#绘制红色分量直方图
plt.subplot(224)
plt.hist(r.ravel(), bins=256, density=1, facecolor='r', edgecolor='r', alpha=0.75)
plt.xlabel("x")
plt.ylabel("y")
plt.title("(d)红色分量直方图")
plt.show()
(1)灰度增强直方图对比
通过灰度值上移,提升图像的亮度
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图像
img=cv2.imread('lena-hd.png')
#图像灰度转换
grayimage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#获取图像高度和宽度
height=grayimage.shape[0]
width=grayimage.shape[1]
result=np.zeros((height,width),np.uint8)
#图像灰度上移变换 DB=DA+50
for i in range(height):
for j in range(width):
if(int(grayimage[i,j]+50>255):
gray=255
else:
gray=int(grayimage[i,j]+50)
result[i,j]=np.uint8(gray)
#计算原图的直方图
hist=cv2.calcHist([img],[0],None,[256],[0,255])
#计算灰度变换的直方图
hist_res=cv2.calcHist([result],[0],None,[256],[0,255])
#原始图像
plt.figure(figsize=(8,6))
plt.subplot(221),plt.imshow(img,'gray'),plt.title('(a)),plt.axis('off')
#绘制掩膜
plt.subplot(222),plt.plot(hist),plt.title('(b)'),plt.xlable('x'),plt.ylable('y')
#绘制掩膜设置后的图像
plt.subplot(223),plt.imshow(result,'gray'),plt.title('(c)'),plt.axis('off')
#绘制直方图
plt.subplot(224),plt.plot(hist_res),plt.title('(d)'),plt.xlable('x'),plt.ylable('y')
plt.show()
#核心代码展示
for i in range(height):
for j in range(width):
gray=int(grayimage[i,j]*0.8)
result[i,j]=np.uint8(gray)
(3) 图像反色直方图对比DB=255-DA
#核心代码展示
for i in range(height):
for j in range(width):
gray=255-grayimage[i,j]
result[i,j]=np.uint8(gray)
(4) 图像对数变换直方图对比
该算法将增加低灰度区域的对比度,从而增强暗部的细节,使用的表达式为:
DB = c x log(1+DA)
for i in range(height):
for j in range(width):
gray=42*np.log(1.0+grayimage[i,j])
result[i,j]=np.uint8(gray)
(5)图像阈值化处理直方图对比
该算法原型为threshold(Gray,127,255,cv2.THRESH_BINARY),当前像素点的灰度值大于 thresh 阈值时(如 127),其像素点的灰度值设定为最大值(如 9 位灰度值最大为 255);否则,像素点的灰度值设置为 0。二进制阈值化处理及直方图对比的 Python 代码如下所示。
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img=cv2.imread('lena-hd.png')
#图像灰度转换
grayimage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二进制阈值化处理
r,result=cv2.threshold(grayimage,127,255,cv2.THRESH_BINARY)
#计算原图的直方图
hist=cv2.calcHist([img],[0],None,[256],[0,256])
#计算阈值化处理的直方图
hist_res=cv2.calcHist([result],[0],None,[256],[0,256])
#原始图像
plt.figure(figsize=(8,6))
plt.subplot(221),plt.imshow(img,'gray'),plt.title('(a)'),plt.axis('off')
#绘制原始图像直方图
plt.subplot(222),plt.plot(hist),plt.title('(b)'),plt.xlable('x'),plt.ylable('y')
#阈值化处理后的图像
plt.subplot(223),plt.imshow(result,'gray'),plt.title('(c)'),plt.axis('off')
#阈值化处理图像的直方图
plt.subplot(224),plt.plot(hist_res),plt.title('(d)'),plt.xlable('x'),plt.ylable('y')
plt.show()