opencv之圖像亮度變換和形態學變換(八)
文章目錄
- opencv之圖像亮度變換和形態學變換(八)
- 一、圖像亮度變換
- 1.1 亮度變換
- 1.2 線性變換
- 1.3 直接像素值修改
- 案例
- 二、形態學變換
- 2.1 核
- **2.2 腐蝕(Erosion)**
- **2.3 膨脹(Dilation)**
- **2.4 開運算(Opening)**
- **2.5 閉運算(Closing)**
- **2.6 禮帽運算(Top Hat)**
- **2.7 黑帽運算(Black Hat)**
- **2.8 形態學梯度(Morphological Gradient)**
- **核心總結**
- 案例
一、圖像亮度變換
1.1 亮度變換
在講解亮度時,需要和對比度一起來進行解釋。
對比度調整:圖像暗處像素強度變低,圖像亮處像素強度變高,從而拉大中間某個區域范圍的顯示精度。
亮度調整:圖像像素強度整體變高或者變低。
上圖中,(a)把亮度調高,就是圖片中的所有像素值加上了一個固定值;(b)把亮度調低,就是圖片中的所有像素值減去了一個固定值;?增大像素對比度(白的地方更白,黑的地方更黑);(d)減小像素對比度(整幅圖都趨于一個顏色);
OpenCV調整圖像對比度和亮度時,公式為: g ( i , j ) = α f ( i , j ) + β g(i,j)=\alpha f(i,j)+\beta g(i,j)=αf(i,j)+β。但是不能淺顯的講 α \alpha α是控制對比度, β \beta β是控制亮度的。
對比度:需要通過 α 、 β \alpha、\beta α、β一起控制。
亮度:通過 β \beta β控制。
1.2 線性變換
使用 cv2.addWeighted()
函數,可以對圖像的像素值進行加權平均,進而改變圖像的整體亮度。亮度增益可以通過向每個像素值添加一個正值來實現。
cv2.addWeighted(src1, alpha, src2, beta, gamma)
-
src1
:第一張輸入圖像,它將被賦予權重alpha
。 -
alpha
:第一個輸入圖像的權重。 -
src2
:第二張輸入圖像,它將被賦予權重beta
。 -
beta
:第二個輸入圖像的權重。 -
gamma
:一個標量,將被添加到權重求和的結果上,可用于調整總體亮度。計算公式為: dst = src1 * alpha + src2 * beta + gamma
1.3 直接像素值修改
如果只需要增加或減少固定的亮度值,可以直接遍歷圖像像素并對每個像素值進行加減操作。
使用的API:
numpy.clip(a, a_min, a_max)
用于對數組中的元素進行限定,將超出指定范圍的元素值截斷至指定的最小值和最大值之間
-
a
:輸入數組。 -
a_min
:指定的最小值,數組中所有小于a_min
的元素將被替換為a_min
。 -
a_max
:指定的最大值,數組中所有大于a_max
的元素將被替換為a_max
。
案例
案例一:
import numpy as np
import cv2 as cvimg = cv.imread("images/1.jpg")
# 使用cv2.addWeihted(src1, alpha, src2, beta, gamma)實現線性變換
"""
np.zeros_like(img) 生成與img相同形狀的零矩陣
np.ones_like(img) 生成與img相同形狀的1矩陣
np.full_like(img, n) 生成與img相同形狀的n矩陣
"""
dst = cv.addWeighted(img, 1, np.zeros_like(img), 0, 50)cv.imshow("dst", dst)
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()
案例二:
import cv2 as cv
import numpy as npwindow_name = 'Trackbar'
cv.namedWindow(window_name)# 寫一個改變圖像亮度的方法
def change(p):img = cv.imread('images/1.jpg')if img is None:print("圖像加載失敗,請檢查路徑!")return# 把滑條范圍映射到-255~255p = int(p) # 確保 p 是整數p = p / 255 * (255 - (-255)) - 255# 亮度變換dst = np.uint8(img + p)dst = np.clip(dst, 0, 255)cv.imshow(window_name, dst)# 創建滑條
cv.createTrackbar('p', 'Trackbar', 0, 255, change)# 初始化顯示
change(0) # 初始化時調用一次,確保圖像顯示cv.waitKey(0)
cv.destroyAllWindows()
二、形態學變換
形態學變換(Morphological Transformations)是一種基于形狀的簡單變換,它的處理對象通常是二值化圖像。形態學變換有兩個輸入,一個輸出:輸入為原圖像、核(結構化元素),輸出為形態學變換后的圖像。其基本操作有腐蝕和膨脹,這兩種操作是相反的,即較亮的像素會被腐蝕和膨脹。下面我們來說一下核、腐蝕與膨脹的概念。
2.1 核
自適應二值化中,我們已經接觸過核了,還記得嗎?就是那個在原圖中不斷滑動計算的3*3的小區域,那其實就是一個3*3的核。
核(kernel)其實就是一個小區域,通常為3*3、5*5、7*7大小,有著其自己的結構,比如矩形結構、橢圓結構、十字形結構,如下圖所示。通過不同的結構可以對不同特征的圖像進行形態學操作的處理。
2.2 腐蝕(Erosion)
- 作用:收縮白色區域(前景),消除小噪點、細線
- 原理:結構元素覆蓋區域內有黑即黑(取最小值)
- 效果:目標"變瘦",邊緣平滑
2.3 膨脹(Dilation)
- 作用:擴展白色區域,填補空洞、斷裂
- 原理:結構元素覆蓋區域內有白即白(取最大值)
- 效果:目標"變胖",輪廓連通
2.4 開運算(Opening)
- 操作:先腐蝕后膨脹
- 作用:消除孤立噪點、分離粘連物體
- 特點:保留原主體,去除小干擾
2.5 閉運算(Closing)
- 操作:先膨脹后腐蝕
- 作用:填充內部孔洞、閉合縫隙
- 特點:平滑輪廓,保持主體完整性
2.6 禮帽運算(Top Hat)
- 公式:原圖 - 開運算結果
- 作用:提取比背景亮的細節(如微小亮斑)
- 應用:背景均勻時的前景增強
2.7 黑帽運算(Black Hat)
- 公式:閉運算結果 - 原圖
- 作用:提取比背景暗的細節(如暗色缺陷)
- 應用:檢測深色區域或空洞
2.8 形態學梯度(Morphological Gradient)
- 公式:膨脹圖 - 腐蝕圖
- 作用:突出邊緣輪廓
- 效果:類似邊緣檢測,但更平滑
核心總結
操作 | 關鍵作用 | 典型應用場景 |
---|---|---|
腐蝕 | 消除噪點、細化物體 | 去除胡椒噪聲 |
膨脹 | 連接斷裂、填充孔洞 | 文字修復 |
開運算 | 去噪+保形 | 分離粘連細胞 |
閉運算 | 補洞+平滑 | 填充指紋斷裂 |
禮帽 | 提取亮細節 | 顯微圖像亮斑提取 |
黑帽 | 提取暗細節 | 工業缺陷檢測 |
形態學梯度 | 邊緣增強 | 目標輪廓提取 |
注:所有操作均依賴**結構元素(核)**的形狀和大小選擇!
案例
案例一:腐蝕和膨脹
import cv2 as cv
import numpy as nplong = cv.imread("images/long.png")
# 定義一個5×5的卷積核
kernel = np.ones((5,5),np.uint8)
# 腐蝕操作cv.erode(src, kernel, dst, anchor, iterations, borderType, borderValue)
# iterations表示迭代次數
dst_erode = cv.erode(long,kernel,iterations=1)# 膨脹操作cv.dilate(src, kernel, dst, anchor, iterations, borderType, borderValue)
dst_dilate = cv.dilate(long,kernel,iterations=5)cv.imshow("long",long)
cv.imshow("dst_erode",dst_erode)
cv.imshow("dst_dilate",dst_dilate)
cv.waitKey(0)
cv.destroyAllWindows()
案例二:
import cv2 as cv
import numpy as npcar = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定義一個5×5的卷積核
kernel = np.ones((5,5),np.uint8)
# 開運算 cv.morphologyEx(src,op,kernel) # 先腐蝕再膨脹
open = cv.morphologyEx(car,cv.MORPH_OPEN,kernel)
# 閉運算 cv.morphologyEx(src,op,kernel) # 先膨脹再腐蝕
close = cv.morphologyEx(car,cv.MORPH_CLOSE,kernel)# 顯示圖像
cv.imshow("car",car)
cv.imshow("open",open)
cv.imshow("close",close)
cv.waitKey(0)
cv.destroyAllWindows()
案例三:
import cv2 as cv
import numpy as npcar = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定義一個5×5的卷積核
kernel = np.ones((5,5),np.uint8)
# 禮帽運算cv.morphologyEx(src,op,kernel) 原圖減"開運算"
dst_top = cv.morphologyEx(car,cv.MORPH_TOPHAT,kernel)# 黑帽運算cv.morphologyEx(src,op,kernel) "閉運算"的結果圖與原圖像之差
dst_black = cv.morphologyEx(car,cv.MORPH_BLACKHAT,kernel)cv.imshow("car",car)
cv.imshow("dst_top",dst_top)
cv.imshow("dst_black",dst_black)
cv.waitKey(0)
cv.destroyAllWindows()
案例四:
import cv2 as cv
import numpy as npcar = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定義一個5×5的卷積核
kernel = np.ones((5,5),np.uint8)
# 形態學梯度 cv2.morphologyEx(src,op,kernel) 像素點在膨脹后的圖像值與其在腐蝕后的圖像值之差
gradient = cv.morphologyEx(car,cv.MORPH_GRADIENT,kernel)
cv.imshow("gradient",gradient)
cv.imshow("car",car)
cv.waitKey(0)
cv.destroyAllWindows()