找到最近的矢量

时间:2010-05-23 18:38:25

标签: python optimization

最近我写了算法来量化RGB图像。每个像素由(R,G,B)矢量表示,并且量化码本是一对三维矢量。需要将图像的每个像素映射到(例如,“替换为”)最接近欧氏距离的码本像素(更准确地说,是欧氏平方)。 我这样做了:

class EuclideanMetric(DistanceMetric):
    def __call__(self, x, y):
        d = x - y
        return sqrt(sum(d * d, -1))

class Quantizer(object):
    def __init__(self, codebook, distanceMetric = EuclideanMetric()):
        self._codebook = codebook
        self._distMetric = distanceMetric

    def quantize(self, imageArray):
        quantizedRaster = zeros(imageArray.shape)

        X = quantizedRaster.shape[0]
        Y = quantizedRaster.shape[1]
        for i in xrange(0, X):
            print i
            for j in xrange(0, Y):
                dist = self._distMetric(imageArray[i,j], self._codebook)
                code = argmin(dist)
                quantizedRaster[i,j] = self._codebook[code]

        return quantizedRaster

......它的功能非常好,我的Pentium Core Duo 2.2 GHz,4 Gigs内存和2600 * 2700像素的图像差不多800秒:(

有没有办法对此进行一些优化?也许是其他算法或某些特定于Python的优化。

UPD :我尝试使用平方欧几里德,但仍然花了很多时间。

3 个答案:

答案 0 :(得分:4)

一个简单的优化是放弃sqrt调用。 x与sqrt(x)是单调的,因为你不需要实际距离,只需要最小距离,而是使用x ^ 2。因为sqrt很贵所以应该有所帮助。

这种技巧在使用距离时会被大量使用。例如,如果您有距离阈值,则可以使用阈值^ 2并在距离计算中删除sqrt。实际上,只有在需要绝对距离时才需要sqrt。对于相对距离,请删除sqrt。

更新:可能需要进行算法更改。现在,您将每个码本矢量与每个像素进行比较。它会加快速度,减少距离计算的次数。

使用kd-tree可能会做得更好,这会减少从O(codebook)到O(log(codebook))的每个像素的搜索。我从来没有在python中做过这个,但是一些谷歌搜索给了一个可能有效的实现here

答案 1 :(得分:1)

您可以使用scipy.cluster.vq中的矢量量化函数vq

答案 2 :(得分:0)

如果X非常大,那么您打印的i相当多,这可能会严重影响性能。如需不太具体的答案,请继续阅读。

为了找出你的过程中的瓶颈在哪里,我建议一个时间装饰器,就像

一样。
from functools import wraps
import time

def time_this(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        finish = time.time()
        elapsed = (finish - start) * 1000
        print '{0}: {1} ms'.format(func.__name__, elapsed)
        return result
    return wrapper

我曾经在某个地方找到过这个,并且一直用它来弄清楚我的代码速度慢的地方。您可以将算法分解为一系列单独的函数,然后使用此装饰器修饰函数以查看每个函数调用需要多长时间。然后,这是一个摆弄哪些语句的函数,以查看改进装饰函数运行时间的函数。主要是你正在寻找两件事:1)需要很长时间才能执行的语句,或者2)执行时间不一定需要很长时间的语句,但这些语句执行的次数很多,性能的改善很小对整体表现影响很大。

祝你好运!