繁体   English   中英

Python、OpenCV:在不溢出 UINT8 数组的情况下增加图像亮度

[英]Python, OpenCV: Increasing image brightness without overflowing UINT8 array

我正在尝试增加灰度图像的亮度。 cv2.imread()返回一个 numpy 数组。 我正在向数组的每个元素添加整数值。 从理论上讲,这会增加它们中的每一个。 之后,我将能够设置 255 的上限阈值并获得更高亮度的图像。

这是代码:

grey = cv2.imread(path+file,0)

print type(grey)

print grey[0]

new = grey + value

print new[0]

res = np.hstack((grey, new))

cv2.imshow('image', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

但是, numpy 添加显然是这样做的:

new_array = old_array % 256

每个高于 255 的像素强度值都成为除以 256 的余数。

结果,我变黑而不是完全变白。

这是输出:

<type 'numpy.ndarray'>
[115 114 121 ..., 170 169 167]
[215 214 221 ...,  14  13  11]

这是图像:

在此处输入图片说明

我怎样才能关闭这个余数机制? 有没有更好的方法来增加 OpenCV 的亮度?

一种想法是在添加value之前通过检查255和当前像素值之间的差异并检查它是否在value内来检查添加是否会导致溢出。 如果是,我们不会添加value ,我们会直接将它们设置为255 ,否则我们将进行添加。 现在,可以通过创建掩码来简化此决策,并且 -

mask = (255 - grey) < value

然后,将此掩码/布尔数组提供给np.where ,让它根据掩码在255grey+value之间进行选择。

因此,最后我们将实现为 -

grey_new = np.where((255 - grey) < value,255,grey+value)

样品运行

我们用一个小的有代表性的例子来演示这些步骤。

In [340]: grey
Out[340]: 
array([[125, 212, 104, 180, 244],
       [105,  26, 132, 145, 157],
       [126, 230, 225, 204,  91],
       [226, 181,  43, 122, 125]], dtype=uint8)

In [341]: value = 100

In [342]: grey + 100 # Bad results (e.g. look at (0,1))
Out[342]: 
array([[225,  56, 204,  24,  88],
       [205, 126, 232, 245,   1],
       [226,  74,  69,  48, 191],
       [ 70,  25, 143, 222, 225]], dtype=uint8)

In [343]: np.where((255 - grey) < 100,255,grey+value) # Expected results
Out[343]: 
array([[225, 255, 204, 255, 255],
       [205, 126, 232, 245, 255],
       [226, 255, 255, 255, 191],
       [255, 255, 143, 222, 225]], dtype=uint8)

对示例图像进行测试

使用问题中发布的示例图像为我们提供arr并使用value作为50 ,我们将 -

在此处输入图片说明

这是另一种选择:

# convert data type
gray = gray.astype('float32')

# shift pixel intensity by a constant
intensity_shift = 50
gray += intensity_shift

# another option is to use a factor value > 1:
# gray *= factor_intensity

# clip pixel intensity to be in range [0, 255]
gray = np.clip(gray, 0, 255)

# change type back to 'uint8'
gray = gray.astype('uint8)

简而言之,您应该为每个值添加 50,找到maxBrightness ,然后thisPixel = int(255 * thisPixel / maxBrightness)

您必须检查每个像素是否溢出。 Divakar 建议的方法简单快捷。 您实际上可能希望增加(在您的情况下为 50)每个值,然后将其标准化为 255。这将保留图像明亮区域的细节。

使用 OpenCV 的功能。 他们实施“饱和”数学。

new = cv.add(grey, value)

cv.add文档

当你只写new = grey + value ,那不是 OpenCV 做的工作,那是 numpy 做的工作。 numpy 没有什么特别的。 整数环绕是标准行为。

对我来说有效的另一种方法是使用 PIL>Image 库中的混合函数将白色图像“混合”到原始图像中。

from PIL import Image
correctionVal = 0.05 # fraction of white to add to the main image
img_file = Image.open(location_filename)
img_file_white = Image.new("RGB", (width, height), "white")
img_blended = Image.blend(img_file, img_file_white, correctionVal)

img_blended = img_file * (1 - correctionVal) + img_file_white * correctionVal

因此,如果 CorrectVal = 0,我们得到原始图像,如果 CorrectVal = 1,我们得到纯白色。

此功能对超过 255 的 RGB 值进行自我校正。

混合黑色 (RGB 0, 0, 0) 会降低亮度。

我遇到了类似的问题,但不是加法,而是以非均匀方式缩放图像像素。

这个的一维版本:

a=np.array([100,200,250,252,255],dtype=np.uint8)
scaling=array([ 1.1,  1.2,  1.4,  1.2,  1.1])
result=np.uint8(a*scaling)

当然,这会给您带来溢出问题; 结果:

array([110, 240,  94,  46,  24], dtype=uint8)

np.where 有效:

result_lim=np.where(a*scaling<=255,a*scaling,255)

产生 result_lim 为:

array([ 110.,  240.,  255.,  255.,  255.])

我想知道时间,我在 4000 x 6000 图像(而不是一维数组)上进行了这个测试,发现 np.where() 至少在我的条件下,花费了大约 2.5 倍的时间。 不知道是否有更好/更快的方法来做到这一点。 如上所述,转换为浮点数、执行操作然后进行裁剪的选项比 np.where() 方法要慢一些。

不知道有没有更好的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM