[画像補正] 一般的な画像補正アルゴリズム

主要なプラットフォームごとに収集および分類

プロジェクトアドレス: Image-Enhancement

1. ヒストグラムの等化

① アルゴリズム原理
ヒストグラム等化は、一般にグレースケール画像のコントラスト強調(顔の影部分の強調など)に使用できます。

② アルゴリズムのメリット・デメリット
カラー画像の R、G、B の 3 チャンネルを直接等化して合成すると、色ムラや歪みなどの問題が非常に発生しやすいため、RGB 画像は一般に YCrCb 空間に変換され、Y チャネルはイコライゼーション (Y チャネルは輝度成分を表します)
画像の説明を追加してください

2. 灰色の世界のアルゴリズム

① アルゴリズム原理
グレーワールドアルゴリズムは、「色の変化が多い画像では、R、G、B の 3 つの成分の平均値が同じグレー値になる傾向がある」というグレーワールド仮説に基づいています。グレー。物理的な意味では、グレーワールド法は、自然風景による光の平均反射の平均値が全体として一定値であり、この一定値がほぼ「灰色」であると仮定します。カラー バランス アルゴリズムは、処理対象の画像にこの仮定を適用することで、画像から周囲光の影響を除去し、元のシーン画像を取得できます。

グレー値を決定するには通常 2 つの方法があります

1) 固定値を使用します。8 ビット画像 (0 ~ 255) の場合、通常はグレー値として 128 を使用します。

2) ゲイン係数を計算し、3 つのチャネルの avgR、avgG、avgB の平均値をそれぞれ計算し、次のようにします。
A vg = (avg R + avg G + avg B) / 3 kr = A vg / avg R kg = A vg / avg G kb = A vg / avg B Avg=(avgR + avgG + avgB) / 3 \\ kr=Avg/avgR \\ kg=Avg/avgG \\ kb=Avg/avgBビデオ_=( by R_ _+by G_ _+a vg B ) /3kr _=vg / vg R _ _kg _=A vg / a vg GKB=A vg / a vg B

計算されたゲイン係数を使用して、各ピクセル値を再計算して新しい画像を形成します

② アルゴリズムの長所と短所
このアルゴリズムはシンプルで高速ですが、画像シーンの色が豊富でない場合、特に大きなモノクロオブジェクトがある場合、アルゴリズムは失敗することがよくあります。
Vegetable.png の効果は明ら​​かですが、sky.png の効果は明ら​​かではありません
画像の説明を追加してください
画像の説明を追加してください

3. Retinexアルゴリズム

① アルゴリズム原理
網膜大脳皮質(Retinex)理論では、世界は無色であり、人間の目で見える世界は光と物質、つまり人間の目にマッピングされた画像と物質の相互作用の結果であると考えられています。長波 (R) と中波 (G)、短波 (B) および物体の反射特性

画像の説明を追加してください
I ( x , y ) = R ( x , y ) L ( x , y ) I(x, y)=R(x, y)L(x,y)( x ,y )=R ( x ,y ) L ( x y )
ここで、I は人間の目で見える画像、R は物体の反射成分、L は環境光の照明成分、(x, y) は 2 次元画像の対応する位置です。

L を推定することで R を計算します。具体的には、L はガウスぼかしと I の畳み込みによって取得でき、次のように表されます。
log ( R ) = log ( I ) − log ( L ) L = F ∗ I log(R)= log(I)-log(L)\\L=F*Iログ( R ) _ _=ログ() _ _ログ( L ) _ _L=F私は
どこにFFFはガウスぼかしフィルターです。∗ *関数関数を求めます
F = 1 2 π σ exp ( − r 2 σ 2 ) F=\frac{1}{\sqrt{2\pi}\sigma}exp(\frac{-r^2}{\sigma ^2})F=午後2時 p1e × p (p2r2)
ここで、σ \sigmaσはガウス サラウンド空間定数 (Gaussian Surround Space Constant) と呼ばれ、アルゴリズムにおけるいわゆるスケールであり、画像処理に比較的大きな影響を与えます。2 次元画像の場合、r 2 r^2r2は対応する位置に等しい:x 2 + y 2 x^2+y^2バツ2+yつまり、照明コンポーネントはガウス フィルタリング後の元の画像の結果であると一般に考えられています。

② アルゴリズムの長所と短所
Retinex アルゴリズム、SSR (シングルスケール レティネックス) から MSR (マルチスケール レティネックス)、そして最も一般的に使用される MSRCR (色復元機能付きマルチスケール レティネックス) まで、色復元の主な目的は色を調整することです。画像の局所領域によるコントラスト グレースケール
画像の場合は一度計算するだけで済みますが、RGB 3 チャネルなどのカラー画像の場合は各チャネルを次のように計算する必要がありますまず
一連の式を見てください。

R M S R C R ( x , y ) ′ = G ⋅ R M S R C R ( x , y ) + b R M S R C R ( x , y ) = C ( x , y ) R M S R ( x , y ) C ( x , y ) = f [ I ′ ( x , y ) ] = f [ I ( x , y ) ∑ I ( x , y ) ] C i ( x , y ) = f [ I i ′ ( x , y ) ] = f [ I i ( x , y ) ∑ j = 1 N I j ( x , y ) ] f [ I ′ ( x , y ) ] = β l o g [ α I ′ ( x , y ) ] = β l o g [ α I ′ ( x , y ) ] − l o g [ ∑ I ( x , y ) ] RMSRCR(x,y)'=G⋅RMSRCR(x,y)+b \\ RMSRCR (x,y)=C(x,y)RMSR(x,y) \\ C(x,y)=f[I'(x,y)]=f[\frac{I(x,y)}{∑I(x,y)}]Ci(x,y)=f[Ii′(x,y)]=f[Ii(x,y)∑j=1NIj(x,y)] \\ f[I'(x,y)]=βlog[αI'(x,y)]=β{log[αI'(x,y)]−log[∑I(x,y)]} RMSRCR(x,y)=GRMSRCR(x,y)+bRMSRCR(x,y)=C(x,y)RMSR(x,y)C(x,y)=f[I(x,y)]=f[I(x,y)I(x,y)]Ci(x,y)=f[Ii(x,y)]=f[Ii(x,y)j=1NIj(x,y)]f[I(x,y)]=βlog[αI(x,y)]=βlog[αI(x,y)]log[I(x,y)]

G表示增益Gain(一般取值:5)

b表示偏差Offset(一般取值:25)

I (x, y)表示某个通道的图像

C表示某个通道的彩色回复因子,用来调节3个通道颜色的比例;

f(·)表示颜色空间的映射函数;

β是增益常数(一般取值:46);

α是受控制的非线性强度(一般取值:125)

MSRCR算法利用彩色恢复因子C,调节原始图像中3个颜色通道之间的比例关系,从而把相对较暗区域的信息凸显出来,达到了消除图像色彩失真的缺陷。 处理后的图像局部对比度提高,亮度与真实场景相似,在人们视觉感知下,图像显得更加逼真;但是MSRCR算法处理图像后,像素值一般会出现负值。所以从对数域r(x, y)转换为实数域R(x, y)后,需要通过改变增益Gain,偏差Offset对图像进行修正画像の説明を追加してください

四、自动白平衡(AWB)

① 算法原理
用一个简单的概念来解释什么是白平衡:假设,图像中R、G、B最高灰度值对应于图像中的白点,最低灰度值的对应于图像中最暗的点;其余像素点利用(ax+b)映射函数把彩色图像中R、G、B三个通道内的像素灰度值映射到[0.255]的范围内.

白平衡的本质是让白色的物体在任何颜色的光源下都显示为白色,这一点对人眼来说很容易办到,因为人眼有自适应的能力,只要光源的色彩不超出一定的限度,就可以自动还原白色。但相机就不同了,无论是图像传感器还是胶卷都会记录光源的颜色,白色的物体就会带上光源的颜色,白平衡所要做的就是把这个偏色去掉。

② 算法优缺点
自动白平衡是一个很复杂的问题,目前还没有一个万能的方法可以解决所有场景的白平衡问题画像の説明を追加してください

五、自动色彩均衡(ACE)

① 算法原理
ACE算法源自retinex算法,可以调整图像的对比度,实现人眼色彩恒常性和亮度恒常性,该算法考虑了图像中颜色和亮度的空间位置关系,进行局部特性的自适应滤波,实现具有局部和非线性特征的图像亮度与色彩调整和对比度调整,同时满足灰色世界理论假设和白色斑点假设。

第一步:对图像进行色彩/空域调整,完成图像的色差校正,得到空域重构图像;
R c ( p ) = ∑ j ∈ S u b s e t , j ≠ p r ( I c ( p ) − I c ( j ) ) d ( p , j ) R_c(p)=\sum_{j\in Subset,j\ne p}\frac{r(I_c(p)-I_c(j))}{d(p,j)} Rc(p)=jSubset,j=pd(p,j)r(Ic(p)Ic(j))
式中, R c Rc Rc 是中间结果, I c ( p ) − I c ( j ) I_c(p)-I_c(j) Ic(p)Ic(j)为两个不同点的亮度差, d ( p , j ) d(p,j) d(p,j) 表示距离度量函数, r ( ∗ ) r(*) r()为亮度表现函数,需是奇函数;这一步可以适应局部图像对比度, r ( ∗ ) r(*) r()能够放大较小的差异,并丰富大的差异,根据局部内容扩展或者压缩动态范围。一般得, r ( ∗ ) r(*) r()为:
r ( x ) = { 1 , x < − T x / T , − T ⩽ x ⩽ T − 1 , x > T r(x)=\begin{cases} 1&,x<-T \\ x/T&,-T\leqslant x\leqslant T \\ -1&,x>T\end{cases} r(x)= 1x/T1,x<T,TxT,x>T
第二步:对校正后的图像进行动态扩展。ACE算法是对单一色道进行的,对于彩色图片需要对每一个色道分别处理
其中存在一种简单的线性扩展:

R ( x ) = r o u n d [ 127.5 + w ∗ R c ( p ) ] R(x)=round[127.5+w*R_c(p)] R(x)=round[127.5+wRc(p)],其中, w w w表示线段 [ ( 0 , m c ) , ( 255 , M c ) ] [(0,m_c),(255,M_c)] [(0,mc),(255,Mc)]的斜率,且有:
M c = m i n [ R c ( p ) ] , M c = m a x [ R c ( p ) ] M_c=min[R_c(p)],M_c=max[R_c(p)] Mc=min[Rc(p)]Mc=max[Rc(p)]

第三步:利用下面的公式将 R ( x ) R(x) R ( x )は[0,1][0,1]に展開されます[ 0 ,1 ]、拡張チャネル
L ( x ) = R ( x ) − min R max R − min RL(x)=\frac{R(x)-minR}{maxR-minR}L ( × )=マックスR _IR _R ( × )私のR
②アルゴリズムの長所と短所
一般に、ACE の強調効果は retinex よりも優れています。ACE の現在のピクセルは画像全体の他のピクセルと差分的に比較され、計算の複雑さが非常に非常に高く、これがアプリケーションを制限する主な理由であることに注意してください。

そこで、一般的なアルゴリズムでは、指定されたサンプル数で画像全体の画素情報を置き換えて差分計算を行うことで、計算量を削減し効率を向上させています。
画像の説明を追加してください
要約: 従来のさまざまなアルゴリズムのレンダリングを観察すると、ACE 自動色等化アルゴリズムは比較的優れた汎用性と効果を持っていますが、もちろん、一部の写真では良好な結果が得られません。

# 部分图像增强算法代码
"""
Project :Image-Enhancement 
File    :base_enhance.py
Author  :MangoloD
Date    :2022/3/9 13:48 
"""
# 图像增强算法,图像锐化算法
# 1)基于直方图均衡化 2)基于拉普拉斯算子 3)基于对数变换 4)基于伽马变换 5)CLAHE 6)retinex-SSR 7)retinex-MSR
# 其中,基于拉普拉斯算子的图像增强为利用空域卷积运算实现滤波
# 基于同一图像对比增强效果
# 直方图均衡化:对比度较低的图像适合使用直方图均衡化方法来增强图像细节
# 拉普拉斯算子可以增强局部的图像对比度
# log对数变换对于整体对比度偏低并且灰度值偏低的图像增强效果较好
# 伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于相机过曝)情况下的图像增强效果明显

import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt


# 直方图均衡增强


def hist(image):
    r, g, b = cv2.split(image)
    r1 = cv2.equalizeHist(r)
    g1 = cv2.equalizeHist(g)
    b1 = cv2.equalizeHist(b)
    image_equal_clo = cv2.merge([r1, g1, b1])
    return image_equal_clo


# 拉普拉斯算子
def laplacian(image):
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
    image_lap = cv2.filter2D(image, cv2.CV_8UC3, kernel)
    return image_lap


# 对数变换
def log(image):
    image_log = np.uint8(np.log(np.array(image) + 1))
    cv2.normalize(image_log, image_log, 0, 255, cv2.NORM_MINMAX)
    # 转换成8bit图像显示
    cv2.convertScaleAbs(image_log, image_log)
    return image_log


# 伽马变换
def gamma(image):
    fgamma = 2
    image_gamma = np.uint8(np.power((np.array(image) / 255.0), fgamma) * 255.0)
    cv2.normalize(image_gamma, image_gamma, 0, 255, cv2.NORM_MINMAX)
    cv2.convertScaleAbs(image_gamma, image_gamma)
    return image_gamma


# 限制对比度自适应直方图均衡化CLAHE
def clahe(image):
    b, g, r = cv2.split(image)
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    b = clahe.apply(b)
    g = clahe.apply(g)
    r = clahe.apply(r)
    image_clahe = cv2.merge([b, g, r])
    return image_clahe


def replaceZeroes(data):
    min_nonzero = min(data[np.nonzero(data)])
    data[data == 0] = min_nonzero
    return data


# retinex SSR
def SSR(src_img, size):
    L_blur = cv2.GaussianBlur(src_img, (size, size), 0)
    img = replaceZeroes(src_img)
    L_blur = replaceZeroes(L_blur)

    dst_Img = cv2.log(img / 255.0)
    dst_Lblur = cv2.log(L_blur / 255.0)
    dst_IxL = cv2.multiply(dst_Img, dst_Lblur)
    log_R = cv2.subtract(dst_Img, dst_IxL)

    dst_R = cv2.normalize(log_R, None, 0, 255, cv2.NORM_MINMAX)
    log_uint8 = cv2.convertScaleAbs(dst_R)
    return log_uint8


def SSR_image(image):
    size = 3
    b_gray, g_gray, r_gray = cv2.split(image)
    b_gray = SSR(b_gray, size)
    g_gray = SSR(g_gray, size)
    r_gray = SSR(r_gray, size)
    result = cv2.merge([b_gray, g_gray, r_gray])
    return result


# retinex MMR
def MSR(img, scales):
    weight = 1 / 3.0
    scales_size = len(scales)
    h, w = img.shape[:2]
    log_R = np.zeros((h, w), dtype=np.float32)

    for i in range(scales_size):
        img = replaceZeroes(img)
        L_blur = cv2.GaussianBlur(img, (scales[i], scales[i]), 0)
        L_blur = replaceZeroes(L_blur)
        dst_Img = cv2.log(img / 255.0)
        dst_Lblur = cv2.log(L_blur / 255.0)
        dst_Ixl = cv2.multiply(dst_Img, dst_Lblur)
        log_R += weight * cv2.subtract(dst_Img, dst_Ixl)

    dst_R = cv2.normalize(log_R, None, 0, 255, cv2.NORM_MINMAX)
    log_uint8 = cv2.convertScaleAbs(dst_R)
    return log_uint8


def MSR_image(image):
    scales = [15, 101, 301]  # [3,5,9]
    b_gray, g_gray, r_gray = cv2.split(image)
    b_gray = MSR(b_gray, scales)
    g_gray = MSR(g_gray, scales)
    r_gray = MSR(r_gray, scales)
    result = cv2.merge([b_gray, g_gray, r_gray])
    return result


def image_enhance(image, is_gamma=False):
    if is_gamma:
        image = image / 255.0  # 注意255.0得采用浮点数
        image = np.power(image, 0.5) * 255.0
        image = image.astype(np.uint8)

    # numpy实现
    out_min = 0
    out_max = 255

    in_min = np.min(image)
    in_max = np.max(image)

    a = float(out_max - out_min) / (in_max - in_min)
    b = out_min - a * in_min
    img_norm = image * a + b
    img_norm = img_norm.astype(np.uint8)
    return img_norm


def paint(image):
    plt.subplot(4, 2, 1)
    plt.imshow(image)
    plt.axis('off')
    plt.title('Offical')

    # 直方图均衡增强
    image_equal_clo = hist(image)

    plt.subplot(4, 2, 2)
    plt.imshow(image_equal_clo)
    plt.axis('off')
    plt.title('equal_enhance')

    # 拉普拉斯算法增强
    image_lap = laplacian(image)

    plt.subplot(4, 2, 3)
    plt.imshow(image_lap)
    plt.axis('off')
    plt.title('laplacian_enhance')

    # LoG对象算法增强
    image_log = log(image)

    plt.subplot(4, 2, 4)
    plt.imshow(image_log)
    plt.axis('off')
    plt.title('log_enhance')

    # 伽马变换
    image_gamma = gamma(image)

    plt.subplot(4, 2, 5)
    plt.imshow(image_gamma)
    plt.axis('off')
    plt.title('gamma_enhance')

    # CLAHE
    image_clahe = clahe(image)

    plt.subplot(4, 2, 6)
    plt.imshow(image_clahe)
    plt.axis('off')
    plt.title('CLAHE')

    # retinex_ssr
    image_ssr = SSR_image(image)

    plt.subplot(4, 2, 7)
    plt.imshow(image_ssr)
    plt.axis('off')
    plt.title('SSR')

    # retinex_msr
    image_msr = MSR_image(image)

    plt.subplot(4, 2, 8)
    plt.imshow(image_msr)
    plt.axis('off')
    plt.title('MSR')

    plt.show()


if __name__ == "__main__":
    image = cv2.imread("images/BGRT2.jpg")
    image_ = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

    flag = 0
    if flag == 0:
        paint(image_)
    elif flag == 1:
        image_msr = MSR_image(image)
        plt.subplot(1, 2, 1)
        plt.imshow(image_)
        plt.axis('off')
        plt.title('Offical')

        plt.subplot(1, 2, 2)
        plt.imshow(cv2.cvtColor(image_msr, cv2.COLOR_BGR2RGB))
        plt.axis('off')
        plt.title('MSR')

        plt.show()
    else:
        img = image_enhance(image_, is_gamma=False)
        plt.subplot(1, 2, 1)
        plt.imshow(image_)
        plt.axis('off')
        plt.title('Offical')

        plt.subplot(1, 2, 2)
        plt.imshow(img)
        plt.axis('off')
        plt.title('common')

        plt.show()

おすすめ

転載: blog.csdn.net/weixin_42166222/article/details/123377594