1. 程式人生 > >OpenCV—python 色階調整(直方圖均衡化)

OpenCV—python 色階調整(直方圖均衡化)

文章目錄

一、色階調整( Levels Adjustment )原理

色階:就是用直方圖描述出的整張圖片的明暗資訊。如圖
從左至右是從暗到亮的畫素分佈,
黑色三角代表最暗地方(純黑—黑點值為0),
白色三角代表最亮地方(純白—白點為 255)。
灰色三角代表中間調。(灰點為1.00)

對於一個RGB影象, 可以對R, G, B 通道進行獨立的色階調整,即對三個通道分別使用三個色階定義值。還可以再對 三個通道進行整體色階調整。
因此,對一個影象,可以用四次色階調整。最終的結果,是四次調整後合併產生的結果。
cv2.equalizeHist(img) 函式

img = cv2.imread('./20181106194742.png',0)
equ = cv2.equalizeHist(img) # 只能傳入灰度圖

res = np.hstack((img,equ))  # 影象列拼接(用於顯示)

cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在這裡插入圖片描述

二、自動色階影象處理演算法

cv2.createCLAHE() 對比度有限自適應直方圖均衡
直方圖均衡後背景對比度有所改善。但導致亮度過高,我們丟失了大部分資訊。這是因為它的直方圖並不侷限於特定區域。
因此,為了解決這個問題,使用自適應直方圖均衡

。在此,影象被分成稱為“圖塊”的小塊(在OpenCV中,tileSize預設為8x8)。然後像往常一樣對這些塊中的每一個進行直方圖均衡。所以在一個小區域內,直方圖會限制在一個小區域(除非有噪音)。如果有噪音,它會被放大。為避免這種情況,應用對比度限制。如果任何直方圖區間高於指定的對比度限制(在OpenCV中預設為40),則在應用直方圖均衡之前,將這些畫素剪下並均勻分佈到其他區間。均衡後,為了去除圖塊邊框中的瑕疵,應用雙線性插值。

import numpy as np
import cv2

img = cv2.imread('20181106194742.png',0)
clahe = cv2.createCLAHE(
clipLimit=2.0, tileGridSize=(8,8)) cl1 = clahe.apply(img) cv2.imshow('img',img) cv2.imshow('cl1',cl1) cv2.waitKey(0) cv2.destroyAllWindows()

在這裡插入圖片描述
自適應色階去霧氣

import numpy as np
import cv2
 
def ComputeHist(img):
    h,w = img.shape
    hist, bin_edge = np.histogram(img.reshape(1,w*h), bins=list(range(257)))
    return hist
    
def ComputeMinLevel(hist, rate, pnum):
    sum = 0
    for i in range(256):
        sum += hist[i]
        if (sum >= (pnum * rate * 0.01)):
            return i
            
def ComputeMaxLevel(hist, rate, pnum):
    sum = 0
    for i in range(256):
        sum += hist[255-i]
        if (sum >= (pnum * rate * 0.01)):
            return 255-i
            
def LinearMap(minlevel, maxlevel):
    if (minlevel >= maxlevel):
        return []
    else:
        newmap = np.zeros(256)
        for i in range(256):    #獲取閾值外的畫素值 i< minlevel,i> maxlevel
            if (i < minlevel):
                newmap[i] = 0
            elif (i > maxlevel):
                newmap[i] = 255
            else:
                newmap[i] = (i-minlevel)/(maxlevel-minlevel) * 255
        return newmap
        
def CreateNewImg(img):
    h,w,d = img.shape
    newimg = np.zeros([h,w,d])
    for i in range(d):
        imgmin = np.min(img[:,:,i])
        imgmax = np.max(img[:,:,i])
        imghist = ComputeHist(img[:,:,i])
        minlevel = ComputeMinLevel(imghist, 8.3, h*w)
        maxlevel = ComputeMaxLevel(imghist, 2.2, h*w)
        newmap = LinearMap(minlevel,maxlevel)
        if (newmap.size ==0 ):
            continue
        for j in range(h):
            newimg[j,:,i] = newmap[img[j,:, i]]
    return newimg


if __name__ == '__main__':
    img = cv2.imread('./20181106194742.png')
    newimg = CreateNewImg(img)
    cv2.imshow('original_img', img)
    cv2.imshow('new_img', newimg/255)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

在這裡插入圖片描述