OpenCV-像素運算~算術運算

  • 2019 年 11 月 13 日
  • 筆記

將圖片看成類型為uint8的像素矩陣,因此我們可以將兩個像素矩陣進行加減乘除等一些列運算,這也被稱為像素運算,像素運算包括兩種:

  1. 算術運算,比如加減乘除運算。可以調節影像的亮度以及對比度;
  2. 邏輯運算,比如與或非。可以通過邏輯運算完成遮罩層的控制。

本小節主要介紹像素運算中的算術運算。

01

算術運算

算術運算至少需要兩張圖片,由於將圖片看成了擁有三個通道的像素矩陣(還有單通道),因此兩張圖片的算術運算,很顯然的推廣到矩陣之間的運算。學過線性代數的應該知道,矩陣之間能夠進行加法和減法運算的前提條件是兩個矩陣必須形狀一樣,因此在對兩張圖片進行算術運算的時候,必須長寬一致才可以。還有一點需要注意,此時的加減很好理解,但是此時的乘除並不是矩陣之間的乘法或者除法(乘以逆矩陣),而是像素矩陣中對應元素之間的乘除,即逐位運算。

為了演示更好的效果,這裡使用下面兩張圖片,文件名分別命名為"01.jpg"以及"02.jpg"。

02

像素運算~加法

處理影像的相加操作,實質上就是影像的像素矩陣相加。我們分別使用OpenCV提供的add函數以及直接使用影像的像素ndarray數組進行相加操作。

執行結果:

可以看出執行的結果並不是我們想的那樣,兩種方式得到的結果並不一致。下面通過一個簡單的例子:

列印出相加後像素矩陣的結果:

[[ 40 255 255]   [245 240 255]   [255 255 255]]  ********************  [[ 40  19   0]   [245 240  19]   [101 209 186]]

從上面的結果可以看出,其實執行結果不同,只是因為兩種相加方式對於uint8類型數據超過255的不同處理而已,

  1. OpenCV中的add函數,當相加後的結果超過255(大於255),則將其超過的像素點設置為255;
  2. ndarray數組直接相加,相加後如果超過了255(大於255),則會用這個超過255的數值對256進行%執行取模運算,比如對於左下角的運算(102 + 255)% 256 = 101。

我們通常用到的就是OpenCV這種處理方式,對於原始的兩張圖來說,Linux圖中大部分都是黑色,也就是為像素值為0的部分,因此加上windows圖中的有顏色部分,相加得到的就是windows影像的顏色,而Linux圖中的白色部分,本身已經是255了,在加上windows中非0的顏色像素,更會超過255,由於OpenCV中將其設置為255,因此還是白色。

03

像素運算~加法

像素的減法操作和前面的加法操作類似。

執行結果:

當然如果使用ndarray數組直接進行相減操作也是可以的,但是和相加一樣,兩種方式對負數的處理不同:

  1. OpenCV中當進行減法運算的時候遇到小於0的數,將其設置為0;
  2. ndarray數組中遇到小於0的數時候,比如(10 – 30) = -20的時候,用256 + (-20) = 236,感興趣的可以,將加法操作中的對比換成減法操作。

Linux中黑色部分像素值為0,0減去windows中彩色部分變為負數,OpenCV中將其變為0,因此大部分都是黑色,但是在Linux中白色部分,像素值為255,而對應的windows部分值為0 – 255之間,因此相減會變成一個正的整數,因此可以看出做減法操作的時候,Linux圖片文字的部分很炫,五顏六色。

04

像素運算~乘法

有了減法和加法的積累,乘法操作也是很簡單的,這裡只需要注意:

  1. 使用OpenCV進行像素運算:
    1. 超過255的像素點,設置為255;
    2. 小於0的像素點,設置為0;
  2. 使用ndarray數組進行像素運算:
    1. 超過255的像素點,將其對256做取余操作;
    2. 小於0的像素點,將其與256相加;

執行結果:

可以看出結果還是挺炫的,相乘操作,如果非零相乘的話會讓結果變大,當然0乘上任何的數都為0,由於OpenCV對超過255會變為255(乘法很容易超過255),在OpenCV相乘的結果中白色和黑色的區域會相對多一些。此時看結果的Linux圖周邊會有鋸齒的效果,這是因為Linux圖中的Linux文字周圍是有平滑模糊的,這些在Linux文字周邊的值並不為0,因此並不為白色,所以就會產生這種鋸齒的效果。

05

像素運算~除法

除法操作和上面類似,這裡不再贅述。

執行結果:

由於相除讓結果變的都比較小,所以實際使用中使用的很少。