Practical Python and OpenCV,3rd Edition 05

图像算术(image arithmetic)

我们都知道基本的算术运算,如加法和减法。但是在处理图像时,我们需要记住颜色空间和数据类型的限制。

例如,RGB图像具有落在[0,255]范围内的像素。那么如果我们正在检查强度为250的像素并尝试向它添加10,会发生什么?

在正常的算术规则下,我们最终得到的值为260.但是,由于RGB图像表示为8位无符号整数,因此260不是有效值。

那么,会发生什么?我们是否应该执行某种检查以确保没有像素落在[0,255]范围之外,从而将所有像素剪切为最小值0和最大值255?

或者我们应用模数运算,并“wrap around(环绕)”?在模数规则下,添加10到250将简单地回绕到值4。

哪种方式是处理超出[0,255]范围的图像添加和减法的“正确”方法?

答案是没有正确的方法——它只取决于你如何操纵像素以及你想要的结果。

但是,请务必记住OpenCV和NumPy加法之间存在差异。NumPy将执行模运算和“warp around”。另一方面,OpenCV将执行裁剪并确保像素值永远不会超出范围[0,255]

请看代码:

from __future__ import print_function
import numpy as np
import argparse
import cv2
ap = argparse.ArgumentParser()
ap.add_argument('-i',"--image",required=True,
help="path to the image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
cv2.imshow("Original",image)
print("max of 255: {}".format(cv2.add(np.uint8([200]),np.uint8([100]))))
print("min of 0: {}".format(cv2.add(np.uint8([50]),np.uint8([100]))))
print("wrap around: {}".format(np.uint8([200]) + np.uint8([100])))
print("wrap around: {}".format(np.uint8([50]) - np.uint8([100])))

解释

第一个print函数,我们定义了两个8位无符号整数的NumPy数组。第一个数组有一个元素:值为200.第二个数组也只有一个元素,但值为100.然后我们使用OpenCV的cv2.add方法将值一起添加。那么返回的值到底回事多少呢?那么,根据标准算术规则,我们认为结果应该是300,但是,请记住,我们正在使用8位无符号整数,其范围仅在[0,255]之间。由于我们使用的是cv2.add方法,OpenCV会为我们处理剪切,并确保添加产生的最大值为255.当我们执行此代码时,我们可以看到返回值是255。

第二个print函数,我们使用cv2.subtract执行减法。同样,我们定义了两个NumPy数组,每个数组都有一个元素,以及8位无符号整数数据类型。第一个数组的值为50,第二个数组的值为100。根据算术规则,返回值本该是-50,但是OpenCV再一次为我们进行裁剪,返回值会是0.

max of 255: [[255]]

min of 0: [[0]]

但是如果我们使用NumPy来执行算术而不是OpenCV会发生什么?

第三个print函数,首先,我们定义两个NumPy数组,每个数组都有一个元素,以及8位无符号整数数据类型。 第一个数组的值为200,第二个数组的值为100.使用cv2.add函数,我们的添加将被剪切并返回值255。但是Numpy并不会执行裁剪。它会执行模运算并"warps around(环绕)"。一旦值达到255,Numpy将回绕到0并再一次向上技术,直到100 steps reached。

第四个print函数,在减法期间一旦达到0,模运算操作就会回绕并从255开始向后计数。

wrap around: [44]

wrap around: [206]

现在我们已经在OpenCV和NumPy中探讨了图像算法的注意事项,让我们对实际图像执行算法并查看结果:

M = np.ones(image.shape,dtype="uint8") * 100
added = cv2.add(image,M)
cv2.imshow("Added",added)
M = np.ones(image.shape,dtype="uint8") * 50
subtracted = cv2.subtract(image,M)
cv2.imshow("Subtracted",subtracted)
cv2.waitKey(0)

显示效果:

Practical Python and OpenCV,3rd Edition 05

解释

我们首先定义了一个NumPy数组,其大小与我们的图像相同 同样,我们肯定使用8位无符号整数作为我们的数据类型。为了用100的值而不是1来填充我们的矩阵,我们简单地将1的矩阵乘以100.最后,我们使用cv2.add函数将我们的100的矩阵添加到原始图像——从而增加每个像素强度 图像乘以100,但如果它们试图超过255,则确保所有值都被剪切到范围[0,255]。

同样的,我们再定义了一个NumPy数组,并将原始图像减去50个像素,最后,曾经是白色的像素现在看起来是灰色的。这是因为我们从像素中减去50并将它们推向RGB颜色空间的较暗区域。

关注不迷路哦!!


分享到:


相關文章: