【opencv】(2) 图像处理:边界填充、图像融合、图像阈值、数值计算
主要內(nèi)容有:邊界填充 cv2.copyMakeBorder(),數(shù)值計算?cv2.add(),改變尺寸?cv2.resize(),圖像融合?cv2.addWeighted(),圖像閾值?cv2.threshold()
在開始之前,我們先導(dǎo)入圖像,img中存放我們需要用到的圖像。并定義一個圖像顯示函數(shù),便于接下來畫圖。
# 導(dǎo)入opencv庫
import cv2
# 定義圖像顯示函數(shù)
def cv_show(name,img):# 傳入(自定義窗口名,圖像數(shù)據(jù))cv2.imshow(name,img) # 等待時間設(shè)為0,讓圖像不會自己消失cv2.waitKey(0)# cv2.waitKey(1000) # 圖像顯示1000毫秒后消失# 鍵盤上任意按一個圖像消失cv2.destroyAllWindows()# 指定圖像所在的文件夾
filepath = 'C:\\...\\opencv\\img'
# 提取問價夾中的某一張圖像
img = cv2.imread(filepath+'\\wise3.jpg')
1. 邊界填充
設(shè)置邊界框方法:?cv2.copyMakeBorder(src, top, bottom, left, right, borderType,? value)
src: 輸入的圖片
top, bottom, left, right: 相應(yīng)方向上的邊框?qū)挾?/span>
borderType: 定義添加邊框的方法
value:如果borderType為 cv2.BORDER_CONSTANT 時需要填充的常數(shù)值
borderType方法如下:
cv2.BORDER_REPLICATE:復(fù)制法,復(fù)制最邊緣像素
cv2.BORDER_REFLECT:反射法,在圖像中指定像素的兩邊進行反射復(fù)制,如: gfedcba|abcdefgh|hgfedcb
cv2.BORDER_REFLECT_101:反射法,以最邊緣像素為軸,如:dcba|abcd|dcba
cv2.BORDER_WRAP:外包裝法,如:cdefgh|abcdefgh|abcdefg
cv2.BORDER_CONSTANT:常量數(shù)值填充
我們分別來看一下各種方法:
#(1)邊界填充
# 先指定在上下左右分別填充的大小
top_size,bottom_size,left_size,right_size = (50,50,50,50)
# 填充函數(shù)cv2.copyMakeBorder(輸入圖像,填充多少,borderType=填充方法)# 復(fù)制
img1 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE)
# 反射
img2 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REFLECT)
# 反射101
img3 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REFLECT_101)
# 外包裝
img4 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_WRAP)
# 常量填充,value=0
img5 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_CONSTANT,value=0)# 繪圖
import matplotlib.pyplot as plt
# 顯示中文宋體
plt.rcParams['font.sans-serif'] = ['SimSun']
# 設(shè)置畫板大小
plt.figure(figsize=(10,7))
# 原圖
plt.subplot(231),plt.imshow(img),plt.title('原圖')
# 復(fù)制
plt.subplot(232),plt.imshow(img1),plt.title('復(fù)制')
# 反射
plt.subplot(233),plt.imshow(img2),plt.title('反射')
# 反射101
plt.subplot(234),plt.imshow(img3),plt.title('反射101')
# 外包裝
plt.subplot(235),plt.imshow(img4),plt.title('外包裝')
# 常量填充
plt.subplot(236),plt.imshow(img5),plt.title('常量0填充')
我們從圖中可以看出不同方法的區(qū)別。可能有同學(xué)可能會問,這顏色怎么這么奇怪。注意,在opencv中圖像的顏色通道是BGR組成的,而matplot中顏色通道是RGB構(gòu)成,在展示圖像時,會有顏色的差別,所以盡量用opencv的圖像展示方法。
2. 數(shù)值計算
2.1 直接相加
兩張圖片直接做加法,需要兩張圖像的size一樣大,對應(yīng)的像素點相加,由于每個像素點值的大小在0-255之間,因此相加后大于255的像素值自動減去255,如150+150=300,沒有300的像素值,自動變成45。如果一張圖像整體加上一個常量,即每個元素的增加一個常量值,亮度提升。
# 先讀入2張圖片
img1 = cv2.imread(filepath+'\\sit1.jpg')
img2 = cv2.imread(filepath+'\\wise2.jpg')
# ==1== 直接相加超過255的像素值會自動減去255
# 對img1上的所有像素點加10,整體的shape不變
img3 = img1+10
cv_show('img3',img3)
# 將兩張圖相加,兩張圖的shape需要一致
img4 = img1+img2
cv_show('img4',img4)
# 由于圖中的每個像素點的取值是在0-255之間,如果超過255會自動減去255
size相同的兩幅圖像直接相加后的結(jié)果為
2.2 使用函數(shù)相加 cv2.add()
cv2.add(src1, src2)
要求兩張圖象的size和通道數(shù)相同。對應(yīng)像素值相加,相加后,超過255的數(shù)值就讓它等于255
?src1, src2:兩幅圖像相加,或一張圖像加一個數(shù)值
?mask:圖像掩膜,為8位單通道的灰度圖像,用于指定要更改的輸出圖像數(shù)組的元素,即輸出圖像像素只有mask對應(yīng)位置元素不為0的部分才輸出,否則該位置像素的所有通道分量都設(shè)置為0
dtype:輸出圖像數(shù)組的深度,即圖像單個像素值的位數(shù)(如RGB用三個字節(jié)表示,則為24位)。
# ==2== cv2.add()
# 相加后若超過255,那像素點的值就取255
img5 = cv2.add(img1,img2)
cv_show('img5',img5)
3. 圖像融合
將兩張圖像按一定比例融合在一起,需要兩張圖像的size和通道數(shù)相同
#(3)圖像融合,兩張圖混合在一起
# 讀取兩張圖片
img1 = cv2.imread(filepath+'\\sit2.jpg')
img2 = cv2.imread(filepath+'\\wise2.jpg')
# ==1== 先查看一下兩張圖的shape
img1.shape #(503,1201,3)
img2.shape #(1080,1440,3)
3.1 改變圖像大小
指定具體的長度和高度: cv2.resize(圖像, (長, 高))
指定縮放比例: cv2.resize(圖像, (0,0), fx=沿x軸縮放比例, fy=沿y軸縮放比例)
注意制定具體的長度和高度時,一定是先指定寬再指定長,如下?cv2.resize(img2,(1201,503)),把img2變成高為503長為1201,而我們.shape查到的結(jié)果是(高, 長)
# ==2== 改變大小cv2.resize(圖像,指定大小),接收返回值
# 注意先指定寬,再指定高
# 將img2變得和img1的size一樣
img2 = cv2.resize(img2,(1201,503))
img2.shape
# 不指定具體數(shù)值,只給出倍數(shù)關(guān)系,即圖像沿x和y軸的縮放比例
img4 = cv2.resize(img2,(0,0),fx=3,fy=3)
cv_show('name', img4)
3.2 圖像融合
兩張圖像按一定比例融合:?cv2.addWeighted(圖像1, 權(quán)重1, 圖像2, 權(quán)重2, 亮度偏置)
相當于 y = a x1 + b x2 + c,其中a、b代表權(quán)重,c代表亮度上提亮多少
img5 = cv2.addWeighted(img1,0.5,img3,0.4,0)
cv_show('img5',img5)
4. 圖像閾值
首先我們把需要用到的圖像和庫導(dǎo)入一下
import cv2
import matplotlib.pyplot as plt
# 指定圖像所在文件夾
filepath = 'C:\\...\\opencv\\img'
# 轉(zhuǎn)換成灰度
img = cv2.imread(filepath+'\\wise3.jpg',cv2.IMREAD_GRAYSCALE)
圖像閾值處理函數(shù):?ret, dst = cv2.threshold(src, thresh, maxval, type)
參數(shù):
src:??輸入圖,只能輸入單通道圖像,通常是灰度圖
dst:? 輸出圖
thresh:??閾值,是一個值,通常為127
maxval:??當圖像超過了閾值或低于閾值(由type決定),所賦予的值
type:??二值化操作的類型,包含:
cv2.THRESH_BINARY ?二值法,超過閾值thresh部分取maxval(設(shè)定的最大值),否則取0
cv2.THRESH_BINARY_INV??超過閾值的部分取0,小于閾值取maxval
cv2.THRESH_TRUNC ?截斷,大于閾值的部分設(shè)為閾值,小于閾值的不變
cv2.THRESH_TOZERO ?大于閾值的部分不變,小于閾值的部分變成0。亮的部分不變,暗的部分變成黑點
cv2.THRESH_TOZERO_INV ?大于閾值的變成0,小于閾值的不變。暗的部分不變,亮的部分變成黑點
返回值
ret:??閾值
dst:??輸出圖
# 方法1:輸入灰度圖,閾值127,大于閾值變成255,小于閾值變成0
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
# 方法2:大于閾值127變成0,小于閾值變成255。原本比較亮的變成黑點,原來暗的變成白點
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
# 方法3:大于閾值127的設(shè)為閾值,小于閾值的不變
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
# 方法4:大于閾值127的值變成127,小于127的值不變
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
# 方法5:小于127的值不變,大于127的值變成0
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)# 繪圖
titles=['original','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images=[img,thresh1,thresh2,thresh3,thresh4,thresh5]
plt.figure(figsize=(8,8))
for i in range(6):plt.subplot(2,3,i+1)plt.imshow(images[i],'gray')plt.title(titles[i])
plt.show()
總結(jié)
以上是生活随笔為你收集整理的【opencv】(2) 图像处理:边界填充、图像融合、图像阈值、数值计算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【opencv】(1) 基础操作:图像视
- 下一篇: 【opencv】(3) 图像滤波:均值、