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顏色空間的較暗區域。

關注不迷路哦!!


分享到:


相關文章: