[英]Segmentation using maximum likelihood algorithm on images using python
我想使用在python中实现的最大似然算法执行图像分割。 类的均值向量和协方差矩阵是已知的,并且可以在图像上进行迭代(很大... 5100X7020),我们可以为每个像素计算成为给定类的一部分的概率。
只需用Python编写
import numpy as np
from numpy.linalg import inv
from numpy.linalg import det
...
probImage1 = []
probImage1Vector = []
norm = 1.0 / (np.power((2*np.pi), i/2) * np.sqrt(np.linalg.det(covMatrixClass1)))
covMatrixInverz = np.linalg.inv(covMatrixClass1)
for x in xrange(x_img):
for y in xrange(y_img):
X = realImage[x,y]
pixelValueDifference = X - meanVectorClass1
mult1 = np.multiply(-0.5,np.transpose(pixelValueDifference))
mult2 = np.dot(covMatrixInverz,pixelValueDifference)
multMult = np.dot(mult1,mult2)
expo = np.exp(multMult)
probImage1Vector.append(np.multiply(norm,expo))
probImage1.append(probImage1Vector)
probImage1Vector = []
这个代码在大图像上执行时速度很慢的问题...矢量减法和乘法之类的计算会消耗大量时间,即使它们只是1X3矢量。
您能否提示如何加快此代码的速度? 我真的很感激。 抱歉,如果我不清楚,我仍然是python的初学者。
仔细看看:
mult1 = np.multiply(-0.5,np.transpose(pixelValueDifference))
mult2 = np.dot(covMatrixInverz,pixelValueDifference)
multMult = np.dot(mult1,mult2)
我们看到该操作基本上是:
A.T (d) C (d) A # where `(d)` is the dot-product
这三个步骤可以很容易地表示为np.einsum
一个字符串符号,就像这样-
np.einsum('k,lk,l->',pA,covMatrixInverz,-0.5*pA)
在两个迭代器i(=x)
和j(=y)
执行此操作,我们将得到一个完全矢量化的表达式-
np.einsum('ijk,lk,ijl->ij',pA,covMatrixInverz,-0.5*pA))
或者,我们可以使用np.tensordot
减少的第一部分-
mult2_vectorized = np.tensordot(pA, covMatrixInverz, axes=([2],[1]))
output = np.einsum('ijk,ijk->ij',-0.5*pA, mult2_vectorized)
将所有方法列为功能-
# Original code posted by OP to return array
def org_app(meanVectorClass1, realImage, covMatrixInverz, norm):
probImage1 = []
probImage1Vector = []
x_img, y_img = realImage.shape[:2]
for x in xrange(x_img):
for y in xrange(y_img):
X = realImage[x,y]
pixelValueDifference = X - meanVectorClass1
mult1 = np.multiply(-0.5,np.transpose(pixelValueDifference))
mult2 = np.dot(covMatrixInverz,pixelValueDifference)
multMult = np.dot(mult1,mult2)
expo = np.exp(multMult)
probImage1Vector.append(np.multiply(norm,expo))
probImage1.append(probImage1Vector)
probImage1Vector = []
return np.asarray(probImage1).reshape(x_img,y_img)
def vectorized(meanVectorClass1, realImage, covMatrixInverz, norm):
pA = realImage - meanVectorClass1
mult2_vectorized = np.tensordot(pA, covMatrixInverz, axes=([2],[1]))
return np.exp(np.einsum('ijk,ijk->ij',-0.5*pA, mult2_vectorized))*norm
def vectorized2(meanVectorClass1, realImage, covMatrixInverz, norm):
pA = realImage - meanVectorClass1
return np.exp(np.einsum('ijk,lk,ijl->ij',pA,covMatrixInverz,-0.5*pA))*norm
时间-
In [19]: # Setup inputs
...: meanVectorClass1 = np.array([23.96000000, 58.159999, 61.5399])
...:
...: covMatrixClass1 = np.array([[ 514.20040404, 461.68323232, 364.35515152],
...: [ 461.68323232, 519.63070707, 446.48848485],
...: [ 364.35515152, 446.48848485, 476.37212121]])
...: covMatrixInverz = np.linalg.inv(covMatrixClass1)
...:
...: norm = 0.234 # Random float number
...: realImage = np.random.rand(1000,2000,3)
...:
In [20]: out1 = org_app(meanVectorClass1, realImage, covMatrixInverz, norm )
...: out2 = vectorized(meanVectorClass1, realImage, covMatrixInverz, norm )
...: out3 = vectorized2(meanVectorClass1, realImage, covMatrixInverz, norm )
...: print np.allclose(out1, out2)
...: print np.allclose(out1, out3)
...:
True
True
In [21]: %timeit org_app(meanVectorClass1, realImage, covMatrixInverz, norm )
1 loops, best of 3: 27.8 s per loop
In [22]: %timeit vectorized(meanVectorClass1, realImage, covMatrixInverz, norm )
1 loops, best of 3: 182 ms per loop
In [23]: %timeit vectorized2(meanVectorClass1, realImage, covMatrixInverz, norm )
1 loops, best of 3: 275 ms per loop
看起来完全矢量化的einsum + tensordot
混合解决方案做得很好!
为了进一步提高性能,还可以考虑使用numexpr
模块来加速大型数组上的exponential
计算。
第一步,我将摆脱不必要的函数调用,例如转置,点和乘法。 这些都是您应该内联进行的简单计算。 当您真正看到自己在做什么时,与其将其隐藏在函数内部,不如将其理解为性能问题。
这里的根本问题是,这似乎至少是四次复杂度运算。 您可能想简单地将所有循环中要执行的操作数相乘。 是5亿,20亿,3500亿? 多少?
要控制性能,您需要了解您正在执行多少指令。 现代计算机每秒可以执行约10亿条指令,但是如果涉及内存移动,则速度可能会大大降低。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.