1. 程式人生 > >【數字影象處理系列二】基本概念:亮度、對比度、飽和度、銳化、解析度

【數字影象處理系列二】基本概念:亮度、對比度、飽和度、銳化、解析度



在上文【數字影象處理系列一】opencv-python快速入門篇 中結合了opencv-python對數字影象的基本操作有了一定的瞭解,本文我們將一起過數字影象概念和形成原理,並探討一下亮度、對比度、解析度、飽和度、銳化等基本屬性

來~幹~,上一張程式截圖:
在這裡插入圖片描述



一、何為數字影象


1、數字影象定義

對於一幅影象,我們可以將其放入座標系中,這裡取影象左上定點為座標原點,x 軸向右,和笛卡爾座標系x軸相同;y 軸向下,和笛卡爾座標系y軸相反。這樣我們可將一幅影象定義為一個二維函式 f(x,y),影象中的每個畫素就可以用 (x,y) 座標表示,而在任何一對空間座標 (x,y) 處的幅值 f 稱為影象在該點的強度或灰度,當 x,y 和灰度值 f 是有限離散數值時,便稱該影象為 數字影象

2、數字影象形成過程

我們平時見到的多數影象都是有照射源和形成影象的場景元素對光能的反射和吸收而產生的,得到我們可見的數字影象分為一下幾個步驟:

(1) 影象感知和獲取

照射源入射光線照射到物體,經過反射或是折射光纖進入到人眼中,然後看到物體。而將照射能量轉化為數字影象便需要用到感測器,主要的感測器有:

  • 單個成像感測器
  • 條帶感測器
  • 陣列感測器

原理很簡單: 就是通過將輸入電能和對特殊型別檢測能源敏感的感測器材料相結合,把輸入能源轉化為電壓,輸出的電壓波再經過取樣和量化便可得到離散的數字影象 f(x,y)

注:由圖形形成模型來理解一下灰度級或強度級,請看下面

上面我們提到影象可由而為函式 f(x,y) 表示,其物體意義其實就來自於照射源對物體的照射,函式 f(x,y) 可由兩個分量來表示:

  • 入射到被觀察場景的光源照射總量
  • 場景中物體所反射的光源總量

上述兩個分量分別稱為入射分量和反射分量,表示為 i(x,y)、r(x, y),有:
在這裡插入圖片描述
其中:

在這裡插入圖片描述
在這裡插入圖片描述

因此影象的灰度值或強度值是由入射分量和反射分量決定的,i(x,y) 的性質取決於照射源,而r(x, y) 的性質取決於成像物體的特性,公式只是給出了 i(x,y)、r(x, y) 的一般取值範圍,自然對於不同的照射源和成像物體則 i(x,y)、r(x, y) 會有不同的取值,因此數字影象灰度取值範圍便是:
在這裡插入圖片描述
在這裡插入圖片描述
因此區間[Lmin,Lmax]便稱為影象的灰度級,實際情況下常常令該區間為[0,L-1],其中f=0時為黑色,f=L-1時在灰度級中為白色,所有中間值是從黑色到白色之間變化的灰度色調,而影象最高和最低灰度級之間的灰度差便為對比度


(2) 影象取樣和量化

為了產生一幅數字影象,我們需要把連續的感知資料轉化為數字形式,便是:取樣和量化。取樣和量化目的便是為了將連續的感知資料離散化,而且影象的質量在很大程度上也取決於取樣和量化中所用的樣本數和灰度級,想了解詳細過程請參考:影象的取樣與量化及灰度直方圖


(3) 顯示數字影象

數字影象f(x,y)主要有三種表示方式:

  • 畫為三維表面影象,如下圖2.18(a)
  • 視覺化灰度陣列影象,如下圖2.18(b)
  • 二維數值陣列影象,如下圖2.18(c )

在這裡插入圖片描述




二、亮度、對比度、飽和度、銳化、解析度


畫重點啦: 影象亮度、對比度、飽和度和銳化之間並不是彼此獨立的,改變其中一個特徵可能會同時引起影象其他特徵的變化,至於變化的程度取決於影象本身的特性,先建立一個概念,在後面的會在詳述

1、亮度

影象亮度通俗理解便是影象的明暗程度,數字影象 f(x,y) = i(x,y) r(x, y) ,如果灰度值在[0,255]之間,則 f 值越接近0亮度越低,f 值越接近255亮度越高。而且我們也要把亮度和對比度區分開來,正如上述提的對比度指的是最高和最低灰度級之間的灰度差。下面通過圖片感受一下亮度變化對數字影象的影響:
在這裡插入圖片描述

上面白色和紅色兩幅圖中,圖的右邊相對於左邊增加了亮度,可以看出影象右邊相對於左邊亮度有了一個整體的提升,這裡只是對亮度做了一個小弧度的提升,我們嘗試著將亮度提升的更高,如下圖:
在這裡插入圖片描述

這裡需要強調的是如果我們對亮度做這麼一個劇烈的改變,那麼便會在改變圖片強度的同時也影響了圖片的飽和度、對比度和清晰度,此時兩個圖片右邊部分飽和度、對比度和清晰度都降低了,原因是過度增加亮度導致陰影趕上了高光,因為最大灰度值是固定的,所以最低灰度值快趕上了最大灰度值,因此影響了圖片的飽和度、對比度和清晰度


2、對比度和飽和度

(1) 飽和度指的是影象顏色種類的多少, 上面提到影象的灰度級是[Lmin,Lmax],則在Lmin、Lmax 的中間值越多,便代表影象的顏色種類多,飽和度也就更高,外觀上看起來影象會更鮮豔,調整飽和度可以修正過度曝光或者未充分曝光的圖片。使影象看上去更加自然

(2) 對比度上面已經介紹過,指的是影象暗和亮的落差值,即影象最大灰度級和最小灰度級之間的差值,看下圖:
在這裡插入圖片描述
上面白色和紅色輻條影象的右側都增加了對比度,但我們可以看出右側的白色輻條或是紅色輻條隨著對比度的增加,白/紅色輻條都變亮了,背景變暗了,影象看起來更加清晰。


但注意:在紅色輻條中增加對比度同時也增加了飽和度,但白色輻條的飽和度沒有隨著亮度的增加而增加,這印證了前面說的變化的程度取決於影象本身的特性。因為飽和度對於具有鮮豔顏色,顏色豐富的影象影響很大,而對於暗淡的顏色或幾乎是中性顏色影響較小


3、銳化

影象銳化是補償影象的輪廓,增強影象的邊緣及灰度跳變的部分,使影象變得清晰。影象銳化在實際影象處理中經常用到,因為在做影象平滑,影象濾波處理的時候經過會把丟失影象的邊緣資訊,通過影象銳化便能夠增強突出影象的邊緣、輪廓

再通過下圖來觀察一下影象銳化效果:
在這裡插入圖片描述

從山圖中我們可以看出影象白色、紅色輻條的接近中心的細輻條亮度、對比度和飽和度也有了明顯的提升,但外側確沒有太明顯的變化,這是因為影象銳化會更多的增強邊緣資料,因此影響也就更加明顯


小結一下:上面三個小節分別對影象的亮度、對比度、飽和度、銳化的概念做了基本的闡述,同時配圖也著重強調了影象的亮度、對比度、飽和度、銳化之間也不是完全孤立存在的,是會互相影響的,So明白了他們之間的相互影響,在以後做數字影象處理的時候能根據更好的去調節影象亮度、對比度、飽和度、銳化這些屬性

4、解析度

不太規範的說影象解析度可以看成是影象的大小,解析度高影象就大,更清晰反之解析度低影象就小。官方說法:影象解析度指影象中儲存的資訊量,是每英寸影象內有多少個畫素點,即:畫素每英寸,單位為PPI(Pixels Per Inch),因此放大影象便會增強影象的解析度,影象解析度大影象更大,更加清晰,例如:一張圖片解析度是500x200,也就是說這張圖片在螢幕上按1:1放大時,水平方向有500個畫素點(色塊),垂直方向有200個畫素點(色塊)




三、影象亮度、對比度、飽和度、銳化、解析度調節示例


先畫個重點:

  • 影象對比度調節可以直接在RGB空間利用變換公式 g(i,j)= af(i,j) + b 對影象進行線性變化;
  • 影象飽和度通常在RGB色彩空間調整不是很直觀,而HSL彩色空可以很直觀表示出每個畫素的飽和度,所以對於飽和度的調節,首先讀取影象的畫素RGB值然後再轉換到HSL空間得到飽和度與亮度值,調整以後再從HSL空間轉換到RGB空間的RGB值,完成影象飽和度調整
  • 影象銳化通常分為利用空間濾波器銳化影象、利用頻域濾波器銳化影象,將在後續文章影象濾波中做詳細闡述,本文不討論

1、RGB空間影象亮度、對比度調節

對於數字影象變換,設原畫素灰度為 f(i,j),轉化後的畫素灰度為 g(i,j),則常用的線性變換是 g(i,j)= af(i,j) + b, 其中係數 a 影響影象的對比度,係數 b 影響影象的亮度,具體如下:
(1) a=1時是原圖;
(2) a>1時對比度增強,影象看起來更加清晰;
(3) a<1時對比度減弱,影象看起來變暗;
(4) b影響影象的亮度,隨著增加b (b>0)和減小b (b>0),影象整體的灰度值上移或者下移, 也就是影象整體變亮或者變暗, 不會改變影象的對比度

上程式碼:

import cv2
import imutils
import numpy as np

def c_and_b(arg):
    ''''''
    cnum = cv2.getTrackbarPos(trackbar_name1, wname)
    bnum = cv2.getTrackbarPos(trackbar_name2, wname)
    #print(bnum)
    cimg = np.ones((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            lst = 0.1*cnum*img[i, j] + bnum
            cimg[i, j] = [int(ele) if ele < 255 else 255 for ele in lst]
    cv2.imshow(wname, imutils.resize(cimg, 800))

wname = 'brightness and contrast'
trackbar_name1 = 'contrast'
trackbar_name2 = 'brightness'
img = cv2.imread("E:/peking_rw/ocr_project/base_prehandle/img/li.jpg")
height, width = img.shape[:2]
img = cv2.resize(img, (int(width/height*400), 400), interpolation=cv2.INTER_CUBIC)

cv2.namedWindow(wname)
cv2.createTrackbar(trackbar_name1, wname, 10, 20, c_and_b)
cv2.createTrackbar(trackbar_name2, wname, 0, 100, c_and_b)

c_and_b(0)
if cv2.waitKey(0) == 27:
    cv2.destroyAllWindows()

執行效果如下:

在這裡插入圖片描述


2、HSL空間影象亮度、飽和度調節

HSL空間:代表色相,飽和度,明度三個通道的顏色。 H: Hue 色相、 S:Saturation 飽和度、 L :Lightness 明度。例如:歸一化後二維數字影象(0, 0)畫素的值為(0.2,0.3,0.4),則代表H=0.2,S=0.3,L=0.4

上程式碼:

import cv2
import imutils
import numpy as np

def s_and_b(arg):
    lsImg = np.zeros(image.shape, np.float32)
    hlsCopy = np.copy(hlsImg)
    l = cv2.getTrackbarPos('l', 'l and s')
    s = cv2.getTrackbarPos('s', 'l and s')
    #1.調整亮度飽和度(線性變換)、 2.將hlsCopy[:,:,1]和hlsCopy[:,:,2]中大於1的全部擷取
    hlsCopy[:, :, 1] = (1.0 + l / float(MAX_VALUE)) * hlsCopy[:, :, 1]
    hlsCopy[:, :, 1][hlsCopy[:, :, 1] > 1] = 1
    #HLS空間通道2是飽和度,對飽和度進行線性變換,且最大值在255以內,這一歸一化了,所以應在1以內
    hlsCopy[:, :, 2] = (1.0 + s / float(MAX_VALUE)) * hlsCopy[:, :, 2]
    hlsCopy[:, :, 2][hlsCopy[:, :, 2] > 1] = 1
    # HLS2BGR
    lsImg = cv2.cvtColor(hlsCopy, cv2.COLOR_HLS2BGR)
    # 顯示調整後的效果
    cv2.imshow("l and s", imutils.resize(lsImg, 650))
    
image = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/cartoon.jpg', 1)
# 影象歸一化,且轉換為浮點型, 顏色空間轉換 BGR轉為HLS
fImg = image.astype(np.float32)
fImg = fImg / 255.0
#HLS空間,三個通道分別是: Hue色相、lightness亮度、saturation飽和度
#通道0是色相、通道1是亮度、通道2是飽和度
hlsImg = cv2.cvtColor(fImg, cv2.COLOR_BGR2HLS)

l, s, MAX_VALUE = 100, 100, 100
cv2.namedWindow("l and s", cv2.WINDOW_AUTOSIZE)
cv2.createTrackbar("l", "l and s", l, MAX_VALUE, s_and_b)
cv2.createTrackbar("s", "l and s", s, MAX_VALUE, s_and_b)

s_and_b(0)
if cv2.waitKey(0) == 27:
    cv2.destroyAllWindows()

執行效果如下:

在這裡插入圖片描述


3、影象解析度調節

影象解析度調節就比較簡單了,經常使用,opencv-python中自帶了resize函式可以對影象的解析度進行調節,resize函式官方給出定義:

cv2.resize(img, (width,  height),  interpolation = cv2.INTER_LINEAR)

引數一: 影象物件
引數二: (width, height)輸入的影象的寬度和高度
引數三: 使用何種差值方式對影象進行縮放,由一下常用幾種

  • cv2.INTER_LINEAR: 雙線性插值,預設情況使用
  • cv2.INTER_NEAREST: 最鄰近插值
  • cv2.INTER_AREA: 使用畫素區域關係重新取樣,和cv2.INTER_NEAREST相似
  • cv2.INTER_CUBIC: 4x4畫素鄰域內的雙立方插值
import cv2
import imutils
import numpy as np

rgb_img = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/li.jpg')
height, width = rgb_img.shape[:2]
rgb_img = cv2.resize(rgb_img, (int(width/height*100), 100), interpolation=cv2.INTER_CUBIC)
cv2.imshow('resize image', rgb_img))
if cv2.waitKey(0) == 27:
    cv2.destroyAllWindows()

影象解析度調節效果
在這裡插入圖片描述




四、總結


總結一下本文所學習的知識點:

  • 數字影象的定義
  • 數字影象的形成過程
  • 數字影象亮度、對比度、飽和度、銳化、解析度概念以及亮度、對比度、飽和度、銳化之間相互影響的關係
  • 數字影象亮度、對比度、飽和度、解析度調節示例演示

本文分享結束,有問題歡迎交流學習,大家也可以關注我的微信公眾號,一起交流學習:
在這裡插入圖片描述