第一次写文章,dalao轻喷1551
最近在写一个计算图像联合熵的算法,遇到了一个问题,那就是如何高效统计出两幅图像相同位置的数对出现的概率。for遍历太慢,而在项目存在单元数以百万计大小的大数组时,切片算法加联合灰度矩阵都显得缓慢了起来。于是想写一种使用pandas库新算法统计数对个数。
但是pandas库的扫描无论是几维数组似乎都是扫描最小的单个元素(如有误请指正),并没有看到对比多维数组每一行的方法或者一次扫描多个元素的方法。这个时候,我采用了一种等效改变进制的方法,将一行的多个元素合并成了一个数,这样就将多列数转换成了一列数,就可以利用pandas库进行统计计算了。
代码如下:
import pandas as pd
import numpy as np
M1 = M1.reshape(2, (M1.shape[1] * M1.shape[2]))
# 展开每一层到一维,重构多层二维数组到单层二维数组,M1,M2均为ndarray
M1 = M1.T
#反转两行到两列,此处看M1的形状而定
M2 = M1[::, 0] * (np.max(M1[::, 1]) + 1) + M1[::, 1]
#最关键的一步,将两列二维数组转换为一维数组,此处的np.max(M1[::, 1])即为M1第二列到第一列的“进制”
s = pd.Series(M2)
Mhist = s.value_counts(normalize=True)
#此处统计出来的是数对对应的个数,如需还原成原数组使用余数操作即可
例如如果两列数组的第一列最大值是39,则可以将40作为第二列到第一列的“进制”,相当于把两列数转换成了一个40进制数,如果有更高位的数,每一级的进制只需要将之前所有级的进制累乘即可。如果数位过多,导致最后数字溢出浮点数的最大范围,则可以将此数组的每一行转换成一个字符串,如一行[14,47,70,76,62,24,46,68,80,95,51,26,48,95,26,73,84]可转换为字符串‘14,47,70,76,62,24,46,68,80,95,51,26,48,95,26,73,84’再进行统计。
这个方法能省去多列浮点数所需的内存,对电脑算法速度有很大改善,比纯numpy统计快10倍,比for循环遍历快50倍,如果有更好的办法可以写在评论区,共同学习