在这里我将以分辨率为590*326的图片hua.jpg来作为演示图片,如下图,是一个拿着战矛的机甲风人物。为了方便下面我将其称为“小花”
将图像读入Numpy的数组对象后,可以对其进行数学操作。
首先导入必备的numpy和cv2
import numpy as np
import cv2
#读取图片
pic = cv2.imread('hua.jpg')
#使用numpy中的array方法将图片以数组形式读取
arr = np.array(data)
#读取图片的shape值(为一个元组)
pic_shape = arr.shape
print(arr)
print(pic_shape)
运行后可以看到图片小花的矩阵和它的形状(326, 590, 3),shape为一个数组
其中326为图像的宽度,590为图像的长度,3代表这个图像有三个通道RGB
from PIL import Image
import numpy as np
pic_arrL = np.array(Image.open('hua.jpg').convert('L'))
print(pic_arrL)
convert('L')
为灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
原型
[[[41 23 46]
[41 23 46]
[41 23 46]
...
[37 10 30]
[37 10 30]
[37 10 30]]
[[40 22 45]
[40 22 45]
[40 22 45]
...
灰度处理后
[[32 32 32 ... 19 19 19]
[31 31 31 ... 19 19 19]
[31 31 31 ... 19 19 19]
...
[18 18 18 ... 11 11 11]
[18 18 18 ... 11 11 11]
[18 18 19 ... 11 11 11]]
设任意函数f,它将0~255映射到自身(输出区间和输入区间相同)那么对载入的图像实现不同级别的灰度变换则可以通过设定函数f来进行实现
from PIL import Image
import numpy as np
from pylab import *
# 灰度图像
# f(x) = 255 - x
pic_arrL = np.array(Image.open('hua.jpg').convert('L'))
# 输出最大最小值以确定图像像素范围
print('对图像进行反向处理:\n', int(pic_arrL.min()),int(pic_arrL.max()))
# f(x) = (100/255)x + 100
im1 = (100.0/255) *pic_arrL +100 # 将图像想阻止控制在100~200
print('将图像像素值变换到100...200区间:\n', int(im1.min()),int(im1.max()))
# f(x) = 255*(x/255)^2
im2 = 255.0 * (pic_arrL/255.0) ** 2 # 对像素值求平方后得到的图像
print('对像素值求平方后得到的图像:\n', int(im2.min()),int(im2.max()))
# 图像展示
# pic_arrL
figure()
gray()
subplot(131)
imshow(pic_arrL)
axis('off')
title(r'$f(x) = 255 - x$')
# im1
subplot(132)
imshow(im1)
axis('off')
title(r'$f(x) = \frac{100}{255}x + 100 $')
# im2
subplot(133)
imshow(im2)
axis('off')
title(r'$f(x) = 255(\frac{x}{255})^2 $')
show()
定义完公式后对图像进行运算,最终通过 pylab 库的方法将图像展示,其中title利用latex语法进行公式的呈现。如下图,将小花不同程度的灰度图展现了出来。
指将一副图像的灰度直方图变平,使得变换后的图像中每个灰度值的分布概率都相同。
作用:将灰度值归一化;可以增强图像的对比度。
首先需要导入的工具包有
其中PCV导入时若遇到导入后不能使用的问题,则需进入其github官网进行下载 https://github.com/jesolem/PCV ,如github速度很慢可以使用csdn的gitcode镜像进入。
注意:不使用PCV来进行图像直方图均衡化请往下看
mirrors / jesolem / pcv · GitCode
在PCV目录下打开终端输入命令:python setup.py install
结果会发现报错,原因在于有很多文件中有着python2版本中的print,需将其改为python3的格式(加一对小括号)
如图如果在pycharm中运行可以直接点进文件链接进行跳转,并修改。例如此条:
改为如下
print (imname + "...skipped" )
但是由于PCV这个包已经八九年没有更新了,对于python3来说属实不太友好,这里采用自己定义好的直方图均衡化的函数
from PIL import Image
from pylab import *
# 添加中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']
hua = array(Image.open('hua.jpg').convert('L'))
def histeq(im,nbr_bins=256):
"""对一副灰度图像进行直方图均衡化"""
imhist,bins = histogram(im.flatten(),nbr_bins,normed = True)
# 累计分布函数
cdf = imhist.cumsum()
# 归一化(概率分布)
cdf = 255*cdf/cdf[-1]
# 线性插值
im2 =interp(im.flatten(),bins[:-1],cdf)
return im2.reshape(im.shape),cdf
im2,cdf = histeq(hua,256)
figure()
subplot(2,2,1)
axis('off')
gray()
title(u'原始图像')
imshow(hua)
subplot(2,2,2)
axis('off')
gray()
title(u'直方图均衡化后图像')
imshow(im2)
subplot(2,2,3)
axis('off')
title(u'原始直方图')
hist(hua.flatten(),128,density=True)
subplot(2,2,4)
axis('off')
title(u'均衡化后的直方图')
hist(im2.flatten(),128,density=True)
show()
运行程序效果如下,小花的原始的图像直方图为“左高右低”。均衡化处理过后小花的图像直方图的分布变得平均了
import cv2 as cv
import numpy as np
# 图像显示
def picShow(pic_title, pic_data):
cv.imshow(pic_title, pic_data)
cv.waitKey(0)
cv.destroyAllWindows()
def pixGray(img): # 直方图统计
h = img.shape[0]
w = img.shape[1]
gray_level = np.zeros(256)
gray_level2 = np.zeros(256)
for i in range(1, h - 1):
for j in range(1, w - 1):
gray_level[img[i, j]] += 1 # 统计灰度级为img_gray[i,j]的个数
for i in range(1, 256):
gray_level2[i] = gray_level2[i - 1] + gray_level[i] # 统计灰度级小于img_gray[i,j]的个数
return gray_level2
def imgEqualize(img): # 直方图均衡化
h, w = img.shape
gray_level2 = pixGray(img)
lut = np.zeros(256)
for i in range(256):
lut[i] = 255.0 / (h * w) * gray_level2[i] # 得到新的灰度级
lut = np.uint8(lut + 0.5)
out = cv.LUT(img, lut)
print('图像直方图均衡化 处理完毕')
return out
if __name__ == "__main__":
pic = cv.imread('hua.jpg', 0)
title = 'mulan'
picture = np.hstack((pic, imgEqualize(pic)))
picShow(title, picture)
运行结果如图: