OpenCV-Python常用影象運算:加減乘除冪開方對數及位運算

2020-10-20 11:01:15

☞ ░ 前往老猿Python部落格 https://blog.csdn.net/LaoYuanPython

一、引言

在寫該文之前,老猿就影象的一些運算已經單獨邊學邊發了,在寫這些文的過程中,發現這些運算函數共同點很多,例如大部分引數一樣、部分處理方法一樣等,另外還有些函數可以實現相同或近似的效果,因此在前面那些文章的基礎上,將其綜合為一個整體來發布,更方便大家閱讀。

OpenCV中影象儲存為矩陣,因此影象的運算其實就是矩陣的運算。影象的運算主要包括影象基礎算術運算、影象加權運算(又稱為影象融合)、按位元運算等類別。這些運算可以直接通過numpy矩陣進行,也可以通過opencv的專用方法進行,但opencv的矩陣運算和numpy矩陣運算還是有些不同。例如在加法處理上,OpenCV加法是飽和運算(超過255即按255),而Numpy加法是模運算(超過255按256取模的結果作為結果,好多)。對加法來說,顏色值越大OpenCV 的結果會更好,因此推薦使用opencv的進行算術運算。本文的內容全部基於OpenCV的方法進行介紹。

二、OpenCV影象運算語法

2.1、影象運算函數列表

OpenCV影象運算包括如下函數:

  1. 加法運算:add(src1, src2, dst=None, mask=None, dtype=None)
  2. 減法運算:subtract(src1, src2, dst=None, mask=None, dtype=None)
  3. 乘法運算:multiply(src1, src2, dst=None, scale=None, dtype=None)
  4. 除法運算:divide(src1, src2, dst=None, scale=None, dtype=None)
  5. 冪運算:pow(src, power, dst=None)
  6. 開方運算:sqrt(src, dst=None)
  7. 自然常數e為底的指數函數:exp(src, dst=None)
  8. 對數運算:log(src, dst=None)
  9. 融合權重加法:addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)
  10. 位與運算:bitwise_and(src1, src2, dst=None, mask=None)
  11. 位或運算:bitwise_or(src1, src2, dst=None, mask=None)
  12. 位互斥或運算:bitwise_xor(src1, src2, dst=None, mask=None)
  13. 位非運算:bitwise_not(src, dst=None, mask=None)

2.2、影象運算常用引數說明

  • src:輸入影象矩陣
  • src1、src2:兩副大小和通道數相等的輸入影象或一副輸入影象和一個標量(關於標量請參考《OpenCV-Python中的標量Scalar是什麼》)
  • dst:目標影象輸出,要求與輸入影象大小相同,如果傳值則可以直接以實參作為目標影象儲存變數,否則可以用函數返回值作為目標影象儲存變數,在實參非None傳入的情況下,返回值與該實參值相同
  • scale:縮放因子,影象運算時,先執行src1*scale,再以該乘積進行後續運算
  • mask:影象掩膜,可選引數,為8位元單通道的灰度影象,用於指定要更改的輸出影象陣列的元素,即輸出影象畫素只有mask對應位置元素不為0的部分才輸出,否則該位置畫素的所有通道分量都設定為0。更多關於掩膜的內容請參考《OpenCV學習02-矩陣的掩膜操作
  • dtype:可選引數,輸出影象陣列的深度,即影象單個畫素值的位數(如RGB用三個位元組表示,則為24位元)。在幫助檔案中介紹,引數src1和src2可以有不同的影象深度(即影象畫素位數,如8位元、16位元、24位元和32位元),如可以將16位元影象和一個8位元影象相加將輸出結果儲存在32位元輸出陣列中。關於這個引數老猿研究可很長時間,因為認為如果影象深度不一樣,意味著影象的通道數也不一樣,通道數不一樣,意味著陣列大小不一樣,這樣的兩個陣列無法進行運算。後來機緣契合下自認為理解了,這裡說的影象深度不是通道數*8,而是單個通道值表示的位數,即單通道不一定是8位元的,也可以是16位元、24位元或32位元的。看如下程式碼就明白了:
def main():
    img1 = cv2.imread(r'F:\pic\shape1.png').astype(np.float32)
    img2 = cv2.imread(r'F:\pic\shape2.png')
    img = cv2.add(img1,img2,dtype=24)

上述程式碼將以兩種不同表示方法讀入兩副影象,第一幅影象是以float32來表示影象單通道值,第二幅影象是預設值uint8來表示影象單通道值,二者機器位數不同,但相加之後轉為了24位元影象,即單通道為8位元組影象。

2.3、部分影象運算函數詳解

針對部分重要的影象運算,老猿在前面已經單獨進行了介紹,包括:

  1. OpenCV-Python影象的加法運算cv2.add函數詳解
  2. OpenCV-Python影象的減法運算cv2.subtract函數詳解以及和矩陣減法的差異對比
  3. OpenCV-Python影象乘法運算cv2.multiply函數詳解及畫素值溢位歸一化處理
  4. OpenCV-Python影象除法運算cv2.divide函數及影象相除處理
  5. OpenCV-Python影象融合cv2.addWeighted權重加法函數詳解
  6. OpenCV-Python影象位與運算bitwise_and函數詳解

2.4、其他影象運算函數簡介

  1. 冪運算:pow(src, power, dst=None),對影象的每個通道值計算power引數對應的冪作為結果影象的通道值,如果power為整數,則直接計算冪值,如果power為浮點數,則取通道值的絕對值參與計算,即:在這裡插入圖片描述

  2. 開方運算:sqrt(src, dst=None),對影象的每個通道值開方作為結果影象的通道值,即:dst(I)=sqrt(src1(I))

  3. 自然常數e為底的指數函數:exp(src, dst=None),以e為底對影象的每個通道值作為冪值計算結果影象的通道值,即:在這裡插入圖片描述

  4. 對數運算:log(src, dst=None),計算影象的每個通道值的自然對數作為結果影象的通道值,即:dst(I)=ln(src(I))

  5. 位或運算:bitwise_or(src1, src2, dst=None, mask=None),計算兩副影象每個通道值或一影象通道值與一個標量的按位元或的結果作為結果影象的通道值

  6. 位互斥或運算:bitwise_xor(src1, src2, dst=None, mask=None),計算兩副影象每個通道值或一影象通道值與一個標量的按位元互斥或的結果作為結果影象的通道值

  7. 位非運算:bitwise_not(src, dst=None, mask=None),將src影象的每個通道值按位元取反作為結果影象的值。

三、相關函數的作用分析

  1. 影象的減法、除法以及互斥或都可以用於分析影象的差異點,但減法和互斥或更準確 ;
  2. 加法、權重加法以及影象或運算都可以用於合併影象,但由於運算方法與差異,效果會有不同,針對不同影象的融合選擇哪種方法與影象資料及應用的目標相關;
  3. 影象的自乘、冪運算都可以用於調整影象的對比度;
  4. 非運算及互斥或運算可以將影象的一部分影象的視覺效果提高;
  5. 影象乘法、位與都可以用於提取影象的感興趣部分或者遮蔽某些部分,在這方面的功能與影象掩碼的效果相同,只是實現方式不同;
  6. 通過閾值處理、影象求反、與處理等可以提取影象中的結構特徵

四、按位元運算的簡單案例

前面部分影象運算函數詳解中舉例介紹了影象加減乘除權重加及位與的相關功能,在此補充一個簡單的按位元運算的案例。程式碼如下:

import numpy as np
import cv2
def main():
    img1 = cv2.imread(r'F:\pic\shape1.png').astype(np.float32)
    img2 = cv2.imread(r'F:\pic\shape2.png')

    resultImgAnd = cv2.bitwise_and(img1, img2)
    resultImgOr = cv2.bitwise_or(img1, img2)
    resultImgXor = cv2.bitwise_xor(img1, img2)
    resultImgNot = cv2.bitwise_not(img1)
    resultImgXorScalar = cv2.bitwise_xor(img1, (255,255,255,255))

    cv2.imshow('img1',img1)
    cv2.imshow('img2', img2)
    cv2.imshow('resultImgAnd', resultImgAnd)
    cv2.imshow('resultImgOr', resultImgOr)
    cv2.imshow('resultImgXor', resultImgXor)
    cv2.imshow('resultImgNot', resultImgNot)
    cv2.imshow('resultImgXorScalar', resultImgXorScalar)
    cv2.waitKey(0)

main()

執行顯示的圖片截圖:
在這裡插入圖片描述

五、小結

本文詳細介紹了OpenCV-Python影象的加減乘除冪開方對數及位運算相關的函數及語法,並總結了相關函數的作用。OpenCV中影象儲存為矩陣,因此影象的運算其實就是矩陣的運算。影象的運算主要包括影象基礎算術運算、影象加權運算(又稱為影象融合)、按位元運算等類別。這些運算可以直接通過numpy矩陣進行,也可以通過opencv的專用方法進行,但opencv的矩陣運算是飽和運算,其運算效果比純粹的矩陣運算效果更好。

更多OpenCV-Python介紹請參考專欄《OpenCV-Python圖形影象處理 》
專欄網址https://blog.csdn.net/laoyuanpython/category_9979286.html

關於老猿的付費專欄

老猿的付費專欄《使用PyQt開發圖形介面Python應用 》(https://blog.csdn.net/laoyuanpython/category_9607725.html)專門介紹基於Python的PyQt圖形介面開發基礎教學,付費專欄《moviepy音視訊開發專欄》 (https://blog.csdn.net/laoyuanpython/category_10232926.html)詳細介紹moviepy音視訊剪輯合成處理的類相關方法及使用相關方法進行相關剪輯合成場景的處理,兩個專欄都適合有一定Python基礎但無相關知識的小白讀者學習。

付費專欄文章目錄:《moviepy音視訊開發專欄文章目錄》(https://blog.csdn.net/LaoYuanPython/article/details/107574583)、《使用PyQt開發圖形介面Python應用專欄目錄 》(https://blog.csdn.net/LaoYuanPython/article/details/107580932)。

對於缺乏Python基礎的同仁,可以通過老猿的免費專欄《專欄:Python基礎教學目錄》(https://blog.csdn.net/laoyuanpython/category_9831699.html)從零開始學習Python。

如果有興趣也願意支援老猿的讀者,歡迎購買付費專欄。

跟老猿學Python、學OpenCV!

☞ ░ 前往老猿Python博文目錄 https://blog.csdn.net/LaoYuanPython