计算机视觉Python与机器学习

数字图像的基本运算

2018-12-22  本文已影响7人  水之心

直方图

直方图简单来说就是图像中每个像素值的个数统计,比如说一副灰度图中像素值为 0 的有多少个,1 的多少个……。直方图是一种分析图片的手段。

Numpy 中直方图计算

其中 ravel() 函数将二维矩阵展平变成一维数组:

from matplotlib import pyplot as plt
import cv2
import numpy as np


def getI(fname, show=False):
    img = plt.imread(fname)
    if show:
        plt.imshow(img)
        plt.show()
    return img


fname = r'E:\Data\URLimg\猫\波斯猫\16.jpg'

img = getI(fname, show=True)
<Figure size 640x480 with 1 Axes>
%%time
hist, bins = np.histogram(img[:,:,0].ravel(), 256, [0, 256])  # 性能:26.5 ms
Wall time: 28.5 ms
%%time
hist = np.bincount(img[:,:,0].ravel(), minlength=256)  # 性能:13 ms
Wall time: 10 ms

画出直方图

fig, ax = plt.subplots(1, 2, figsize=(12, 5))
colors = ['red', 'green', 'blue']


for i in range(3):
    hist, x = np.histogram(img[:, :, i].ravel(), bins=256, range=(0, 256)) # bins 指定统计区间被等分的个数
    ax[0].plot(.5 * (x[:-1] + x[1:]), hist, label=colors[i], color=colors[i])
    
ax[0].legend(loc='upper left')
ax[0].set_xlim(0, 256)
hist2, x2, y2 = np.histogram2d(img[:,:,0].ravel(), img[:,:,2].ravel(), bins=(100, 100), range=[(0,256), (0,256)])
ax[1].imshow(hist2, extent=(0, 256, 0, 256), origin='lower', cmap='gray')
ax[1].set_ylabel('red')
ax[1].set_xlabel('blue')
plt.show()
output_5_0.png

其实 Matplotlib 自带了一个计算并绘制直方图的功能,不需要用到上面的函数:

plt.hist(img[:,:,0].ravel(), 256, [0, 256])
plt.show()
output_7_0.png

OpenCV 中直方图计算

cv2.calcHist(images, channels, mask, histSize, ranges)

%%time
hist = cv2.calcHist([img], [2, 1, 0], None, [30, 20, 10], [0, 256]*3)  # 性能:2.5 ms
Wall time: 3.52 ms
hist.shape
(30, 20, 10)

直方图均衡化

一副效果好的图像通常在直方图上的分布比较均匀,直方图均衡化就是用来改善图像的全局亮度和对比度。其实从观感上就可以发现,前面那幅图对比度不高,偏灰白。

OpenCV 中用 cv2.equalizeHist() 实现均衡化。我们把两张图片并排显示,对比一下:

equ = cv2.equalizeHist(img[:,:,0])

plt.imshow(np.hstack((img[:,:,0], equ)), cmap = 'gray')  # 并排显示
plt.show()
output_12_0.png
fig, ax = plt.subplots(1, 2, figsize=(10, 5))

ax[0].hist(img[:,:,0].ravel(), 256, [0, 256])
ax[0].set_title('Hist')
ax[1].hist(equ.ravel(), 256, [0, 256])
ax[1].set_title('equalizeHist')
plt.show()
output_13_0.png

可以看到均衡化后图片的亮度和对比度效果明显好于原图。不难看出来,直方图均衡化是应用于整幅图片的,这样会模糊掉一部分细节信息。自适应均衡化就是用来解决这一问题的:它在每一个小区域内(默认 8 \times 8)进行直方图均衡化。当然,如果有噪点的话,噪点会被放大,需要对小区域内的对比度进行了限制,所以这个算法全称叫:对比度受限的自适应直方图均衡化CLAHE(Contrast Limited Adaptive Histogram Equalization

自适应均衡化

# 自适应均衡化,参数可选
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
cl1 = clahe.apply(img[:,:,0])

plt.imshow(np.hstack((img[:,:,0], equ, cl1)), cmap = 'gray')  # 并排显示
plt.show()

点运算

即对应元素的四则运算:

# 乘法
plt.imshow(np.hstack([img*i for i in range(1,4)])) 
plt.show()
output_17_0.png
# 除法
plt.imshow(np.hstack([img/i for i in [2, 5, 7]]).astype('B'))
plt.show()
output_18_0.png
# 加法
plt.imshow(np.hstack([img+i for i in [2, 30, 70]]))
plt.show()
output_19_0.png
# 减法
plt.imshow(np.hstack([img-i for i in [2, 50, 70]]).astype('B'))
plt.show()
output_20_0.png
# 组合运算
plt.imshow(np.hstack([img*i-i for i in [2, 50, 70]]).astype('B'))
plt.show()
output_21_0.png
#  指数运算
plt.imshow(np.hstack([np.exp(img*i + 1e-9) for i in [2, 50, 70]]).astype('B'))
plt.show()
output_22_0.png
# 对数运算
plt.imshow(np.hstack([np.log(img*i + 1e-9) for i in [2, 50, 70]]).astype('B'))
plt.show()
output_23_0.png
# 阈值处理
plt.imshow(np.hstack([255*(img < i).astype('B') for i in [50, 150, 200]]))
plt.show()
output_24_0.png
上一篇 下一篇

猜你喜欢

热点阅读