Python的bug“num”或np.总和"?

2022-05-21 08:41:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写以下代码片段来计算两个图像的相似性:

import cv2, sys                                                                          [5/981]
import numpy as np

def compute_hisgram(path):
    hog = cv2.HOGDescriptor()
    im = cv2.imread(path)
    img_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    h = hog.compute(im)

    return h

def histogram_intersection(h1, h2):
    # minima = np.minimum(h1, h2)
    # intersection = np.true_divide(np.sum(minima), np.sum(h2))
    #return intersection
    return cv2.compareHist(h1, h2, cv2.HISTCMP_INTERSECT)


h1 = compute_hisgram(sys.argv[1])
h2 = compute_hisgram(sys.argv[2])

h12 = histogram_intersection(h1, h2)


# to normalize, we need to divide by the original image.
print (h12/np.sum(h2))

当以两个图像作为输入执行上述代码时,它会输出一个接近1.0的值,这看起来很正常。你知道吗

python3 t.py image1.png image2.png
0.9932124283243112

然而,令我非常惊讶的是,最后一句话是这样写的:

print (h12/sum(h2))

输出不同,是大于1的数字!代码比以前慢了很多。你知道吗

python3 t.py image1.png image2.png
[1.1126189]

这是Pythonsum函数的错误吗?还是我错过了什么?谢谢。你知道吗

==========更新

以下是print (h2)的输出:

[[0.0924307 ]
 [0.05680538]
 [0.07150667]
 ...
 [0.10983132]
 [0.17328948]
 [0.0688285 ]]

h12

4517725.058263534

Tags: 代码returnpngnpsysh2h1cv2sumprintcomputeimintersectionh12hisgram
1条回答
网友
1楼 ·

这些函数的求和方式不同。 示例:

a = np.full((9000,), 1/9000)
sum(a)
# 0.9999999999998027
np.sum(a)
# 0.9999999999999999
math.fsum(a)
# 1.0

所以呢np.总和()给出的结果比sum()更准确。你知道吗

请参见fsum了解一些解释:

math.fsum(iterable)

Return an accurate floating point sum of values in the iterable. Avoids loss of precision by tracking multiple intermediate partial The algorithm’s accuracy depends on IEEE-754 arithmetic guarantees and the typical case where the rounding mode is half-even. On some non-Windows builds, the underlying C library uses extended precision addition and may occasionally double-round an intermediate sum causing it to be off in its least significant bit.

For further discussion and two alternative approaches, see the ASPN cookbook recipes for accurate floating point summation.


您可能还想看看accupy。关于不同求和方法的精确度,有一些非常有用的图表。

下面是一个真正的病理例子(取自here),显然准确的结果正好是20000:

a = [1, 1e100, 1, -1e100] * 10000
math.fsum(a), np.sum(a), sum(a)
# (20000.0, 0.0, 0.0)