归一化图像返回---> OverflowError:无法将浮点无穷大转换为整数

时间:2020-07-07 18:07:17

标签: python numpy opencv image-processing normalization

下面是我编写的python代码,用于对图像进行规范化并使其照度不变。 对于图像的每个像素,新像素值应为(R/sum,G/sum,B/sum),其中sum=R+G+B

import numpy as np
import cv2 


img=cv2.imread(r'C:/Users/kjbaili/.spyder-py3/color_supression_RV/rub00.jpg')


print(img[200,200])
print(img[200,200,0])

def normalized(down):

    norm_img = np.zeros(down.shape, down.dtype)
    

    width,height,channels=down.shape
    
    for y in range(0,height):
        for x in range(0,width):
              sum=down[x,y,0]+down[x,y,1]+down[x,y,2]
             
              b=(down[x,y,0]/ sum)*255
              g=(down[x,y,1]/ sum)*255
              r=(down[x,y,2]/ sum)*255
            
            
              norm_img[x,y,0]= b
              norm_img[x,y,1]= g
              norm_img[x,y,2]= r
              
    return norm_img


image=normalized(img)


cv2.imshow('normalized',image)


cv2.waitKey(0)
cv2.destroyAllWindows()

但是,出现以下错误:

OverflowError: cannot convert float infinity to integer

尽管,我在这里找到了与此相关的类似回答问题,但是由于我不知道哪个值带来无限的价值,所以我无法将其投射到我的问题上。

很高兴获得帮助

预先感谢

1 个答案:

答案 0 :(得分:3)

您的访问索引已切换。您应该进行down[y,x,0]等操作,而不是down[x,y,0]。但是,我怀疑您访问这里没有遇到任何错误,因为图像是方形的。此外,与完全浮点精度相比,将三个数字加在一起的精度有限时,值将溢出。例如,将200 + 100 + 50添加到无符号的8位整数中将得到350 % 256 = 94。无限结果中可能发生的情况是,要么您的像素全都是黑色,所以归一化会导致被0除的错误,或者三个值的总和溢出,使您获得0的值,再次得到该结果。

您可以做的是进行完整性检查,以确保如果三个通道的总和不等于0,则执行归一化。另外,您将需要更改精度,以便求和后可以处理更高的值。

换句话说:

def normalized(down):

    norm_img = np.zeros(down.shape, down.dtype)
    

    width,height,channels=down.shape
    
    for y in range(0,height):
        for x in range(0,width):
              sum=float(down[y,x,0])+float(down[y,x,1])+float(down[y,x,2])  # Change
              
              if sum > 0:  # Change
                  b=(down[y,x,0]/ sum)*255.0   # Change
                  g=(down[y,x,1]/ sum)*255.0
                  r=(down[y,x,2]/ sum)*255.0
            
                  norm_img[y,x,0]= b  # Should cast downwards automatically
                  norm_img[y,x,1]= g
                  norm_img[y,x,2]= r
              
    return norm_img

这当然是非常低效的,因为您要遍历单个像素,而没有利用体现NumPy数组的矢量化的优势。简而言之,使用numpy.sum并沿第三维进行求和,然后将每个通道除以相应的数量:

def normalized(down):
    sum_img = np.sum(down.astype(np.float), axis=2)
    sum_img[sum_img == 0] = 1
    return (255 * (down.astype(np.float) / sum_img[...,None])).astype(down.dtype)

第一行计算一个2D数组,其中每个位置沿通道维度求和,从而为您提供每个空间位置的RGB值之和。我也将类型提升为浮点数以在规范化时保持精度。接下来,在第二行代码中进行中间检查,以确保不存在被零除的错误,因此任何像素为0时,我们将其哨兵值设置为1,以使除法结果为0。之后,我们获取输入图像,并将每个相应的RGB像素除以相应空间位置处的和。请注意,我已经使用广播,以便将2D sum数组制作为具有单个第三通道的3D数组,以使广播正常工作。最后,我将其乘以255,就像您在先前版本中所做的一样。我还要确保将最终结果转换为函数中的传入类型。

为了更加简洁,您可以通过在第三个维度求和后使用keepdims的{​​{1}}参数来保持单例维度来进一步简化此操作。这样可以避免手动插入单例尺寸:

numpy.sum