OpenCV—python 自動色彩均衡(ACE)

一、ACE算法理論

圖像對比度增強的算法在很多場合都有用處,特別是在醫學圖像中,這是因爲在衆多疾病的診斷中,醫學圖像的視覺檢查時很有必要的。醫學圖像由於本身及成像條件的限制,圖像的對比度很低。因此,在這個方面已經開展了很多的研究。這種增強算法一般都遵循一定的視覺原則。衆所周知,人眼對高頻信號(邊緣處等)比較敏感。雖然細節信息往往是高頻信號,但是他們時常嵌入在大量的低頻背景信號中,從而使得其視覺可見性降低。因此適當的提高高頻部分能夠提高視覺效果並有利於診斷。

ACE在圖像處理方面可以有兩種,
一種是:Automatic Color Equalization,即自動彩色均衡。【論文與代碼】
一種是:Adaptive Contrast Enhancement,即自適應對比度增強

高動態範圍圖像是指在一幅圖像中,既有明亮的區域又有陰影區域,爲了使細節清晰,需要滿足以下幾點:

  1. 對動態範圍具有一定的壓縮能力;
  2. 對亮暗區域的細節有一定的顯示能力;
  3. 滿足上面條件基礎上不破壞圖像的清晰度。

對於高動態範圍處理,基於人眼視覺系統(HSV)在顏色連續和亮度連續方面得到較好的滿足。該算法考慮了圖像中顏色和亮度的空間位置關係,進行局部的自適應濾波,實現具有局部和非線性特徵的圖像亮度,色彩與對比度調整,同時滿足灰度世界理論和白斑點假設。

算法原理
Rizzi等依據Retinex理論提出了自動顏色均衡算法,該算法考慮了圖像中顏色和亮度的空間位置關係,進行局部特性的自適應濾波,實現具有局部和非線性特徵的圖像亮度與色彩調整和對比度調整,同時滿足灰色世界理論假設和白色斑點假設。

1.1 ACE算法
  1. 獲得空域重構圖像
    對圖像進行色彩/空域調整,完成圖像的色差矯正,得到空域重構圖像:

Rc=jsubset,jpr(Ic(p)Ic(j))d(p,j)(1)R_c = \sum_{j\in subset,j \neq p }\frac{r(I_c(p) - I_c(j))}{d(p,j)} \tag{1}

  1. 其中Rc(p)Rc(p)是中間結果,Ic(p)Ic(j)I_c(p) - I_c(j)爲2個點的亮度差,d(p,j)d(p,j) 表示距離度量函數,r()r(∗) 爲亮度表現函數,需要是奇函數,這一步可以適應局部圖像對比度,r()r(∗) 可以放大較小的差異,並豐富大的差異,根據局部內容擴展或者壓縮動態範圍。一般的,r()r(∗) 爲:
    r(x)={1x<Tx/TTxT1x>Tr(x) = \left\{\begin{matrix} 1 & x<-T\\ x/T & -T \leqslant x \leqslant T\\ -1 & x>T \end{matrix}\right.

  2. 對校正後的圖像進行動態擴展。ACE算法是對單一色道進行的,對於彩色圖片需要對每一個色道分別處理。一種簡單的線性擴展可以表示爲:
    Oc(p)=round[127.5+scRc(p)](2)O_c(p) = round[127.5+s_cR_c(p)] \tag{2}
    其中:scs_c斜率爲:[(mc,0),(mc,255)][(m_c,0),(m_c,255)]Mc=maxp[Rc(p)]mc=minp[Rc(p)]M_c = \max_{p}[R_c(p)],m_c = \min_{p}[R_c(p)]

    還可以將其映射到 [0,255][0,255]的空間中:
    L(x)=R(x)minRmaxRminRL(x) = \frac{R(x) - \min R}{ \max R - \min R}

自動彩色均衡算法改進:
式(1)算法複雜度較高,對於一副像素數爲N的圖像,需要執行O(N2)級次非線性映射計算,圖像尺寸越大,耗時越多,所以針對式(1)產生了許多加速改進算法。例如:LLLUT加速策略,使用快速傅里葉變換替換卷積,將ACE轉換爲對規範直方圖均衡化的一種平滑和局部修正的方法,並給出了求解最優模型:
argminI12x(I(x)12)214Mxyxω(x,y)Sα(I(x)I(y))arg \min_I\frac{1}{2}\sum_{x}(I(x)-\frac{1}{2})^2 -\frac{1}{4M}\sum_x\sum_{y\neq x}\omega(x,y)S\alpha (I(x)-I(y))

其中:
Sα=sαS_{\alpha }' = s_\alpha
ω=1/xy\omega =1/||x-y||
M=maxxR(x)M = \max_xR(x)

對於改進方法,可以考慮的因素:

  1. 其他的坡度函數SαS \alpha,多項式函數逼近;
  2. 除了 1/xy1/||x-y|| 外的權重函數的選擇;
  3. 在求和的過程中,y 可以限制在一個小窗口中;
  4. L(x)L(x) 的一些其他的方法;

多項式逼近展示:
在這裏插入圖片描述

二、快速ACE算法

2.1 原理

ACE的增強效果普遍與retinex好。需要注意的是,ACE中當前像素是與整個圖像的其他像素做差分比較,計算複雜度非常非常高,這也是限制它應用的最主要原因。
本文主要基於兩個假設:
(1)對一副圖像ACE增強後得到輸出Y,如果對Y再進行一次ACE增強,輸出仍然是Y本身;
(2)對一副圖像的ACE增強結果進行尺寸縮放得到Y,對Y進行ACE增強,輸出仍然是Y本身。

如果上面假設成立,我們就可以對圖像進行縮放得到 I1I_1,對 I1I_1 的ACE增強結果進行尺度放大(與I尺寸一樣)得到Y1Y_1,那麼 YYY1Y_1 是非常接近的,我們只需要在Y1基礎上進一步處理即可。
這裏就又引申了兩個細節問題:

  1. 如何快速的求 I1I_1 的ACE增強結果?
    其實很簡單,對它再次縮放得到 I2I_2 ,求 I2I_2 的增強結果,依次類推,就是金字塔結構思想。
  2. 如何在 Y1Y_1 基礎上進一步處理得到 YY
    因爲是在整個圖像域進行差分比較運算,與近處鄰域像素的比較構成了YY的細節信息,與遠處像素的比較構成了YY的全局背景信息,那麼我們合理假設,YYY1Y_1的全局背景信息相同,只更新細節信息即可,也就是,我們需要在Y1Y_1基礎上加上 II 中鄰近像素的差分結果,並減去Y1Y_1中鄰近像素的差分結果就是最終的輸出 YY

爲敘述方便,這裏假設後面的圖像都是歸一化到 [0,1] 之間的浮點數圖像。
ACE算法的計算公式爲:
Y=g(I(x0)I(x))w(x0,x)Y = \frac{ \sum g(I(x_0)-I(x))}{\sum w(x_0,x)}

其中:
xIx\in I
ww是權重參數,離中心點像素越遠w值越小,可以直接取值歐氏距離。
g()g()是相對對比度調節參數,非線性的,簡單取如下計算方法:
g(x)=max(min(ax,1.0),1.0)g(x) = \max(\min(ax, 1.0), -1.0)
a是控制參數,值越大,細節增強越明顯。計算完後,還要對Y進行一次歸一化即可得到最終的增強圖像。
2.2 代碼演示
import cv2
import numpy as np
import math
 
def stretchImage(data, s=0.005, bins = 2000):    #線性拉伸,去掉最大最小0.5%的像素值,然後線性拉伸至[0,1]
    ht = np.histogram(data, bins);
    d = np.cumsum(ht[0])/float(data.size)
    lmin = 0; lmax=bins-1
    while lmin<bins:
        if d[lmin]>=s:
            break
        lmin+=1
    while lmax>=0:
        if d[lmax]<=1-s:
            break
        lmax-=1
    return np.clip((data-ht[1][lmin])/(ht[1][lmax]-ht[1][lmin]), 0,1)
 
g_para = {}
def getPara(radius = 5):                        #根據半徑計算權重參數矩陣
    global g_para
    m = g_para.get(radius, None)
    if m is not None:
        return m
    size = radius*2+1
    m = np.zeros((size, size))
    for h in range(-radius, radius+1):
        for w in range(-radius, radius+1):
            if h==0 and w==0:
                continue
            m[radius+h, radius+w] = 1.0/math.sqrt(h**2+w**2)
    m /= m.sum()
    g_para[radius] = m
    return m
 
def zmIce(I, ratio=4, radius=300):                     #常規的ACE實現
    para = getPara(radius)
    height,width = I.shape
    zh,zw = [0]*radius + range(height) + [height-1]*radius, [0]*radius + range(width)  + [width -1]*radius
    Z = I[np.ix_(zh, zw)]
    res = np.zeros(I.shape)
    for h in range(radius*2+1):
        for w in range(radius*2+1):
            if para[h][w] == 0:
                continue
            res += (para[h][w] * np.clip((I-Z[h:h+height, w:w+width])*ratio, -1, 1))
    return res
 
def zmIceFast(I, ratio, radius):                #單通道ACE快速增強實現
    height, width = I.shape[:2]
    if min(height, width) <=2:
        return np.zeros(I.shape)+0.5
    Rs = cv2.resize(I, ((width+1)/2, (height+1)/2))
    Rf = zmIceFast(Rs, ratio, radius)             #遞歸調用
    Rf = cv2.resize(Rf, (width, height))
    Rs = cv2.resize(Rs, (width, height))
 
    return Rf+zmIce(I,ratio, radius)-zmIce(Rs,ratio,radius)    
            
def zmIceColor(I, ratio=4, radius=3):               #rgb三通道分別增強,ratio是對比度增強因子,radius是卷積模板半徑
    res = np.zeros(I.shape)
    for k in range(3):
        res[:,:,k] = stretchImage(zmIceFast(I[:,:,k], ratio, radius))
    return res
 
if __name__ == '__main__':
    m = zmIceColor(cv2.imread('p4.bmp')/255.0)*255
    cv2.imwrite('zmIce.jpg', m)

鳴謝
文獻地址:https://www.researchgate.net/publication/253622155_Real-Time_Adaptive_Contrast_Enhancement_For_Imaging_Sensors
C++:https://blog.csdn.net/weixin_45709330/article/details/104447450
論文與源碼:http://www.ipol.im/pub/art/2012/g-ace/
https://blog.csdn.net/zmshy2128/article/details/53470357#comments
https://www.cnblogs.com/Imageshop
https://blog.csdn.net/weixin_45709330/article/details/104447336

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章