国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)

這篇具有很好參考價(jià)值的文章主要介紹了基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

線性變換

假設(shè)輸入圖像為I,寬為W,高為H,輸出圖像為O,圖像的線性變換可以用以下公式定義:
O ( r , c ) = a × I ( r , c ) + b , 0 ≤ r < H , 0 ≤ c < W O(r, c) = a × I(r, c) + b, 0 ≤ r < H, 0 ≤ c < W O(r,c)=a×I(r,c)+b,0r<H,0c<W
當(dāng)a=1,b=0時(shí),O為I的一個(gè)副本;如果a>1,則輸出圖像O的對比度比I有所增大;如果0<a<1,則O的對比度比I有所減小。而b值的改變,影響的是輸出圖像的亮度,當(dāng)b>0時(shí),亮度增加;當(dāng)b<0時(shí),亮度減小

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 統(tǒng)計(jì)灰度直方圖并繪制
def calGrayHist(I):
    h, w = I.shape
    grayHist = np.zeros(256, np.uint64)
    for i in range(h):
        for j in range(w):
            grayHist[I[i][j]] += 1
    
    plt.plot(grayHist)
    plt.xlabel("gray label")
    plt.ylabel("number of pixels")

img_gray = cv.imread("./001_07.bmp", 0)
out = 2.0 * img_gray + 5
# 進(jìn)行數(shù)據(jù)截?cái)啵笥?55的像素值截?cái)酁?55
out[out > 255] = 255
out = out.astype(np.uint8)

plt.figure(figsize=(20,5))
plt.subplot(141)
plt.imshow(img_gray, cmap = "gray")
plt.subplot(142)
calGrayHist(img_gray)
plt.subplot(143)
plt.imshow(out, cmap = "gray")
plt.subplot(144)
calGrayHist(out)
# plt.savefig("./showimg.jpg")
plt.show()

基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
線性變換的參數(shù)需要根據(jù)不同的應(yīng)用及圖像自身的信息進(jìn)行合理的選擇,可能需要進(jìn)行多次測試,所以選擇合適的參數(shù)是相當(dāng)麻煩的。直方圖正規(guī)化就是基于當(dāng)前圖像情況自動選取a和b的值的方法

直方圖正規(guī)化

基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)

# 直方圖正規(guī)化
# 計(jì)算原圖中出現(xiàn)的最小灰度級和最大灰度級
Imin, Imax = cv.minMaxLoc(img_gray)[:2]
'''
# 也可以使用numpy計(jì)算
Imax = np.max(img_gray)
Imin = np.min(img_gray)
'''
Omin, Omax = 0, 255
a = float(Omax - Omin) / (Imax - Imin)
b = Omin - a * Imin
out = a * img_gray + b
out = out.astype(np.uint8)

基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
代碼中計(jì)算原圖中出現(xiàn)的最小灰度級和最大灰度級可以使用OpenCV提供的函數(shù)

minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(src[, mask])

返回值分別為:最小值,最大值,最小值的位置索引,最大值的位置索引。

正規(guī)化函數(shù)normalize: dst=cv.normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]])

使用函數(shù)normalize對圖像進(jìn)行對比度增強(qiáng)時(shí),經(jīng)常令參數(shù)norm_type=NORM_MINMAX,此函數(shù)內(nèi)部實(shí)現(xiàn)和上邊講的計(jì)算方法是相同的,參數(shù)alpha相當(dāng)于Omax,參數(shù)beta相當(dāng)于Omin。注意,使用normalize可以處理多通道矩陣,分別對每一個(gè)通道進(jìn)行正規(guī)化操作。使用該函數(shù)的代碼如下,實(shí)現(xiàn)結(jié)果和上邊是相同的

out = np.zeros(img_gray.shape, np.uint8)
cv.normalize(img_gray, out, 255, 0, cv.NORM_MINMAX, cv.CV_8U) # 調(diào)庫
cv.imshow("img", img)
cv.imshow("out", out)
cv.waitKey(0)
cv.destroyAllWindows()

直方圖均衡化(Histogram Equalization)

直方圖均衡化是指: 利用圖像直方圖對對比度進(jìn)行調(diào)整的方法
直方圖均衡化通常用來增加許多圖像的局部對比度,尤其是當(dāng)圖像的有用數(shù)據(jù)的對比度相當(dāng)接近的時(shí)候
為討論方便起見,以 r 和 s 分別表示歸一化了的原圖像灰度和經(jīng)直方圖均衡化后的圖像灰度。當(dāng) r = s = 0 時(shí),表示黑色;當(dāng) r = s = 1 時(shí),表示白色;當(dāng) r, s ∈ (0, 1) 時(shí),表示像素灰度在黑白之間變化
在 [0,1] 區(qū)間內(nèi)的任何一個(gè) r ,經(jīng)變換函數(shù) T ( r ) T(r) T(r) 都可以產(chǎn)生一個(gè)對應(yīng)的 s
s = T ( r ) s = T(r) s=T(r)
式中, T ( r ) T(r) T(r) 應(yīng)當(dāng)滿足以下兩個(gè)條件:

  1. 在 0 ≤ r ≤ 1 內(nèi), T ( r ) T(r) T(r) 為單調(diào)遞增函數(shù);(此條件保證了均衡化后圖像的灰度級從黑到白的次序不變)
  2. 在 0 ≤ r ≤ 1 內(nèi)有 0 ≤ T ( r ) ≤ 1 0 ≤ T(r) ≤ 1 0T(r)1。(此條件保證了均衡化后圖像的像素灰度值在允許的范圍內(nèi))

如果已知隨機(jī)變量 r 的概率密度是 p r ( r ) p_{r}(r) pr?(r),而隨機(jī)變量 s 是 r 的函數(shù),則 s 的概率密度 p s ( s ) p_{s}(s) ps?(s) 可以由 p r ( r ) p_{r}(r) pr?(r) 求出
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
則有: p s ( s ) d s = p r ( r ) d r p_{s}(s)ds = p_{r}(r)dr ps?(s)ds=pr?(r)dr
又有:從人眼視覺特性來考慮,一幅圖像的灰度直方圖如果是均勻分布的,那么該圖像看上去效果比較好 (參考岡薩雷斯數(shù)字圖像處理3.3節(jié))。因此要做直方圖均衡化,這里的 p s ( s ) p_{s}(s) ps?(s) 應(yīng)當(dāng)是均勻分布的概率密度函數(shù)
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
由概率論知識可知,對于區(qū)間 [a,b] 上的均勻分布,其概率密度函數(shù)等于 1 b ? a \frac{1}{b-a} b?a1?。 如果原圖像沒有進(jìn)行歸一化,即 r ∈ [ 0 , L ? 1 ] r \in [0, L-1] r[0,L?1], 那么 p s ( s ) = 1 ( L ? 1 ) ? 0 = 1 L ? 1 p_{s}(s) = \frac{1}{(L-1)-0} = \frac{1}{L-1} ps?(s)=(L?1)?01?=L?11?,歸一化之后 r ∈ [ 0 , 1 ] r \in [0, 1] r[0,1],所以這里的 p s ( s ) = 1 1 ? 0 = 1 p_{s}(s) = \frac{1}{1-0} = 1 ps?(s)=1?01?=1

p s ( s ) = 1 p_{s}(s) = 1 ps?(s)=1代入上式有: d s = p r ( r ) d r ds = p_{r}(r)dr ds=pr?(r)dr,
兩邊積分得: s = T ( r ) = ∫ 0 r p r ( r ) d r s = T(r) = \int_{0}^{r}p_{r}(r)dr s=T(r)=0r?pr?(r)dr
由于數(shù)字圖像灰度級是離散的,所以推廣到離散情況,即用頻率代替概率,有:
s k = T ( r k ) = ∑ i = 0 k p r ( r i ) = ∑ i = 0 k n i N s_{k} = T(r_{k}) = \sum_{i=0}^{k}p_{r}(r_{i}) = \sum_{i=0}^{k}\frac{n_{i}}{N} sk?=T(rk?)=i=0k?pr?(ri?)=i=0k?Nni??
式中, 0 ? r k ? 1 , k = 0 , 1 , 2 , . . . , L ? 1 0 \leqslant r_{k} \leqslant 1, k = 0, 1, 2, ..., L-1 0?rk??1,k=0,1,2,...,L?1 (注: 這里的 r k = k L ? 1 r_{k} = \frac{k}{L-1} rk?=L?1k?,表示歸一化后的灰度級;k表示歸一化前的灰度級),而且需要注意的是,這里的 s k s_{k} sk? 也是歸一化后的灰度級,其值在 0 到 1 之間;有時(shí)需要將其乘以L-1再取整,使其灰度級范圍在 0 到 L-1 之間,與原圖像一致

# 全局直方圖均衡化
def equalHist(img, z_max = 255): # z_max = L-1 = 255
    # 灰度圖像矩陣的高、寬
    H, W = img.shape
    # S is the total of pixels
    S = H * W

    out = np.zeros(img.shape)
    sum_h = 0
    for i in range(256):
        ind = np.where(img == i)
        sum_h += len(img[ind])
        z_prime = z_max / S * sum_h
        out[ind] = z_prime

    out = out.astype(np.uint8)
    return out

基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
從結(jié)果圖的直方圖分布來看,并不是理想的一條水平線,原因是我們是在連續(xù)分布上推導(dǎo)得到的轉(zhuǎn)換函數(shù),但作用于離散分布,且不允許出現(xiàn)非整數(shù)形式的新結(jié)果
不過,整體看來該轉(zhuǎn)換函數(shù)使得新的分布具有展開直方圖分布的效果,增強(qiáng)了整體的對比度

限制對比度的自適應(yīng)直方圖均衡化(CLAHE)

關(guān)于CLAHE原理講解的大多數(shù)文章講的都很泛,就像蜻蜓點(diǎn)水般隨便扯一下就直接調(diào)庫實(shí)現(xiàn)了,所以真要弄懂的話還是要看源碼
http://www.realtimerendering.com/resources/GraphicsGems/gemsiv/clahe.c

上述HE算法得到的結(jié)果存在一些問題: 1) 部分區(qū)域由于對比度增強(qiáng)過大,成為噪點(diǎn);2) 一些區(qū)域調(diào)整后變得更暗/更亮,丟失細(xì)節(jié)信息

針對問題1),有人提出了CLHE (即 Contrast Limited HE對比度限制的HE算法)
對統(tǒng)計(jì)得到的直方圖進(jìn)行裁剪,使其幅值低于某個(gè)上限,將裁剪掉的部分均勻分布在整個(gè)灰度區(qū)間,以確保直方圖總面積不變
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
可以看到,這時(shí)直方圖又會整體上升了一個(gè)高度,會超過我們設(shè)置的上限
其實(shí)在具體實(shí)現(xiàn)的時(shí)候有很多解決方法,可以多重復(fù)幾次裁剪過程,使得上升的部分變得微不足道,或是用另一種常用的方法:

  • 設(shè)裁剪值為ClipThreshold,求直方圖中高于該閾值的部分的總和totalExcess,此時(shí)如果把totalExcess均分給所有灰度級,那么最終的直方圖整體會上升一個(gè)高度,這個(gè)高度是averageIncrease = totalExcess / N,以upper = ClipThreshold - averageIncrease為界限對直方圖進(jìn)行如下處理:
    1.若幅值高于ClipThreshold,直接設(shè)置為ClipThreshold
    2.若幅值處于upperClipThreshold之間,從totalExcess中取出ClipThreshold - 幅值,將幅值填補(bǔ)成ClipThreshold
    3.若幅值低于upper,直接加上averageIncrease即可
    基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
  • 實(shí)現(xiàn)完上面的操作后,還有一些剩余的totalExcess沒有被分出去,這個(gè)剩余是來自于1.和2.,這時(shí)需要再把這些均勻分給那些目前幅值依舊低于ClipThreshold的灰度值
'''
  This function performs clipping of the histogram and redistribution of bins.
  The histogram is clipped and the number of excess pixels is counted. Afterwards
  the excess pixels are equally redistributed across the whole histogram (providing the bin count is smaller than the cliplimit).
'''
def ClipHistogram(pHistogram, ClipThreshold):
    totalExcess = 0
    # 累計(jì)超出閾值的部分
    for i in range(256):
        if pHistogram[i] > ClipThreshold:
            totalExcess += (pHistogram[i] - ClipThreshold)
    
    averageIncrease = totalExcess // 256
    upper = ClipThreshold - averageIncrease
    
    # 修剪直方圖并重新分配數(shù)值
    for i in range(256):
        if pHistogram[i] >= ClipThreshold: # 幅值高于ClipThreshold
            pHistogram[i] = ClipThreshold
        else:
            if pHistogram[i] > upper: # 幅值介于upper和ClipThreshold之間
                totalExcess -= (ClipThreshold - pHistogram[i])
                pHistogram[i] = ClipThreshold
            else: # 幅值小于upper
                totalExcess -= averageIncrease
                pHistogram[i] += averageIncrease
    
    pStartBin = 0
    while totalExcess > 0:
        # 上述過程后totalExcess仍會有剩余未分配,設(shè)置步長將剩余的進(jìn)行均分
        step_size = int(256 / totalExcess)
        if step_size < 1: # step_size至少為1
            step_size = 1
        
        for i in range(pStartBin, 256, step_size):
            if totalExcess == 0:
                break
            if pHistogram[i] < ClipThreshold:
                pHistogram[i] += 1
                totalExcess -= 1 # 減少totalExcess

        pStartBin += 1 # 在其他位置重新開始分配
    
    return pHistogram

針對問題2),有人提出AHE (Adaptive HE自適應(yīng)直方圖均衡化算法),基本思想是: 對原圖中每個(gè)像素,計(jì)算其周圍一個(gè)鄰域內(nèi)的直方圖,并使用HE映射得到新的像素值。為了能夠處理圖像邊緣的像素,一般先對原始圖像做鏡像擴(kuò)邊處理
不過這樣做計(jì)算量偏大,為了減少計(jì)算量,一般先把原始圖像分塊,分別對每個(gè)子區(qū)域進(jìn)行HE變換。但是這樣又產(chǎn)生了新的問題,子區(qū)域相接處像素值分布不連續(xù),產(chǎn)生很強(qiáng)的分割線
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
為了解決這個(gè)問題,提出了優(yōu)化方案雙線性插值的AHE,然后在這個(gè)基礎(chǔ)上,再使用CLHE的限制對比度的思想,就變成了我們熟知的CLAHE算法

CLAHE算法的步驟:

  1. 圖像分塊,以塊為單位,統(tǒng)計(jì)子塊的直方圖
  2. 使用限制對比度方法進(jìn)行修剪直方圖,最后再直方圖均衡化
  3. 像素點(diǎn)灰度值重構(gòu),使用的是雙線性插值

【雙線性插值】
對圖像分塊,然后對每一塊求直方圖均衡化,但不是把直方圖均衡化的結(jié)果全部賦給這個(gè)子塊,因?yàn)檫@樣會造成塊跟塊之間像素值不連續(xù)
那像素點(diǎn)的灰度級該如何更新? 根據(jù)像素點(diǎn)所在位置分成三類
在粉色區(qū)域內(nèi)的點(diǎn)的灰度就等于直方圖均衡化的結(jié)果,即直接由映射函數(shù)計(jì)算得到
在綠色區(qū)域內(nèi)的點(diǎn)的灰度由相鄰兩個(gè)子圖映射函數(shù)插值得到
在其他區(qū)域內(nèi)的所有點(diǎn)的灰度由相鄰四個(gè)子圖映射函數(shù)雙線性插值得到
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
如下圖所示便是雙線性插值的情況,O點(diǎn)的灰度值為 r o r_o ro?,對其周圍最近的四個(gè)子塊的灰度映射函數(shù)進(jìn)行雙線性插值的結(jié)果為:
s o = ( 1 ? x ) ( 1 ? y ) T A ( r o ) + x ( 1 ? y ) T B ( r o ) + ( 1 ? x ) y T C ( r o ) + x y T D ( r o ) s_o = (1 - x)(1 - y)T_A(r_o) + x(1 - y)T_B(r_o) + (1 - x)yT_C(r_o) + xyT_D(r_o) so?=(1?x)(1?y)TA?(ro?)+x(1?y)TB?(ro?)+(1?x)yTC?(ro?)+xyTD?(ro?)
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
【線性插值代碼實(shí)現(xiàn)中的細(xì)節(jié)】
舉個(gè)例子:
把一張圖片分成4×3個(gè)子圖,每個(gè)格子為4×4大小,圖中的P、Q兩點(diǎn)位于邊界處,所以需要使用線性插值得到這兩個(gè)點(diǎn)的灰度級,線性插值第一步找到該點(diǎn)周圍相鄰的兩個(gè)子圖,那P點(diǎn)和Q點(diǎn)的相鄰子圖分別是什么?假設(shè)P點(diǎn)坐標(biāo)為(11, 2)、Q點(diǎn)坐標(biāo)為(9, 2)
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
可以看到,雖然P點(diǎn)和Q點(diǎn)在同一個(gè)子圖中,但相鄰子圖是不同的,Q點(diǎn)的灰度級是由 T A ( r ) T_A(r) TA?(r) T B ( r ) T_B(r) TB?(r)這兩個(gè)映射函數(shù)得到,也就是說Q點(diǎn)相鄰的兩個(gè)子圖是第3個(gè)和第6個(gè)子圖(從0開始編號),而P點(diǎn)的灰度級是由 T B ( r ) T_B(r) TB?(r) T C ( r ) T_C(r) TC?(r)這兩個(gè)映射函數(shù)得到,是第6個(gè)子圖和第9個(gè)子圖
代碼中如何判定?

Q = (9, 2)
P = (11, 2)
tileGridSize = (4, 3) # 將圖片分成4×3份
height_block, width_block = 4, 4 # 每個(gè)子圖的大小

Q_numi = int((Q[0] - height_block / 2) / height_block)
Q_num1 = Q_numi * tileGridSize[1]
Q_num2 = Q_num1 + tileGridSize[1]

P_numi = int((P[0] - height_block / 2) / height_block)
P_num1 = P_numi * tileGridSize[1]
P_num2 = P_num1 + tileGridSize[1]

print(Q_num1, Q_num2)
print(P_num1, P_num2)

運(yùn)行結(jié)果為:

3 6
6 9

Q點(diǎn)的灰度級公式就為:
s Q = ( 1 ? y Q ) T A ( r Q ) + y Q T B ( r Q ) s_Q = (1 - y_Q)T_A(r_Q) + y_QT_B(r_Q) sQ?=(1?yQ?)TA?(rQ?)+yQ?TB?(rQ?)
P點(diǎn)的灰度級公式就為:
s P = ( 1 ? y P ) T B ( r P ) + y P T C ( r P ) s_P = (1 - y_P)T_B(r_P) + y_PT_C(r_P) sP?=(1?yP?)TB?(rP?)+yP?TC?(rP?)
問題來了: yQ和yP怎么獲得?
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
從上圖來看,無非就是該點(diǎn)到相鄰的第一個(gè)子圖中心的距離,所以我們需要知道第一個(gè)子圖中心位置,Q點(diǎn)相鄰的第一個(gè)子圖中心坐標(biāo)為(6, 2),P點(diǎn)相鄰的第一個(gè)子圖中心坐標(biāo)為(10, 2)

print(Q_numi * height_block + height_block / 2)
print(P_numi * height_block + height_block / 2)

yQ = (Q[0] - (Q_numi * height_block + height_block / 2)) / height_block
yP = (P[0] - (P_numi * height_block + height_block / 2)) / height_block  # 除以height_block是為了歸一化
print(yQ)
print(yP)

代碼運(yùn)行結(jié)果:

6.0
10.0
0.75
0.25

當(dāng)然,應(yīng)該也可以使用另一種方式求yQ和yP,但我不知道這個(gè)對不對,因?yàn)槲覄傞_始是想著用求余的方式求yQ和yP,就推出了這個(gè),和上面那種方法求出來的結(jié)果是一樣的

yQ = (Q[0] - height_block / 2) % height_block / height_block
yP = (P[0] - height_block / 2) % height_block / height_block
print(yQ)
print(yP)

CLAHE代碼:

def my_CLAHE(img, clipLimit, tileGridSize):
    height, width = img.shape
    height_block = height // tileGridSize[0]
    width_block = width // tileGridSize[1]
    total = width_block * height_block

    average = width_block * height_block / 256
    ClipThreshold = int(clipLimit * average)

    multi_cdf = []
    for i in range(tileGridSize[0]):
        for j in range(tileGridSize[1]):
            grid = img[i*height_block : (i+1)*height_block, j*width_block : (j+1)*width_block]
            hist = calGrayHist(grid) # 統(tǒng)計(jì)每個(gè)子塊的直方圖
            hist = ClipHistogram(hist, ClipThreshold) # 限制對比度對直方圖進(jìn)行修剪
            
            # 獲取累計(jì)分布直方圖cdf
            cdf = np.zeros(256)
            for k in range(256):
                if k == 0:
                    cdf[k] = hist[k] / total
                else:
                    cdf[k] = cdf[k-1] + (hist[k] / total)
            
            
            multi_cdf.append(cdf.tolist())

    print(np.array(multi_cdf).shape)
    
    out = np.zeros(img.shape)
    # 計(jì)算CLAHE后的像素值: 根據(jù)像素點(diǎn)的位置,選擇不同的計(jì)算方法
    for i in range(height):
        for j in range(width):
            # four coners,即紅色區(qū)域,灰度級直接由映射函數(shù)計(jì)算得到
            if i <= height_block / 2 and j <= width_block / 2: # 左上角
                num = 0
                out[i][j] = int(multi_cdf[num][img[i][j]] * 255)
            elif i <= height_block / 2 and j >= ((tileGridSize[1] - 1) * width_block + width_block / 2): # 右上角
                num = tileGridSize[1] -1
                out[i][j] = int(multi_cdf[num][img[i][j]] * 255)
            elif i >= ((tileGridSize[0] - 1) * height_block + height_block / 2) and j <= width_block: # 左下角
                num = tileGridSize[1] * (tileGridSize[0] - 1)
                out[i][j] = int(multi_cdf[num][img[i][j]] * 255)
            elif i >= ((tileGridSize[0] - 1) * height_block + height_block / 2) and j >= ((tileGridSize[1] - 1) * width_block + width_block / 2): # 右下角
                num = tileGridSize[0] * tileGridSize[1] - 1
                out[i][j] = int(multi_cdf[num][img[i][j]] * 255)

            # four edges except coners,即綠色區(qū)域,灰度級由線性插值得到
            elif j <= width_block / 2: # 左邊界
                num_i = int((i - height_block / 2) / height_block)
                num1 = num_i * tileGridSize[1]
                num2 = num1 + tileGridSize[1]
                y = (i - (num_i * height_block + height_block / 2)) / height_block # 歸一化
                out[i][j] = int(((1 - y) * multi_cdf[num1][img[i][j]] + y * multi_cdf[num2][img[i][j]]) * 255)

            elif i <= height_block / 2: # 上邊界
                num_j = int((j - width_block / 2) / width_block)
                num1 = num_j
                num2 = num1 + 1
                x = (j - (num_j * width_block + width_block / 2)) / width_block # 歸一化
                out[i][j] = int(((1 - x) * multi_cdf[num1][img[i][j]] + x * multi_cdf[num2][img[i][j]]) * 255)

            elif j >= ((tileGridSize[1] - 1) * width_block + width_block / 2): # 右邊界
                num_i = int((i - height_block / 2) / height_block)
                num1 = num_i * tileGridSize[1] + tileGridSize[1] - 1
                num2 = num1 + tileGridSize[1]
                y = (i - (num_i * height_block + height_block / 2)) / height_block # 歸一化
                out[i][j] = int(((1 - y) * multi_cdf[num1][img[i][j]] + y * multi_cdf[num2][img[i][j]]) * 255)

            elif i >= ((tileGridSize[0] - 1) * height_block + height_block / 2): # 下邊界
                num_j = int((j - width_block / 2) / width_block)
                num1 = num_j + (tileGridSize[0] - 1) * tileGridSize[1]
                num2 = num1 + 1
                x = (j - (num_j * width_block + width_block / 2)) / width_block # 歸一化
                out[i][j] = int(((1 - x) * multi_cdf[num1][img[i][j]] + x * multi_cdf[num2][img[i][j]]) * 255)

            # inner area,即紫色區(qū)域,灰度級由雙線性插值得到
            else:
                num_i = int((i - height_block / 2) / height_block)
                num_j = int((j - width_block / 2) / width_block)
                num1 = num_i * tileGridSize[1] + num_j
                num2 = num1 + 1
                num3 = num1 + tileGridSize[1]
                num4 = num2 + tileGridSize[1]
                x = (j - (num_j * width_block + width_block / 2)) / width_block # 歸一化
                y = (i - (num_i * height_block + height_block / 2)) / height_block # 歸一化
                out[i][j] = int(((1 - x) * (1 - y) * multi_cdf[num1][img[i][j]] + 
                                 x * (1- y) * multi_cdf[num2][img[i][j]] + 
                                 (1 - x) * y * multi_cdf[num3][img[i][j]] + 
                                 x * y * multi_cdf[num4][img[i][j]]) * 255)

    out = out.astype(np.uint8)
    return out

代碼運(yùn)行結(jié)果:
基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)
調(diào)庫實(shí)現(xiàn)

# 創(chuàng)建CLAHE對象
clahe = cv.createCLAHE(clipLimit=4.0, tileGridSize=(8, 8))
# 限制對比度的自適應(yīng)閾值直方圖均衡化
img_gray_clahe = clahe.apply(img_gray)

我代碼中沒有考慮過如果圖像尺寸無法整除分塊大小的情況,貼上別人的博客吧,以后有時(shí)間再去想
OpenCV自適應(yīng)直方圖均衡CLAHE圖像和分塊大小不能整除的處理


代碼下載:
https://download.csdn.net/download/weixin_45771864/86329433

參考資源:文章來源地址http://www.zghlxwxcb.cn/news/detail-459650.html

  • 【圖像處理算法】直方圖均衡化
  • 限制對比度自適應(yīng)直方圖均衡(CLAHE算法)
  • 直方圖均衡化(HE, AHE, CLAHE)
  • 限制對比度自適應(yīng)直方圖均衡化(自我理解)
  • OpenCV–Python 圖像增強(qiáng)(線性變換,直方圖正規(guī)化,伽馬變換,全局直方圖均衡化,限制對比度的自適應(yīng)直方圖均衡化)

到了這里,關(guān)于基于python的對比度增強(qiáng)(線性變換、直方圖正規(guī)化、直方圖均衡化、CLAHE)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • opencv-圖像對比度增強(qiáng)

    opencv-圖像對比度增強(qiáng)

    對比度增強(qiáng),即將圖片的灰度范圍拉寬,如圖片灰度分布范圍在[50,150]之間,將其范圍拉升到[0,256]之間。這里介紹下 線性變換,直方圖正規(guī)化,伽馬變換,全局直方圖均衡化,限制對比度自適應(yīng)直方圖均衡化等算法。 線性變換 通過函數(shù)y=ax+b對灰度值進(jìn)行處理,例如對于過暗

    2024年01月16日
    瀏覽(26)
  • OpenCv:直方圖均衡化(HE),自適應(yīng)直方圖均衡化(AHE),限制對比度自適應(yīng)直方圖均衡化(CLAHE)

    OpenCv:直方圖均衡化(HE),自適應(yīng)直方圖均衡化(AHE),限制對比度自適應(yīng)直方圖均衡化(CLAHE)

    總結(jié)了使用Python OpenCv處理圖像直方圖均衡化(HE),自適應(yīng)直方圖均衡化(AHE),限制對比度自適應(yīng)直方圖均衡化(CLAHE)的方法。 HE直方圖增強(qiáng),大家都不陌生,是一種比較古老的對比度增強(qiáng)算法。 通過equalizeHist()可以實(shí)現(xiàn)圖像的直方圖均衡,它是一種全局直方圖均衡,考量的對象

    2024年02月03日
    瀏覽(22)
  • 數(shù)字圖像處理:亮度對比度-幾何變換-噪聲處理

    數(shù)字圖像處理:亮度對比度-幾何變換-噪聲處理

    亮度與對比度轉(zhuǎn)換 圖像變換可分為以下兩種: 點(diǎn)算子:基于像素變換,在這一類圖像變換中,僅僅根據(jù)輸入像素值計(jì)算相應(yīng)的輸出像素值 鄰域算子:基于圖像區(qū)域進(jìn)行變換 兩種常用的點(diǎn)算子是用常數(shù)對點(diǎn)的像素值進(jìn)行乘法或加法運(yùn)算,可以表示為: g ( i , j ) = α ? f ( i ,

    2024年02月10日
    瀏覽(30)
  • 【opencv】示例-demhist.cpp 調(diào)整圖像的亮度和對比度,并在GUI窗口中實(shí)時(shí)顯示調(diào)整后的圖像以及其直方圖。...

    【opencv】示例-demhist.cpp 調(diào)整圖像的亮度和對比度,并在GUI窗口中實(shí)時(shí)顯示調(diào)整后的圖像以及其直方圖。...

    這段代碼是使用C++和OpenCV庫編寫的圖像處理程序,其主要功能是 調(diào)整圖像的亮度和對比度,并在GUI窗口中實(shí)時(shí)顯示調(diào)整后的圖像以及其直方圖。 用戶可以通過界面上的滑動條來動態(tài)地調(diào)整亮度和對比度參數(shù)從而觀察到圖像即時(shí)的變化效果。程序首先讀取并顯示一個(gè)灰度圖像

    2024年04月10日
    瀏覽(28)
  • 【色彩一致性損失:場景亮度解糾纏網(wǎng)絡(luò):紋理-對比度增強(qiáng)網(wǎng)絡(luò):IVIF】

    【色彩一致性損失:場景亮度解糾纏網(wǎng)絡(luò):紋理-對比度增強(qiáng)網(wǎng)絡(luò):IVIF】

    (DIVFusion:無暗區(qū)紅外與可見光圖像融合) 紅外與可見光圖像融合是一種重要的圖像增強(qiáng)技術(shù),其目的是在極端環(huán)境下生成目標(biāo)顯著、紋理豐富的高質(zhì)量融合圖像。然而,現(xiàn)有的圖像融合方法都是針對正常光照條件下的紅外和可見光圖像而設(shè)計(jì)的。在夜景場景中,由于可見光

    2024年02月08日
    瀏覽(22)
  • 【對比度增強(qiáng)】Learning Tone Curves for Local Image Enhancement(LTMNet)

    【對比度增強(qiáng)】Learning Tone Curves for Local Image Enhancement(LTMNet)

    LTMNet這篇文章借鑒了CLAHE算法,所有步驟與CLAHE一致,不同之處在于LTMNet中局部映射曲線是通過CNN預(yù)測得到,而CLAHE中是通過直方圖均衡化而得。關(guān)于CLAHE,【數(shù)字圖像處理】直方圖均衡化這篇博客有簡單介紹。 論文:Learning Tone Curves for Local Image Enhancement 代碼:https://github.co

    2023年04月23日
    瀏覽(30)
  • Python OpenCV調(diào)整圖像亮度對比度及RGB色彩

    python通過opencv庫調(diào)整圖像的步驟: 1. 讀取圖像 直接通過cv2庫讀取圖像,可以讀取jpg, png等格式 2. 調(diào)整圖像亮度及對比度 OpenCV提供 convertScaleAbs 函數(shù)來調(diào)整對比度和亮度,可以直接調(diào)用該函數(shù) 如果只調(diào)整RGB顏色通道,則可以忽略此步驟 3.?分離出圖片的B,R,G顏色通道 使用

    2024年02月03日
    瀏覽(28)
  • python numpy opencv調(diào)整圖片亮度對比度飽和度

    (想要完整代碼直接劃到最后) 原理比較簡單,本質(zhì)上是對圖像各個(gè)通道的每個(gè)像素點(diǎn)做線性變換,對超出范圍[0,255]的做截?cái)嗵幚?,所以使用numpy處理比較方便 一下函數(shù)為了

    2024年02月12日
    瀏覽(20)
  • OpenCV進(jìn)階 —— 調(diào)整圖像亮度對比度

    OpenCV進(jìn)階 —— 調(diào)整圖像亮度對比度

    圖像變換就是找到一個(gè)函數(shù),把原始圖像矩陣經(jīng)過函數(shù)處理后,轉(zhuǎn)換為目標(biāo)圖像矩陣。 可以分為兩種方式,即像素級別的變換和區(qū)域級別的變換 Point operators (pixel transforms) Neighborhood (area-based) operators 像素級別的變換就相當(dāng)于即變換后的每個(gè)像素值都與變換前的同位置的像素值

    2024年02月14日
    瀏覽(25)
  • OpenCV改變圖像的對比度和亮度

    OpenCV改變圖像的對比度和亮度

    在本教程中,您將學(xué)習(xí)如何: 訪問像素值 用零初始化矩陣 了解 cv::saturate_cast 的作用以及它為什么有用 獲取有關(guān)像素轉(zhuǎn)換的一些很酷的信息 在實(shí)際示例中提高圖像的亮度 注意 下面的解釋屬于Richard Szeliski的《計(jì)算機(jī)視覺:算法和應(yīng)用》一書 圖像處理 一般圖像處理算子是

    2024年02月21日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包