目录
- 一:模拟计算图像直方图和累计直方图
- 二:计算图像的均值、标准差、相关系数和协方差
- 三:利用模板进行卷积运算
- 四:获取彩色图像的直方图
- 五:图像直方图均衡化
一:模拟计算图像直方图和累计直方图
① 调用的python工具包:
② 利用生成随机数的函数生成一个256*256的二位数组模拟图像的灰度值的排列:
③ 遍历影像中的每一个像元的像元值,将其存为一个一维数组并进行排序:
④ 由于空值通常用-3.4028235e+38表达,避免错误统计需要提前剔除(利用数组切片的方法:
⑤ 绘制灰度直方图:
import numpy as np import matplotlib.pyplot as plt im_data = np.random.randint(low=0, high=256, size=256 * 256) im_data.shape = 256, 256 print(im_data.shape) # ##########显示灰度直方图######## # 遍历影像中的每一个像元的像元值 data = [] for i in range(im_data.shape[0]): for j in range(im_data.shape[1]): # print(j) data.append(im_data[i][j]) data.sort() # 统计最大最小值 data = np.array(data) print(data.min(), data.max()) # 由于空值通常用-3.4028235e+38表达,避免错误统计需要提前剔除 a = sum(data == 0) print(a) print(data.shape) data = data[a:] # 切片,即a[1:]相当于a[1:len(data)] # 根据影像中最大最小值设定坐标轴 bins = np.linspace(start=0, stop=256, num=256) # 绘制直方图,设定直方图颜色 plt.hist(data, bins, facecolor="black") # 横坐标轴名称 plt.xlabel('像元值') # 纵坐标轴名称 plt.ylabel('频数') # 图表头名称 plt.title('灰度分布直方图') # 显示中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 展现绘制得到的图片 plt.show() # 导出绘制得到的图片 # plt.savefig('C:/test2.jpg') band1_data = im_data
运行结果:
⑥ 绘制累计灰度直方图(只需将hist函数的cumulative参数设置为True):
运行结果:
(因为是随机生成数组,所以灰度值都分布比较均匀)
二:计算图像的均值、标准差、相关系数和协方差
① 在题目一的基础上利用相关函数可直接计算均值与标准差:
运行结果:
② 计算协方差矩阵和相关系数矩阵
a.先定义一个原始列表(模拟将图像灰度值矩阵转为数组后的数据形式),然后再计算其平均值:
b.再定义一个列表与原始列表结合,计算其协方差矩阵:
c. 再定义一个列表与原始列表结合,计算其相关系数矩阵:
origin_list = [[1, 0, 1, 0], [1, 0, 1, 0], [0, 1, 0, 1], [1, 0, 0, 1]] index_1 = 0 avg = [0, 0, 0, 0] for li in origin_list: for num in li: avg[index_1] += num/len(li) index_1 += 1 print('各个平均数: ', avg) xiefangcha = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] i = -1 for li_1 in origin_list: i += 1 j = -1 for li_2 in origin_list: j += 1 for num_1, num_2 in zip(li_1, li_2): xiefangcha[i][j] += (num_1 - avg[i])*(num_2 - avg[j])/3 print('协方差矩阵: ', xiefangcha) xiangguanjuzheng = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] i = 0 for xie in xiefangcha: j = 0 for xi in xie: xiangguanjuzheng[i][j] = xi/((xiefangcha[i][i]**0.5)*(xiefangcha[j][j]**0.5)) j += 1 i += 1 print('相关矩阵: ', xiangguanjuzheng)
结果输出:
各个平均数: [0.5, 0.5, 0.5, 0.5] 协方差矩阵: [[0.3333333333333333, 0.3333333333333333, -0.3333333333333333, 0.0], [0.3333333333333333, 0.3333333333333333, -0.3333333333333333, 0.0], [-0.3333333333333333, -0.3333333333333333, 0.3333333333333333, 0.0], [0.0, 0.0, 0.0, 0.3333333333333333]] 相关矩阵: [[1.0, 1.0, -1.0, 0.0], [1.0, 1.0, -1.0, 0.0], [-1.0, -1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
三:利用模板进行卷积运算
① 定义图像与模板
② 进行卷积运算的方法
③ 参数的传入与结果输出
import numpy as np # 定义图像与模板 input_data = [ [[1, 1, 7, 1, 8, 1, 7, 1, 1], [1, 1, 1, 1, 5, 1, 1, 1, 1], [1, 1, 1, 5, 5, 5, 1, 1, 7], [7, 1, 1, 5, 5, 5, 1, 1, 1], [1, 1, 1, 5, 5, 5, 1, 8, 1], [1, 8, 1, 1, 5, 1, 1, 1, 1], [1, 8, 1, 1, 5, 1, 1, 8, 1], [1, 1, 1, 1, 5, 1, 1, 1, 1], [1, 1, 7, 1, 8, 1, 7, 1, 1]], ] weights_data = [ [[0, -1, 0], [-1, 4, -1], [0, -1, 0]], ] def compute_conv(fm, kernel): [h, w] = fm.shape [k, _] = kernel.shape r = int(k / 2) # 保存计算结果 rs = np.zeros([h - 2, w - 2], np.float32) # 将输入在指定该区域赋值,即除了4个边界后,剩下的区域 # 对每个点为中心的区域遍历 for i in range(1, h - 1): for j in range(1, w - 1): # 取出当前点为中心的k*k区域 roi = fm[i - 1:i + r + 1, j - 1:j + r + 1] # 计算当前点的卷积,对k*k个点点乘后求和 rs[i - 1][j - 1] = np.sum(roi * kernel) return rs def my_conv2d(input, weights): [c, h, w] = input.shape [_, k, _] = weights.shape outputs = np.zeros([h - 2, w - 2], np.float32) # 对每个feature map遍历,从而对每个feature map进行卷积 for i in range(c): # feature map==>[h,w] f_map = input[i] # kernel ==>[k,k] w = weights[i] rs = compute_conv(f_map, w) outputs = outputs + rs return outputs def main(): # shape=[c,h,w] input = np.asarray(input_data, np.float32) # shape=[in_c,k,k] weights = np.asarray(weights_data, np.float32) rs = my_conv2d(input, weights) print(rs) if __name__ == '__main__': main()
运行结果(未输出边缘的像素值):
[[ 0. -6. -8. 5. -8. -6. 0.] [ 0. -4. 8. 0. 8. -4. -6.] [ -6. -4. 4. 0. 4. -4. -7.] [ -7. -4. 8. 0. 8. -11. 28.] [ 21. -7. -8. 8. -8. 0. -14.] [ 21. -7. -4. 8. -4. -7. 28.] [ -7. -6. -4. 5. -4. -6. -7.]]
四:获取彩色图像的直方图
这里用到的是PIL(Python Imaging Library)库,Python平台的图像处理标准库。
① 导入用到的相关的包:
②读入一张彩色tif图像,并分割RGB三种色彩:
③要对图像求直方图,就需要先把图像矩阵进行flatten操作,使之变为一维数组,然后再进行统计,分别提取R\G\B统计值,进行分区绘图:
④相关显示设置,显示原图像:
from PIL import Image import numpy as np import matplotlib.pyplot as plt img = Image.open(r"D:\数据\影像test.tif") r, g, b = img.split() # 分离R\G\B # 要对图像求直方图,就需要先把图像矩阵进行flatten操作,使之变为一维数组,然后再进行统计 # 分别提取R\G\B统计值,叠加绘图 fig = plt.figure("ImageHist") fig.add_subplot(2, 2, 1) ar = np.array(r).flatten() plt.hist(ar, facecolor='red', bins=256, edgecolor='red', ) # 横坐标轴名称 plt.xlabel('像元值') # 纵坐标轴名称 plt.ylabel('频数') # 图表头名称 plt.title('R 灰度分布直方图') fig.add_subplot(2, 2, 2) ag = np.array(g).flatten() plt.hist(ag, bins=256, facecolor='green', edgecolor='green', ) # 横坐标轴名称 plt.xlabel('像元值') # 纵坐标轴名称 plt.ylabel('频数') # 图表头名称 plt.title('G 灰度分布直方图') fig.add_subplot(2, 2, 3) ab = np.array(b).flatten() plt.hist(ab, bins=256, facecolor='blue', edgecolor='blue', ) # 横坐标轴名称 plt.xlabel('像元值') # 纵坐标轴名称 plt.ylabel('频数') # 图表头名称 plt.title('B 灰度分布直方图') ax = fig.add_subplot(2, 2, 4) plt.imshow(img) # 显示中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 调整子图组合及子图之间的位置与间距 plt.subplots_adjust(left=0.1, right=0.9, hspace=0.5, wspace=0.3) plt.show()
运行显示结果如下图:
五:图像直方图均衡化
直方图均衡化的基本原理是:对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而增大对比度,使图像清晰,达到增强的目的。
这里用到了openCV图像处理库,核心代码主要思路为:遍历图像每个像素的灰度,算出每个灰度的概率(n/MN-n是每个灰度的个数,MN是像素总数),用L-1乘以所得概率得到新的灰度:
import cv2 import numpy as np img = cv2.imread("img.tif") img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 直方图统计 def pix_gray(img_gray): h = img_gray.shape[0] w = img_gray.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_gray[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 hist_gray(img_gary): h, w = img_gary.shape gray_level2 = pix_gray(img_gray) 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 = cv2.LUT(img_gray, lut) return out cv2.imshow('input', img_gray) out_img = hist_gray(img_gray) cv2.imshow('output', out_img) cv2.waitKey(0) # cv2.destroyWindow()
再利用前面同样的方法绘制原图与均衡化后的直方图,进行对比,如下图,可以看出均衡化后的图像的对比度得到了增强:
…
学习遥感数字图像处理中做的一些的编程练习。
借鉴参考:
【Python图像处理】图片读取/提取直方图
。。。。