【小林的OpenCV基礎課 6】基本數學操作 初識掩膜
申し訳ありませんが、小林は遅れて來ました
還記得上一話的作業嗎?
- 改變小林自拍照中門鈴的顏色,要求使用ROI和BGR三通道,自拍照就是Github中的"IMG_8257.JPG"。
import cv2nimport numpy as npnnimg = cv2.imread(IMG_8257.JPG,1)nn# 分離圖像 得到BGR三個通道的圖像分量nb,g,r = cv2.split(img)nncv2.namedWindow(Source Image)ncv2.namedWindow(New Red Channel)ncv2.namedWindow(New Image)nn# 顯示原圖和三個通道ncv2.imshow(Source Image, img)nn# 在R通道中確定ROI區域 並修改ROI中所有像素的值nROI = r[260:380, 30:120]nROI = 255nr[260:380, 30:120] = ROInn# 顯示修改後的R通道和它與BG通道合併後的新圖ncv2.imshow(New Red Channel, r)nnewImage = cv2.merge((b, g, r))ncv2.imshow(New Image, newImage)nncv2.waitKey(0)ncv2.destroyAllWindows()n
進入正題。emmm,數學,大眾初戀,這一話是逃不出數學了。不過這一話講的是基本數學操作,有多基本呢?
- 加法:1+1=?
- 帶權重的加法:大學考試中常用的計分手段,比如平時分佔30%,卷面分佔70%
- 邏輯運算:與或非啥的
(康娜醬似懂非懂,畢竟人家是龍)
加法
這裡的加法是建立在矩陣運算的基礎上進行的。
請陳獨秀同志收起線性代數課本(づ ̄ 3 ̄)づ
在OpenCV中圖像的加法常用有兩種:
- OpenCV提供的add方法
- numpy中矩陣的直接相加
import numpy as npnimport cv2n# 使用numpy新建兩個圖像矩陣na = np.zeros((500,500),np.uint8)nb = np.ones((500,500),np.uint8)n# 以矩陣形式查看兩個矩陣的內容nprint(a)nprint(b)n# numpy矩陣直接相加nc = a+bn# OpenCV提供的add方法nd = cv2.add(a,b)nncv2.namedWindow(b)ncv2.imshow(b,b)nb = b + 120ncv2.namedWindow(b+120)ncv2.imshow(b+120,b)ncv2.namedWindow(add)ncv2.imshow(add,d)n# 驗證兩種相加的方法得到的結果是否相同nprint(c.all() == d.all())nncv2.waitKey()ncv2.destroyAllWindows()n
敲黑板了,兩幅圖像相加時,圖像的尺寸和通道數要一致,就好比蘋果手機的數據線只能在蘋果設備中使用而不能在安卓設備上使用。
帶權重的加法
在大學考試中,通常採用帶權重的加法來計算成績,如常見的平時分30%,卷面分70%。而在圖像處理中也提供了一個叫addWeighted的函數來進行圖像混合。
數學公式:
其中Gamma是帶權相加後的總偏移值。
函數原型:
dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])n
- dst:混合後的圖像矩陣
- src1和alpha:第一個圖像矩陣和對應的權重
- src2和beta:第二個圖像矩陣和對應的權重
- gamma:偏移值
- dtype:輸出圖像的深度,即通道數。當輸入的兩幅圖像有相同的通道數時dtype為默認值-1
注意:alpha和beta是按各自的比重分別分配給src1和src2,所以不要求二者相加等於1,但為了增加代碼的可讀性,建議讓alpha和beta相加等於1。
下面小林將馬卡龍的圖片和秋景圖片按1:1相加:
import cv2nimport numpy as npnnimg1 = cv2.imread(m1.jpg)nimg2 = cv2.imread(q1.jpg)nnimg3 = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)nncv2.namedWindow(img1)ncv2.namedWindow(img2)ncv2.namedWindow(img3)ncv2.imshow(img1, img1)ncv2.imshow(img2, img2)ncv2.imshow(img3, img3)nncv2.imwrite(qq1.jpg, img3)nncv2.waitKey()ncv2.destroyAllWindows()n
朦朧的感覺有木有(づ ̄ 3 ̄)づ
邏輯運算
我們先來複習下常用的按位邏輯運算:
- 與 1&1 = 1,1&0 = 0
- 或 1|1 = 1,1|0 = 1
- 非 ~1 = 0,~0 = 1
- 異或 兩者相同為0,不同為1
在OpenCV中有以下的函數對應關係:
- bitwise_and:按位與運算
- bitwise_or:按位或運算
- bitwise_not:按位非運算
- bitwise_xor:按位異或運算
函數原型,以bitwise_and為例:
dst = cv2.bitwise_and(src1, src2[, dst[, mask]])n
重點介紹下這個神奇的mask:
- mask在視覺中通常理解為「掩膜」。小區籃球場上的白線,通常是用兩條寬膠帶平行貼在地上,中間留有一定的寬度,然後一刷子上去,再揭去膠帶,便只有中間的空隙染成了白色,這就是掩膜的原理。
- 在我們處理ROI區域時通常會遇到這樣一種尷尬無比的情況:明明我想要那個籃球作為ROI,但我做出來的ROI都是矩形!場面一度十分尷尬。
- 而掩膜技術就能化解這種尷尬的情況。
那bitwise_and中如何使用掩膜呢?
Step 1:對需要進行掩膜處理的圖像進行閾值化處理
Step 2:如有必要,對閾值化後的圖像進行反轉
Step 3:上述兩步確保「膠帶」區域為0,然後與原圖進行與運算,獲得掩膜處理後的圖像
下面奉上一個demo。(無恥的廣告時間)世界著名的消費級無人機製造商大疆創新(英文名DJI,總部在深圳)在1月23日發布的Mavic Air可謂是驚艷了科技圈,憑藉輕便的機身和不俗的性能讓她瞬間成為大疆最搶手的產品。身為疆粉的小林這裡自然要拿Mavic Air做demo了。我們知道大疆的無人機對攝像頭情有獨鍾,裡面用到了大量CV的東西(強行和OpenCV扯上關係(づ ̄ 3 ̄)づ)。下面我們用掩膜的手段把OpenCV的Logo貼到Mavic Air的帥照上去。
- 使用掩膜獲得Logo的前景圖,白色背景不要
- 在Mavic Air的帥照上划出ROI,用同樣的掩膜處理ROI區域
- 使用加法將掩膜後的Logo蓋到Mavic Air帥照的ROI區域里
代碼中使用了threshold函數做閾值化處理(做過智能車大賽光電組的同學一定深有體會),這個函數如何使用,請同學們查閱API,小林會在下一話講到。
import cv2nimport numpy as npnnimg1 = cv2.imread(mavic air.jpg)nimg2 = cv2.imread(logo1.jpg)nn# 創建ROI區域nrows1,cols1,channels1 = img1.shapenrows2,cols2,channels2 = img2.shapenroi = img1[rows1-rows2:rows1, cols1-cols2:cols1 ]nn# 創建Logo的掩膜nimg2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)nret, mask = cv2.threshold(img2gray, 170, 255, cv2.THRESH_BINARY)nmask_inv = cv2.bitwise_not(mask)ncv2.namedWindow(mask_inv)ncv2.imshow(mask_inv, mask_inv)nn# 在Mavic Air的ROI區域放上掩膜 即貼上"膠帶"nimg1_bg = cv2.bitwise_and(roi,roi,mask = mask)nn# 現在"刷上"顏色nimg2_fg = cv2.bitwise_and(img2,img2,mask = mask_inv)nn# "撕掉膠帶"ndst = cv2.add(img1_bg, img2_fg)ncv2.imwrite(merge.jpg, dst)nroi[:] = dstnncv2.imshow(res,img1)ncv2.waitKey(0)ncv2.destroyAllWindows()n
為什麼要使用反轉後的掩膜呢?為什麼最後要把img1_bg和img2_fg相加呢?小林提示一下:
- 與運算的特點:和1與,數據不變,和0與,結果為0
- 黑色在灰度模型中為0,而BGR模型是由三個灰度通道疊加而成
同學們明白了木有?
其實掩膜技術在CV中應用的特別多,後面小林還會介紹掩膜的其他應用。
這一話的掩膜技術,內容略多,請同學們自行消化。如果不懂可以在評論區留言或者私信小林哦(づ ̄ 3 ̄)づ示例代碼已經同步至Github,對應的文件為C3 Core Operations文件夾下的C3 Addition.py、C3 Addition with Weight.py和C3 Bitwise and Mask.py三個文件。
最後的最後
如果喜歡小林的專欄,就收藏了吧!してください!
推薦閱讀:
※如何看待經典與前沿(熱點)?
※深度學習在圖像去噪方面最近有哪些進展,與傳統方法相比效果如何?
※Batch normalization和Instance normalization的對比?
※【小林的OpenCV基礎課 5】圖像的基本操作