Python:减法时出现溢出问题

3
import cv2
image1 = cv2.imread('one.jpg', 0)
image2 = cv2.imread('two.jpg', 0)
diff   = image1 - image2

对于上面的代码,在某些值时,由于减法而导致溢出。

例如:

238 - 254 = 240

我该怎么做才能防止这种溢出,而得到-16作为答案呢?


有符号整数是否可以作为无符号字节类型? - Pieter21
没错,那是一个无符号字节。 - Pieter21
4
只要使用Python整数作为数值,就不会出现问题。如果涉及到ctypes中的数据类型,如c_short或c_ushort,则可能会出现问题。Python甚至可以自动将整数转换为long类型,或者在数值超出限制时自动使用long类型。 https://docs.python.org/2.4/lib/typesnumeric.html简而言之,我怀疑你并没有完全使用"纯Python"。也许提供一些代码会更有帮助? - Alex Huszagh
代码使用cv2.imread()函数,该函数返回Numpy数组。因此所有必要的信息都在上面的代码中。 - BlackJack
@BlackJack,这是在最近3个小时内添加到示例中的,而我的评论是在那之前发表的。我很高兴她添加了它,这样可以更清楚地解释事情。 - Alex Huszagh
显示剩余3条评论
2个回答

2
在你提供了cv2模块后,这里是优化后的答案。
你的回答显示了问题:
>>> import cv2
>>> img = cv2.imread('myimage.jpg', 0)
>>> img.dtype
dtype('uint8')

这意味着,正如您正确所述,它是一个无符号的8位整数,只能取0-255之间的值。

但是,您可以自动将数组转换为更好的dtype,这比执行int(value)更节省内存。 例如...

>>> img[0][0] 
0
>>> img[0][0] -= 1
>>> img[0][0]
255 # since it's uint8
>>> img[0][0] += 1
>>> img2 = img.astype('uint16')
>>> img2[0][0] -= 1
>>> img2[0][0]
65535 # since it's uint16

您还可以将其转换为除uint8、16、32和64以外的其他类型。例如...

>>> img3 = img2.astype('int64') # signed int64
>>> img3[0][0] -= 7000000
>>> img3[0][0]
-6934465

简而言之,与使用Python内置的类型转换不同,您可以使用NumPy的数据类型手动指定uint8-64和int8-64(以及可能更多),通过指定newarray = array.astype('type')创建紧凑高效的数组,使用新的数据类型。 您还可以指定其他类型,例如“int”,“bool”,“object”等,显示NumPy数组的多功能性和实用性。
要了解有关数据类型及其使用方法的更多信息,请单击此处查看SciPy文档中的链接。

1
上述数字的数据类型是unsigned int8,可以取值范围为0到255。
238 - 254 = -16,由于uint8没有负数的表示方式,所以它给出的答案是240。
相反,将数字转换为int8(-128至127)或int16(-32768至32767)。

1
Nancy,请分享您用于设置此内容的实际代码,包括您正在使用的库。正如@alexanderhuszag所提到的那样,您似乎已经将问题从代码中抽象出来了。未来使用您的库的用户可能会错过解决方案,而没有名称,它可能不适用于其他库的用户。另外,如果您正在使用numpy,则将数字转换为Python整数可能不是最佳解决方案。 - KobeJohn
@kobejohn 我正在使用 cv2 库。cv2.imread() 函数将值作为 uint8 - Nancy
1
感谢您更新问题!现在更清晰了。 - KobeJohn
转换为 int8 仍可能导致溢出或下溢,因为两个无符号8位值之间的最大距离可以是255(或-255)。 - BlackJack
@BlackJack 当然可以。在我的问题中,int8 很好地满足了需求。 - Nancy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接