圖像上的算術運算
1.圖像加法
圖像相加:一般用于對同一場景的多幅圖像求平均,以便有效地降低(additive)隨機噪聲。
利用求平均的方法降低噪聲信號提高信噪比的做法,只有當噪聲可以用同一個獨立分布的隨機模型描述時才會有效。
作用:圖像混合和降噪
使用函數 cv2.add() 將兩幅圖像進行加法運算,當然也可以直接使用 numpy,res=img1+img。兩幅圖像的大小,類型必須一致,或者第二個圖像可以使一個簡單的標量值。
cv2.add(src1, src2, mask)
參數意義如下:
- scr1:輸入的第一幅圖像
- scr2:輸入的第二幅圖像
- mask:可選,掩膜
補充:在有些圖像處理的函數中有的參數里面會有mask參數,即此函數支持掩膜操作,首先何為掩膜以及有什么用,如下:
數字圖像處理中的掩膜的概念是借鑒于PCB制版的過程,在半導體制造中,許多芯片工藝步驟采用光刻技術,用于這些步驟的圖形“底片”稱為掩膜(也稱作“掩模”),其作用是:在硅片上選定的區域中對一個不透明的圖形模板遮蓋,繼而下面的腐蝕或擴散將只影響選定的區域以外的區域。
圖像掩膜與其類似,用選定的圖像、圖形或物體,對處理的圖像(全部或局部)進行遮擋,來控制圖像處理的區域或處理過程。
數字圖像處理中,掩模為二維矩陣數組,有時也用多值圖像,圖像掩模主要用于:
①提取感興趣區,用預先制作的感興趣區掩模與待處理圖像相乘,得到感興趣區圖像,感興趣區內圖像值保持不變,而區外圖像值都為0。
②屏蔽作用,用掩模對圖像上某些區域作屏蔽,使其不參加處理或不參加處理參數的計算,或僅對屏蔽區作處理或統計。
③結構特征提取,用相似性變量或圖像匹配方法檢測和提取圖像中與掩模相似的結構特征。
④特殊形狀圖像的制作。
區別:OpenCV 中的加法與 Numpy 的加法是有所不同的。OpenCV 的加法是一種飽和操作,而 Numpy 的加法是一種模操作。
例子:
x = np.uint8([250])
y = np.uint8([10])
print(x+y) # 250+10 = 260 % 256 = 4
print(cv2.add(x,y)) # 250+10 = 260 => 255
[4]
[[255]]
這種差別在你對兩幅圖像進行加法時會更加明顯。OpenCV 的結果會更好一點。所以我們盡量使用 OpenCV 中的函數。
例子
import cv2
import matplotlib.pyplot as plt
import numpy as np
def img_show(name,img):
"""matplotlib圖像顯示函數
name:字符串,圖像標題
img:numpy.ndarray,圖像
"""
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
plt.imshow(img,'gray')
plt.xticks([])
plt.yticks([])
plt.xlabel(name,fontproperties='FangSong',fontsize=12)
if __name__=="__main__":
img1 = cv2.imread("art-art-exhibition-art-gallery-2110950.jpg")
img2 = cv2.imread("art-exhibition-art-gallery-artwork-2110937.jpg")
print(img1.shape)
print(img2.shape)
img3 = img1.copy() # 復制img1
img3 = img3[:3339,:5008] # 裁剪圖像使img3與img2圖像大小一致
print(img3.shape)
img4 = img2+img3
img5 = cv2.add(img2,img3)
# 圖像顯示
plt.figure(figsize=(12,8),dpi=80)
plt.subplot(221)
img_show('img2',img2)
plt.subplot(222)
img_show('img3',img3)
plt.subplot(223)
img_show('numpy中img2+img3',img4)
plt.subplot(224)
img_show('Opencv中img2+img3',img5)
(3351, 5026, 3)
(3339, 5008, 3)
(3339, 5008, 3)
2.圖像混合
cv2.scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst)
可以按下面的公式對圖片進行混合操作
cv2.addWeighted(InputArray src1, double alpha, InputArray src2,double beta, double gamma,OutputArray dst, int dtype=-1)
這其實也是加法,但是不同的是兩幅圖像的權重不同,這就會給人一種混合或者透明的感覺。圖像混合的計算公式如下:
通過修改 的值(0 → 1),可以實現非??岬幕旌稀,F在我們把兩幅圖混合在一起。第一幅圖的權重是 0.6,第二幅圖的權重是 0.4。函數 cv2.addWeighted() 可以按下面的公式對圖片進行混合操作。
這里的取值為 0。
img1 = cv2.imread("fashion-fun-model-2191055.jpg")
img2 = cv2.imread("delicious-food-food-photography-2111987.jpg")
print(img1.shape)
print(img2.shape)
img3 = img1.copy()
img3 = img3[:4611,:3451]
print(img3.shape)
dst = cv2.addWeighted(img2,0.6,img3,0.4,0)
plt.figure(figsize=(8,20),dpi=80)
plt.subplot(131)
img_show('img2',img2)
plt.subplot(132)
img_show('img3',img3)
plt.subplot(133)
img_show('圖像混合',dst)
(6000, 4000, 3)
(4611, 3451, 3)
(4611, 3451, 3)
3.圖像相減
圖像相減即在兩幅圖像之間對應像素做減法運算。圖像相減可以檢測出兩幅圖像的差異信息,因此這項技術在工業、醫學、氣象以及軍事等領域中都有廣泛的應用。
主要應用:
(1)去除一幅圖像中不需要的圖案,如緩慢變化的背景陰影,周期性噪聲等;
(2)檢測同一場景的兩幅圖像之間的變化
(3)運動檢測
cv2.subtract(src1, src2, mask)
參數意義參見cv2.add()。
img1 = cv2.imread("lenaNoise.png")
img2 = cv2.imread("lena.jpg")
img3 = cv2.subtract(img1,img2)
plt.figure(figsize=(10,8),dpi=80)
plt.subplot(231)
img_show('lenaNoise',img1)
plt.subplot(232)
img_show('lena',img2)
plt.subplot(233)
img_show('圖像相減',img3)
4.乘法運算
可以用來實現掩模處理,即屏蔽掉圖象的某些部分。此外由于時域的卷積和相關運算與頻域的乘積運算對應,因此乘法運算有時也被用來做為一種技巧來實現卷積或相關處理。
cv2.multiply(src1, src2)
5.除法運算
可用于校正成像設備的非線性影響,在特殊形態的圖像(如斷層掃描等醫學圖像)處理中用到。也可用于校正照明不足或者傳感器的非線性影響造成的偏差。
cv2.divide(src1, src2)
6.按位運算
按位操作有:AND,OR,NOT,XOR 等。
- bitwise_and是對二進制數據進行“與”操作,即對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“與”操作,1&1=1,1&0=0,0&1=0,0&0=0
- bitwise_or是對二進制數據進行“或”操作,即對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“或”操作,1|1=1,1|0=0,0|1=0,0|0=0
- bitwise_xor是對二進制數據進行“異或”操作,即對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“異或”操作,1 ^ 1=0,1 ^ 0=1,0 ^ 1=1,0 ^ 0=0
- bitwise_not是對二進制數據進行“非”操作,即對圖像(灰度圖像或彩色圖像均可)每個像素值進行二進制“非”操作,~ 1=0,~ 0=1
cv2.bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray()) # dst = src1 & src2
cv2.bitwise_or(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray()) # dst = src1 | src2
cv2.bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray()) # dst = src1 ^ src2
cv2.bitwise_not(InputArray src, OutputArray dst,InputArray mask=noArray()) # dst = ~src
當我們提取圖像的一部分,選擇非矩形 ROI 時這些操作會很有用(下一章你就會明白)。下面的例子就是教給我們如何改變一幅圖的特定區域。我想把 OpenCV 的標志放到另一幅圖像上。如果我使用加法,顏色會改變,如果使用混合,會得到透明效果,但是我不想要透明。如果它是矩形我可以使用 ROI。但是它不是矩形。但是我們可以通過下面的按位運算實現:
img1 = cv2.imread("delicious-food-food-photography-2111987.jpg")
img2 = cv2.imread("opencv-logo.png")
# 創建一個ROI,并放在左上角
rows,cols,channels = img2.shape
roi = img1[0:rows,0:cols]
# 創建一個mask,并創建一個inverse mask
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
ret,mask = cv2.threshold(img2gray,175,255,cv2.THRESH_BINARY) #閾值處理,后面內容會詳細介紹
mask_inv = cv2.bitwise_not(mask)
# logo的白色區域為感興趣的區域ROI
# 取roi中與mask中不為零的值對應的像素的值,其他值為0
# 注意這里必須有mask=mask或者mask=mask_inv,其中mask=不能忽略
img1_bg = cv2.bitwise_and(roi,roi,mask=mask)
# 取roi中與mask_inv中不為零的值對應的像素的值,其他值為0。
# Take only region of logo from logo image.
img2_fg = cv2.bitwise_and(img2,img2,mask=mask_inv)
# 將logo中的ROI放到主圖像中
dst = cv2.add(img1_bg,img2_fg)
img3 = img1.copy()
img3[0:rows,0:cols] = dst
# 顯示圖像
plt.figure(figsize=(20,8),dpi=80)
plt.subplot(241)
img_show('img1',img1)
plt.subplot(242)
img_show('img2',img2)
plt.subplot(243)
img_show('roi',roi)
plt.subplot(244)
img_show('mask',mask)
plt.subplot(245)
img_show('mask_inv',mask_inv)
plt.subplot(246)
img_show('img2_fg',img1_bg)
plt.subplot(247)
img_show('img2_fg',img2_fg)
plt.subplot(248)
img_show('圖像混合',img3)
7.其他算數運算
cv2.sqrt(InputArray src, OutputArray dst) # 計算每個矩陣元素的平方根
cv2.pow(InputArray src, double power, OutputArray dst) # src的power次冪
cv2.exp(InputArray src, OutputArray dst) # dst = e**src(**表示指數的意思)
cv2.log(InputArray src, OutputArray dst) # dst = log(abs(src))
更多詳情請參考opencv官網。
參考資料:
網址:
https://blog.csdn.net/Gavinmiaoc/article/details/80856246
https://blog.csdn.net/u011028345/article/details/77278467
書籍:《數字圖像處理》《OpenCV-Python-Toturial-中文版》