OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
改變影像的對比度和亮度!

上一個教程: 使用OpenCV新增(混合)兩幅影像
下一個教程: 離散傅立葉變換

原始作者Ana Huamán
相容性OpenCV >= 3.0

目標

在本教程中,您將學習如何

  • 訪問畫素值
  • 用零初始化矩陣
  • 瞭解 cv::saturate_cast 的作用以及為何有用
  • 獲取一些關於畫素變換的重要資訊
  • 在實際示例中提升影像亮度

理論

注意
下面的解釋摘自 Richard Szeliski 的著作 計算機視覺:演算法與應用

影像處理

  • 一般的影像處理運算子是一個函式,它接受一個或多個輸入影像並生成一個輸出影像。
  • 影像變換可視為
    • 點運算子(畫素變換)
    • 鄰域(基於區域)運算子

畫素變換

  • 在這類影像處理變換中,每個輸出畫素的值僅取決於相應的輸入畫素值(此外,可能還有一些全域性收集的資訊或引數)。
  • 此類運算子的示例包括亮度與對比度調整以及色彩校正和變換。

亮度與對比度調整

  • 兩種常用的點處理是與常數進行乘法加法運算

    \[g(x) = \alpha f(x) + \beta\]

  • 引數 \(\alpha > 0\) 和 \(\beta\) 通常被稱為增益偏置引數;有時這些引數被認為分別控制對比度亮度
  • 您可以將 \(f(x)\) 視為源影像畫素,將 \(g(x)\) 視為輸出影像畫素。然後,我們可以更方便地將表示式寫為

    \[g(i,j) = \alpha \cdot f(i,j) + \beta\]

    其中 \(i\) 和 \(j\) 表示畫素位於第 i 行和第 j 列。

程式碼

解釋

  • 我們使用 cv::imread 載入影像並將其儲存到 Mat 物件中
  • 現在,由於我們將對該影像進行一些變換,我們需要一個新的 Mat 物件來儲存它。此外,我們希望它具有以下特點:
    • 初始畫素值等於零
    • 與原始影像相同的大小和型別

我們觀察到 cv::Mat::zeros 根據 image.size()image.type() 返回一個 Matlab 風格的零初始化器

  • 現在,我們要求使用者輸入 \(\alpha\) 和 \(\beta\) 的值
  • 現在,為了執行操作 \(g(i,j) = \alpha \cdot f(i,j) + \beta\),我們將訪問影像中的每個畫素。由於我們處理的是 BGR 影像,每個畫素將有三個值(B、G 和 R),因此我們也將單獨訪問它們。以下是程式碼片段:

請注意以下內容(僅限 C++ 程式碼

  • 要訪問影像中的每個畫素,我們使用以下語法:image.at<Vec3b>(y,x)[c],其中 y 是行,x 是列,c 是 B、G 或 R(0、1 或 2)。
  • 由於操作 \(\alpha \cdot p(i,j) + \beta\) 可能會給出超出範圍的值或非整數值(如果 \(\alpha\) 是浮點數),我們使用 cv::saturate_cast 來確保值的有效性。
  • 最後,我們以通常的方式建立視窗並顯示影像。
注意
除了使用 for 迴圈來訪問每個畫素,我們也可以簡單地使用以下命令:

其中 cv::Mat::convertTo 會有效地執行 *new_image = a*image + beta*。然而,我們想向你展示如何訪問每個畫素。無論如何,這兩種方法都給出相同的結果,但 convertTo 更最佳化,執行速度快得多。

結果

  • 執行我們的程式碼,並使用 \(\alpha = 2.2\) 和 \(\beta = 50\)
    $ ./BasicLinearTransforms lena.jpg
    基本線性變換
    -------------------------
    * 輸入 alpha 值 [1.0-3.0]: 2.2
    * 輸入 beta 值 [0-100]: 50
  • 我們得到以下結果:

實際示例

在本段中,我們將學到的知識付諸實踐,透過調整影像的亮度和對比度來校正曝光不足的影像。我們還將介紹另一種校正影像亮度的技術,稱為伽馬校正。

亮度與對比度調整

增加(/減少)\(\beta\) 值將為每個畫素新增(/減去)一個常數值。超出 [0 ; 255] 範圍的畫素值將被飽和(即,高於 255(/低於 0)的畫素值將被限制在 255(/0))。

淺灰色為原始影像的直方圖,深灰色為 Gimp 中亮度設為 80 時的直方圖

直方圖表示每個顏色級別擁有該顏色級別的畫素數量。黑暗影像會有許多顏色值較低的畫素,因此直方圖會在其左側呈現一個峰值。當新增一個常數偏置時,由於我們為所有畫素添加了一個常數偏置,直方圖會向右移動。

\(\alpha\) 引數將改變色階的分佈方式。如果 \( \alpha < 1 \),色階將被壓縮,結果將是對比度較低的影像。

淺灰色為原始影像的直方圖,深灰色為 Gimp 中對比度設為 < 0 時的直方圖

請注意,這些直方圖是使用 Gimp 軟體中的亮度-對比度工具獲得的。亮度工具應該與 \(\beta\) 偏置引數相同,但對比度工具似乎與 \(\alpha\) 增益不同,在 Gimp 中輸出範圍似乎是居中的(正如您可以在之前的直方圖中注意到的)。

可能會出現這樣的情況:調整 \(\beta\) 偏置會改善亮度,但同時影像會顯得略帶蒙版,因為對比度會降低。使用 \(\alpha\) 增益可以減弱這種效果,但由於飽和度,我們將在原始亮部區域丟失一些細節。

伽馬校正

伽馬校正 可透過輸入值與對映輸出值之間的非線性變換來校正影像的亮度

\[O = \left( \frac{I}{255} \right)^{\gamma} \times 255\]

由於這種關係是非線性的,其效果對所有畫素並非相同,而是取決於它們的原始值。

不同伽馬值對應的曲線圖

當 \( \gamma < 1 \) 時,原始暗部區域會更亮,直方圖將向右移動;而當 \( \gamma > 1 \) 時,效果則相反。

校正曝光不足的影像

以下影像已使用 \( \alpha = 1.3 \) 和 \( \beta = 40 \) 進行校正。

由 Visem(自己的作品)[CC BY-SA 3.0],透過維基共享資源

整體亮度得到了改善,但您可能會注意到,由於所用實現中的數值飽和(攝影中的高光裁剪),雲彩現在嚴重飽和。

以下影像已使用 \( \gamma = 0.4 \) 進行校正。

由 Visem(自己的作品)[CC BY-SA 3.0],透過維基共享資源

伽馬校正應該會減少飽和效果,因為對映是非線性的,並且不像之前的方法那樣可能出現數值飽和。

左:經過 alpha, beta 校正後的直方圖;中:原始影像的直方圖;右:經過伽馬校正後的直方圖

上圖比較了三幅影像的直方圖(三個直方圖的 Y 軸範圍不同)。您可以注意到,原始影像的大部分畫素值都集中在直方圖的低端。經過 \( \alpha \), \( \beta \) 校正後,由於飽和以及向右的偏移,我們可以在 255 處觀察到一個大峰值。經過伽馬校正後,直方圖向右移動,但暗部區域的畫素比亮部區域的畫素移動得更多(參見伽馬曲線)。

在本教程中,您已經學習了兩種調整影像對比度和亮度的簡單方法。它們是基本技術,並非旨在取代光柵圖形編輯器!

程式碼

伽馬校正程式碼

查詢表用於提高計算效能,因為只需計算一次 256 個值。

附加資源