OpenCV—圖像預處理(四)
文章目錄
- OpenCV---圖像預處理(四)
- 九,圖像掩膜
- 9.1 制作掩膜
- 9.2 與運算
- 9.3 顏色替換
- 9.3.1
- 9.3.2 顏色替換
- 十,ROI切割
- 十 一,圖像添加水印
- 11.1模板輸入
- 11.2 與運算
- 11.3 圖像融合(圖像位與操作)
九,圖像掩膜
9.1 制作掩膜
掩膜(Mask)是一種在圖像處理中常見的操作,它用于選擇性地遮擋圖像的某些部分,以實現特定任務的目標。掩膜通常是一個二值化圖像,并且與原圖像的大小相同,其中目標區域被設置為1(或白色),而其他區域被設置為0(或黑色),并且目標區域可以根據HSV的顏色范圍進行修改,如下圖就是制作紅色掩膜的過程:
mask=cv.inRange(img,color_low,color_high)
9.2 與運算
我們在高中時學過邏輯運算中的“與”運算,其規則是當兩個命題都是真時,其結果才為真。而在圖像處理中,“與”運算被用來對圖像的像素值進行操作。具體來說,就是將兩個圖像中所有的對應像素值一一進行“與”運算,從而得到新的圖像。從上面的圖片我們可以看出,掩膜中有很多地方是黑色的,其像素值為0,那么在與原圖像進行“與”運算的時候,得到的新圖像的對應位置也是黑色的
通過掩膜與原圖的與運算,我們就可以提取出圖像中被掩膜覆蓋的區域(扣圖)。
cv2.bitwise_and(src1,src2[,mask])
9.3 顏色替換
顏色替換其原理就是在得到原圖的掩膜之后,對掩膜中的白色區域所對應的原圖中的區域進行一個像素值的修改即可。
9.3.1
由于掩膜與原圖的大小相同,并且像素位置一一對應,那么我們就可以得到掩膜中白色(也就是像素值為255)區域的坐標,并將其帶入到原圖像中,即可得到原圖中的紅色區域的坐標,然后就可以修改像素值了,這樣就完成了顏色的替換
9.3.2 顏色替換
由于掩膜與原圖的大小相同,并且像素位置一一對應,那么我們就可以得到掩膜中白色(也就是像素值為255)區域的坐標,并將其帶入到原圖像中,即可得到原圖中的紅色區域的坐標,然后就可以修改像素值了,這樣就完成了顏色的替換
- 實際練習
import cv2 as cv
import numpy as np
#圖像掩膜
img = cv.imread('txycl/images/demo.png')
img_r =cv.resize(img,(450,350))
#顏色空間轉換hsv
hsv = cv.cvtColor(img_r,cv.COLOR_BGR2HSV)
#創建掩膜cv.inRange(src,lowerb,upperb,dst)
color_low = np.array([23,46,46])
color_high = np.array([34,255,255])
#創建掩膜,大小和原圖一樣
mask_yellow = cv.inRange(hsv,color_low,color_high)
print(mask_yellow)
#與運算
res = cv.bitwise_and(img_r,img_r,mask=mask_yellow)#替換顏色
img_r[mask_yellow==255] = [0,255,0]
#numpy的高級索引,布爾索引
#mask_yellow = 255生成布爾數組,大小和掩膜,等于255的地方為ture,否則false
#img_np[ ]= [0,255,0]進行布爾索引,篩選處為true的元素替換為[0,255,0]# cv.imshow('img',img_r)
# cv.imshow('hsv',hsv)
cv.imshow('mask',mask_yellow)
cv.imshow('res',res)
cv.imshow('img_np',img_r)
cv.waitKey(0)
cv.destroyAllWindows()
創建掩膜
進行與運算
替換顏色
十,ROI切割
ROI:Region of Interest,翻譯過來就是感興趣的區域。什么意思呢?比如對于一個人的照片,假如我們要檢測眼睛,因為眼睛肯定在臉上,所以我們感興趣的只有臉這部分,其他都不care,所以可以單獨把臉截取出來,這樣就可以大大節省計算量,提高運行速度。
在計算機視覺中,當我們使用OpenCV讀取RGB三通道圖像時,它會被轉換成一個三維的Numpy數組。這個數組里的每個元素值都表示圖像的一個像素值。這個三維數組的第一個維度(即軸0)通常代表圖像的高度,第二個維度(即軸1)代表圖像的寬度,而第三個維度(即軸2)代表圖像的三個顏色通道(B、G、R,OpenCV讀取到的圖像以BGR的方式存儲)所對應的像素值。
因此,我們可以通過指定切片的范圍來選擇特定的高度和寬度區域。這樣,我們就能夠獲取這個區域內的所有像素值,即得到了這個區域的圖像塊,通過Numpy的切片操作,我們就完成了ROI切割的操作。這種提取ROI的方法允許我們僅獲取感興趣區域內的像素,而忽略其他不相關的部分,從而大大減少數據處理和存儲的負擔。
#ROI切割
#(363,238)(480,348)(x,y)
img = cv.imread('txycl/images/cat1.png')
#使用numpy數組進行切片
img_roi = img[238:363,348:480]
img_roi[:]=[0,0,255]
cv.imshow('img',img)
# cv.imshow('img',img_roi)
cv.waitKey(0)
cv.destroyAllWindows()
十 一,圖像添加水印
添加水印的概念其實可以理解為將一張圖片中的某個物體或者圖案提取出來,然后疊加到另一張圖片上。具體的操作思想是通過將原始圖片轉換成灰度圖,并進行二值化處理,去除背景部分,得到一個類似掩膜的圖像。然后將這個二值化圖像與另一張圖片中要添加水印的區域進行“與”運算,使得目標物體的形狀出現在要添加水印的區域。最后,將得到的目標物體圖像與要添加水印的區域進行相加,就完成了添加水印的操作。這樣可以實現將一個圖像中的某個物體或圖案疊加到另一個圖像上,從而實現添加水印的效果。就本實驗而言,會用到兩個新的組件,一個是模板輸入,一個是圖像融合。
11.1模板輸入
其實,該組件起到的就是圖片輸入的功能,只不過使用模板輸入所輸入的圖片其實是作為要添加的水印,有了水印的彩色圖之后,我們需要用它來制作一個掩模,這就用到了灰度化和二值化,即先灰度化后二值化,這就得到了帶有水印圖案的掩模。
11.2 與運算
有了模板的掩膜之后(也就是二值化圖),我們就可以在要添加水印的圖像中,根據掩膜的大小切割出一個ROI區域,也就是我們要添加水印的區域,之后讓其與模板的掩膜進行與運算,我們知道,與運算的過程中,只要有黑色像素,那么得到的結果圖中的對應位置也會是黑色像素。由于模板的掩膜中目標物體的像素值為黑色,所以經過與運算后,就會在ROI區域中得到模板圖的形狀。
11.3 圖像融合(圖像位與操作)
將模板的形狀添加到水印區域之后,就可以將該圖像與原始的模板圖進行圖像融合。該組件的目的就是將圖像對應的數組中的對應元素進行相加(一定要注意這里的兩個數組是規格相同的,也就是說要么都是灰度圖,要么都是彩圖)
因此就可以讓原始的模板圖與添加模板圖形狀的ROI區域進行圖像融合,得到添加水印的ROI區域
- 示例
#圖像添加水印
#logo圖片
img_logo = cv.imread('txycl/images/baolong.png')
#背景圖片
img_bg = cv.imread('txycl/images/bg.png')
#獲取logo的大小
h,w,_ = img_logo.shape
#從背景中切割出和logo一樣的大小的區域
img_bg_roi = img_bg[0:h,0:w]
#logo進行灰度處理,并二值化
img_logo_gray = cv.cvtColor(img_logo,cv.COLOR_BGR2GRAY)#創建白色logo的掩膜,目的是獲取logo的顏色,有logo沒背景(反閾值法)
_,white = cv.threshold(img_logo_gray,170,255,cv.THRESH_BINARY_INV)
fg1 = cv.bitwise_and(img_logo,img_logo,mask=white)
#創建黑色logo的掩膜,目的是獲取到背景顏色,有背景沒logo(閾值法)
_,black = cv.threshold(img_logo_gray,170,255,cv.THRESH_BINARY)
fg2 = cv.bitwise_and(img_bg_roi,img_bg_roi,mask=black)
#圖像融合
img_bg_roi[:]=fg1+fg2
#讓融合后的圖像賦值到背景中,這樣原圖也修改#運行
cv.imshow('img_logo',img_logo)#logo
cv.imshow('img_bg_roi',img_bg_roi)#背景
cv.imshow('img_logo_gray',img_logo_gray)#logo灰度圖
cv.imshow('fg1',fg1)#logo二值化
cv.imshow('fg2',fg2)#logo二值化
#cv.imshow('fg',fg)#融合
cv.imshow('img_bg',img_bg)#背景+logo
cv.waitKey(0)
cv.destroyAllWindows()
- 運行
分別為原圖,roi切割圖,白色掩膜,黑色掩膜圖
原圖水印圖