最近上班遇到一些圖片顏色偏離原色,
身為影像工程從業者就會想自己寫 3A算法來校正。
而自動白平衡便是 3A 中的其中 1A – 南湖大山!
而自動白平衡便是 3A 中的其中 1A – Auto White Balance
自動白平衡的核心就是解決圖片色偏的方法,
大都是找到圖片中的參考值,
再用參考值及不同方法去對整張圖片做校正。
像是灰色世界算法就是拿全圖片的加總的三通道均值當作參考值,
再拿這個參考值除以三通道分別均值做成三通道的增益,
得到三通道增益後分別對通道相乘。
今天提到的完美反射核心,它的概念是相信圖片中有一群接近白色的區塊,
因為 RGB or BRG 的世界裡面 (255, 255, 255) 就是白色嘛,
所以有點像找到這塊邊長為 255 的正方形中那群最遠離原點 (0, 0, 0) 的那群點。
找到那群點後,再求得這群的均值作為參考值,
參考值除以各通道的均值就能得到各通道的增益,
最後再拉回去與原圖相乘 -> 結案。
  
def AutoWhiteBalance_PRA(imgPath, ratio=0.2): # 自動白平衡演算法_完美反射核心, 0 < ratio <1.
    BGRimg = cv2.imread(imgPath)
    BGRimg = BGRimg.astype(np.float32)    # 將資料格式轉為 float32,避免 OpenCV 讀圖進來為 np.uint8 而造成後續截斷問題。
    pixelSum = BGRimg[:,:,0] + BGRimg[:,:,1] + BGRimg[:,:,2]     
    pexelMax = np.max(BGRimg[:,:,:])    # 求三通道加總最大值作為像素值拉伸指標
    
    row , col, chan = BGRimg.shape[0], BGRimg.shape[1], BGRimg.shape[2]
    
    pixelSum = pixelSum.flatten()
    imgFlatten = BGRimg.reshape(row*col, chan)
    
    thresholdNum =  int(ratio * row * col)
    thresholdList = np.argpartition(pixelSum, kth=-thresholdNum, axis=None)    # 由右至左設定閾值位置,並得到粗略排序後的索引表。
    thresholdList = thresholdList[-thresholdNum:]    # 取得索引表中比閾值大的索引號
    
    blueMean, greenMean, redMean, i = 0, 0, 0, 0
    
    for i in thresholdList:
        blueMean  += imgFlatten[i][0]
        greenMean += imgFlatten[i][1]
        redMean   += imgFlatten[i][2]
    
    blueMean  /= thresholdNum
    greenMean /= thresholdNum
    redMean   /= thresholdNum
    blueGain  = pexelMax / blueMean
    greenGain = pexelMax / greenMean
    redGain   = pexelMax / redMean
    
    BGRimg[:,:,0] = BGRimg[:,:,0] * blueGain
    BGRimg[:,:,1] = BGRimg[:,:,1] * greenGain
    BGRimg[:,:,2] = BGRimg[:,:,2] * redGain
    BGRimg = np.clip(BGRimg, 0, 255)
    BGRimg = BGRimg.astype(np.uint8)
    return BGRimg
取值範圍直接變成 [0, 255]















































