(デジタル画像処理 MATLAB+Python) 第 5 章 画像強調 - セクション 3: 照度反射モデルに基づく画像強調

照度反射モデルに基づく画像強調: 照度反射モデルに基づく画像強調方法は、画像の明るさとコントラストを調整することで画質を向上させます。この方法では、画像の明るさが照度反射の2 つの部分に分解できると仮定しています。照度は光源によって生成される光の強度の分布であり、反射は物体表面の反射率と光の強度によって決まります。

  • i ( x , y ) i (x, y)i ( x ,y )は、シーンの照明のゆっくりとした変換を表し、低周波成分
  • r ( x , y ) r (x, y)r ( x ,y )はシーン内容の急速な変化を表し、高周波成分

ここに画像の説明を挿入

照明反射モデルに基づく画像強調方法には、主に次の手順が含まれます。

  • 画像の照度分布を推定する: このステップは、後で反射分布を調整できるように、画像内の照度を分離することを目的としています。一般的に使用される手法としては、ヒストグラム等化に基づく手法、ガウスモデルに基づく手法、レティネックス理論に基づく手法などが挙げられます。
  • 画像の反射分布を計算する: 照度分布を取得した後、元の画像を物体表面の反射率情報を表す照度分布で除算することで反射分布を取得できます。
  • 画像の反射分布を調整する: 反射分布の線形または非線形変換によって画像のコントラストと明るさを調整し、画像の品質を向上させることができます。一般的に使用される方法には、ガンマ補正、対数変換、ヒストグラム マッチングなどが含まれます。
  • 調整された反射率分布と照度分布を乗算して、強化された画像を取得します。

1: 準同型フィルタリングに基づく強化

(1。概要

  • 背景: オブジェクトが不均一な照明にさらされている場合、暗い照明に対応する画像部分の詳細を区別することが困難になります。
  • 主な目的: 照明ムラの影響を排除し、画像のディテールを向上させる

準同型フィルタリングに基づく強調:画像を周波数領域に変換して処理し、周波数領域で画像の振幅と位相情報を調整することで画質を効果的に向上させる方法です。具体的には、準同型フィルタリングに基づく画像強調は次の式で表すことができます

g ( x , y ) = H ( u , v ) F ( u , v ) g(x,y) = H(u,v)F(u,v)g ( x ,y =H ( u v ) F ( u v )

其中, g ( x , y ) g(x,y) g ( x ,y )は強化されたイメージF ( u , v ) F(u,v)F ( u ,v ) は、周波数領域での元のイメージのフーリエ変換H ( u , v ) H(u,v)H ( u v )は、周波数領域で画像の振幅と位相情報を調整するために使用されるフィルター関数です。uuu v v v はそれぞれ周波数領域の水平座標と垂直座標を表します。

準同型フィルターの特定の形式は次のように表現できます。

H ( u , v ) = H lp ( u , v ) H hp ( u , v ) H(u,v) = H_{lp}(u,v)H_{hp}(u,v)H ( u v )=HLP(あなたv ) Hhp _(あなたv )

其中, H l p ( u , v ) H_{lp}(u,v) HLP(あなたv) H h p ( u , v ) H_{hp}(u,v) Hhp _(あなたv )はそれぞれローパス フィルターとハイパス フィルターを表し、周波数領域で画像の低周波情報と高周波情報を調整するために使用されます。一般に、H lp ( u , v ) H_{lp}(u,v)HLP(あなたv )ガウス フィルターを使用すると、H hp ( u , v ) H_{hp}(u,v)Hhp _(あなたv )バターワース フィルターの使用。準同型フィルタリングを行う場合、画像を対数変換し、乗算演算を加算演算に変換することができ、計算を簡略化することができる。最後に、強調画像を逆変換することにより、空間領域の強調画像を取得できます。

(2) プログラム

ここに画像の説明を挿入


MATLAB の実装:

Image=double(rgb2gray(imread('gugong1.jpg')));  %打开图像并转换为double数据
imshow(uint8(Image)),title('故宫');
logI=log(Image+1);  %对数运算
sigma=1.414;  filtersize=[7 7];  %高斯滤波器参数
lowfilter=fspecial('gaussian',filtersize,sigma);  %构造高斯低通滤波器
highfilter=zeros(filtersize);
highpara=1; lowpara=0.4;    %控制滤波器幅度范围的系数  
highfilter(ceil(filtersize(1,1)/2),ceil(filtersize(1,2)/2))=1;
highfilter=highpara*highfilter-(highpara-lowpara)*lowfilter; %高斯低通滤波器转换为高斯高通滤波器
highpart=imfilter(logI,highfilter,'replicate','conv'); %时域卷积实现滤波
NewImage=exp(highpart); %指数变换恢复图像
top=max(NewImage(:)); bottom=min(NewImage(:));
NewImage=(NewImage-bottom)/(top-bottom);     %数据的映射处理,符合人眼视觉特性
NewImage=1.5.*(NewImage);
figure,imshow((NewImage));title('基于同态滤波的增强图像');
imwrite(NewImage,'tongtai.bmp');

Python の実装:

import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']

# 读取图像并转换为double数据类型
img = cv2.imread('gugong1.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(np.float64)

# 显示原始图像
plt.imshow(img, cmap='gray')
plt.title('故宫')
plt.show()

# 对图像进行对数变换
log_img = np.log(img + 1)

# 构造高斯低通滤波器
sigma = 1.414
filter_size = (7, 7)
low_filter = cv2.getGaussianKernel(filter_size[0], sigma)
low_filter = low_filter @ low_filter.T

# 构造高斯高通滤波器
high_filter = np.zeros(filter_size)
high_para = 1
low_para = 0.4
high_filter[filter_size[0] // 2, filter_size[1] // 2] = 1
high_filter = high_para * high_filter - (high_para - low_para) * low_filter

# 对图像进行高斯高通滤波
high_part = cv2.filter2D(log_img, -1, high_filter, borderType=cv2.BORDER_REPLICATE)

# 进行指数变换并进行数据映射
new_img = np.exp(high_part)
new_img = (new_img - np.min(new_img)) / (np.max(new_img) - np.min(new_img))
new_img = 1.5 * new_img

# 显示增强后的图像并保存
plt.imshow(new_img, cmap='gray')
plt.title('基于同态滤波的增强图像')
plt.show()

cv2.imwrite('tongtai.bmp', new_img * 255)

2: レティネックス理論

(1) Retinex理論の概要

Retinex理論:1971年にスタンフォード大学のエドウィン・H・ランド教授によって提唱された画像処理理論。レティネックスとは合成語で、レティナ(網膜)+コルテックス(皮質)→レティネックスという構成になっています。長年にわたり、Retinex アルゴリズムはシングルスケール Retinex アルゴリズム (SSR) からマルチスケール加重平均 Retinex アルゴリズム (MSR) に改良され、さらに色復元を備えたマルチスケール Retinex アルゴリズム (MSRCR) に開発されました。これらのアルゴリズムは同じではありませんが、基本原理は非常に似ており、元の画像に対してガウス フィルタリングを適用して照度画像を取得し、可能な限り正確に照度画像を取得し、最後に元の画像から照度画像を分離して、反射画像を取得します。Retinex モデルの理論的基礎は、3 色理論と色の恒常性です。つまり、物体の色は、長波 (赤)、中波 (緑)、および短波を反射する物体の能力によって決まります。反射によるものではなく、波(青色)の光です。 光の強さの絶対値によって決まり、物体の色は光の不均一性の影響を受けず、一貫性を持っています。つまり、Retinex は、色の知覚(色の恒常性)。この理論の中心的な議論は次のとおりです

  • 人間の目の物体の色の認識は、物体の表面の反射特性と密接に関係しています。つまり、反射率が低い物体はより暗く見え、反射率が高い物体はより明るく見えます
  • 人間の目は物体の色を一貫して認識しており、光の変化の影響を受けません。

Retinex 理論では、画像I ( x , y ) I(x,y) が次のように解釈されます。( x ,y )は、次のように照度画像と反射画像で構成されます。照度-反射モデルによれば、Retinex 理論の中核方程式は次のようになります。

  • R ( x , y ) R(x, y)R ( x ,y )はオブジェクトの反射情報を表します
  • L ( x , y ) L(x, y)L ( x ,y )はインシデントコンポーネント情報を表します

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

ここに画像の説明を挿入

Retinex 理論の開発プロセスは次のとおりで、大きく 2 つの段階を経ます。

  • 反復ベースの Retinex アルゴリズム (多くの欠陥があります)
  • センターサラウンドベースのRetinexアルゴリズム

ここに画像の説明を挿入

(1) SSR (シングルスケール Retinex アルゴリズム)

SSR : Retinex に基づく画像強調アルゴリズムであり、単一スケールでのみ動作します。アルゴリズムの手順は次のとおりです。

  • 元画像データの読み込みS ( x , y ) S(x,y)S ( x ,y ) を実行し、整数を double 型に変換します
  • スケールパラメータσ \sigmaを決定しますσのサイズは、条件∬ G ( x , y ) dxdy = 1 \iint G(x,y)dxdy=1 をG ( x ,y ) d x d y=1 λ\ラムダラムダ
  • 公式によるとr ( x , y ) = log ⁡ S ( x , y ) − log ⁡ [ G ( x , y ) ⋅ S ( x , y ) ] r(x,y)=\log S(x,y) -\log[G(x,y)\cdot S(x,y)]r ( x ,y =ログ_S ( x ,y log [ G ( x , _y S ( x ,y )]r ( x , y ) r(x,y)r ( x ,y )
  • r ( x , y ) r(x,y)r ( x ,y )の値は、R ( x , y ) R(x,y)に属するペアによって実数フィールド R に変換されます。R ( x ,y
  • R ( x , y ) R(x,y)R ( x ,y )線形ストレッチ処理を実行すると、出力は次のようになります。

グレースケール画像の場合、グレースケール値は上記の手順で直接処理できますが、カラー画像の場合は、R、G、B の 3 つのグレースケール画像に分解し、次に上記の手順で処理して、最終的にカラーに合成する必要があります。画像

ここに画像の説明を挿入

以下のような効果が得られます
ここに画像の説明を挿入

MATLAB の実装:

clear all;
close all;
clc;
I = imread('origin.jpg');%读图
 
% 提取原始图像的红色通道,将其转换为双精度类型,并进行log变换和二维傅里叶变换
R = I(:, :, 1);
[N1, M1] = size(R);
R0 = double(R);
Rlog = log(R0+1);
Rfft2 = fft2(R0);
 
% 设定高斯核参数sigma,并生成与图像大小相同的高斯核。然后将高斯核进行二维傅里叶变换
sigma = 80;
F = fspecial('gaussian', [N1,M1], sigma);
Efft = fft2(double(F));
 
% 进行卷积操作,然后将该结果进行傅里叶反变换,得到卷积结果的空域图像
DR0 = Rfft2.* Efft;%卷积
DR = ifft2(DR0);%反变换到空域
 
% 将卷积结果的空域图像进行log变换,然后将其与原始图像的log变换相减,得到增强后的图像的log变换
DRlog = log(DR +1);
Rr = Rlog - DRlog;

% 将卷积结果的空域图像进行log变换,然后将其与原始图像的log变换相减,得到增强后的图像的log变换
EXPRr = Rr;
MIN = min(min(EXPRr));
MAX = max(max(EXPRr));
EXPRr = 255*(EXPRr - MIN)/(MAX - MIN);%线性拉伸

 
G = I(:, :, 2);
 
G0 = double(G);
Glog = log(G0+1);
Gfft2 = fft2(G0);
 
DG0 = Gfft2.* Efft;
DG = ifft2(DG0);
 
DGlog = log(DG +1);
Gg = Glog - DGlog;

EXPGg = Gg;
MIN = min(min(EXPGg));
MAX = max(max(EXPGg));
EXPGg = 255*(EXPGg - MIN)/(MAX - MIN);

 
B = I(:, :, 3);
 
B0 = double(B);
Blog = log(B0+1);
Bfft2 = fft2(B0);
 
DB0 = Bfft2.* Efft;
DB = ifft2(DB0);
 
DBlog = log(DB+1);
Bb = Blog - DBlog;

EXPBb = Bb;
MIN = min(min(EXPBb));
MAX = max(max(EXPBb));
EXPBb = 255*(EXPBb - MIN)/(MAX - MIN);

 
result = cat(3, EXPRr, EXPGg, EXPBb);
subplot(121), imshow(I);
subplot(122), imshow(uint8(result));


Python の実装:

import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']

# 读取图像
I = cv2.imread('origin.jpg')

# 提取红色通道,将其转换为双精度类型,并进行log变换和二维傅里叶变换
R = I[:, :, 2]
N1, M1 = R.shape
R0 = np.double(R)
Rlog = np.log(R0+1)
Rfft2 = np.fft.fft2(R0)

# 设定高斯核参数sigma,并生成与图像大小相同的高斯核。然后将高斯核进行二维傅里叶变换
sigma = 80
F = cv2.getGaussianKernel(max(N1,M1),sigma)
F = np.outer(F,F)
Efft = np.fft.fft2(np.double(F),[N1,M1])

# 进行卷积操作,然后将该结果进行傅里叶反变换,得到卷积结果的空域图像
DR0 = Rfft2 * Efft
DR = np.fft.ifft2(DR0)

# 将卷积结果的空域图像进行log变换,然后将其与原始图像的log变换相减,得到增强后的图像的log变换
DRlog = np.log(DR + 1)
Rr = Rlog - DRlog

# 线性拉伸像素值到0-255之间
EXPRr = Rr
MIN = np.min(EXPRr)
MAX = np.max(EXPRr)
EXPRr = 255 * (EXPRr - MIN) / (MAX - MIN)
EXPRr = np.uint8(EXPRr)

G = I[:, :, 1]

G0 = np.double(G)
Glog = np.log(G0+1)
Gfft2 = np.fft.fft2(G0)

DG0 = Gfft2 * Efft
DG = np.fft.ifft2(DG0)

DGlog = np.log(DG+1)
Gg = Glog - DGlog

EXPGg = Gg
MIN = np.min(EXPGg)
MAX = np.max(EXPGg)
EXPGg = 255 * (EXPGg - MIN) / (MAX - MIN)
EXPGg = np.uint8(EXPGg)

B = I[:, :, 0]

B0 = np.double(B)
Blog = np.log(B0+1)
Bfft2 = np.fft.fft2(B0)

DB0 = Bfft2 * Efft
DB = np.fft.ifft2(DB0)

DBlog = np.log(DB+1)
Bb = Blog - DBlog

EXPBb = Bb
MIN = np.min(EXPBb)
MAX = np.max(EXPBb)
EXPBb = 255 * (EXPBb - MIN) / (MAX - MIN)
EXPBb = np.uint8(EXPBb)

# 合并增强后的通道,形成增强后的图像
result = cv2.merge((EXPRr, EXPGg, EXPBb))

# 显示原始图像和增强后的图像
fig, ax = plt.subplots(1, 2)
ax[0].imshow(cv2.cvtColor(I, cv2.COLOR_BGR2RGB))
ax[0].set_title('Original Image

(2) MSR (マルチスケール Retinex アルゴリズム)

MSR : 簡単に言うと、MSR は異なるサイズのいくつかのスケール パラメーターを使用して RGB の 3 つのコンポーネントを個別にフィルターし、線形に重み付けおよび正規化して MSR アルゴリズムを取得します。アルゴリズムの手順は次のとおりです

  • 元画像データの読み込みS ( x , y ) S(x,y)S ( x ,y ) を実行し、整数を double 型に変換します
  • 3 つのスケール パラメーターσ 1 、σ 2 . σ 3 \sigma_{1},\sigma_{2}.\sigma_{3} を決定します。p1p2p3サイズ、条件∬ G k ( x , y ) dxdy = 1 \iint G_{k}(x,y)dxdy=1 を満たすように決定します。G( x ,y ) d x d y= 1、λ 2 、λ 3 \lambda_{1},\lambda_{2},\lambda_{3}123の値
  • レベル比r ( x , y ) = ∑ k = 1 K qk { log ⁡ S ( x , y ) − log ⁡ [ G k ( x , y ) ∗ S ( x , y ) ] } r(\mathrm{x }, \mathrm{y})=\sum_{k=1}^{K} q_{k}\left\{\log \mathrm{S}(\mathrm{x}, \mathrm{y})-\ log \left[\mathrm{G}_{k}(\mathrm{x}, \mathrm{y}) *\mathrm{~S}(\mathrm{x}, \mathrm{y})\right]\右\}r ( x ,y =k = 1Kq{ ログ_S ( x ,y ログ_[ G( x ,y  S ( x ,y ) ] }r ( x , y ) r(x,y)r ( x ,y )
  • r ( x , y ) r(x,y)r ( x ,y )の値は、R ( x , y ) R(x,y)に属するペアによって実数フィールド R に変換されます。R ( x ,y
  • R ( x , y ) R(x,y)R ( x ,y )線形ストレッチ処理を実行すると、出力は次のようになります。

ここに画像の説明を挿入

以下のような効果が得られます

画像の説明を追加してください


MATLAB の実装:

close all; clear all; clc
I = imread('origin.jpg');
I_r = double(I(:,:,1));
I_g = double(I(:,:,2));
I_b = double(I(:,:,3));
I_r_log = log(I_r+1);
I_g_log = log(I_g+1);
I_b_log = log(I_b+1);
Rfft1 = fft2(I_r);
Gfft1 = fft2(I_g);
Bfft1 = fft2(I_b);[m,n] = size(I_r);
sigma1 = 15;
sigma2 = 80;
sigma3 = 200;
f1 = fspecial('gaussian', [m, n], sigma1);
f2 = fspecial('gaussian', [m, n], sigma2);
f3 = fspecial('gaussian', [m, n], sigma3);
efft1 = fft2(double(f1));
efft2 = fft2(double(f2));
efft3 = fft2(double(f3));
D_r1 = ifft2(Rfft1.*efft1);
D_g1 = ifft2(Gfft1.*efft1);
D_b1 = ifft2(Bfft1.*efft1);
D_r_log1 = log(D_r1 + 1);
D_g_log1 = log(D_g1 + 1);
D_b_log1 = log(D_b1 + 1);
R1 = I_r_log - D_r_log1;
G1 = I_g_log - D_g_log1;
B1 = I_b_log - D_b_log1;
D_r2 = ifft2(Rfft1.*efft2);
D_g2 = ifft2(Gfft1.*efft2);
D_b2 = ifft2(Bfft1.*efft2);
D_r_log2 = log(D_r2 + 1);
D_g_log2 = log(D_g2 + 1);
D_b_log2 = log(D_b2 + 1);
R2 = I_r_log - D_r_log2;
G2 = I_g_log - D_g_log2;
B2 = I_b_log - D_b_log2;
D_r3 = ifft2(Rfft1.*efft3);
D_g3 = ifft2(Gfft1.*efft3);
D_b3 = ifft2(Bfft1.*efft3);
D_r_log3 = log(D_r3 + 1);
D_g_log3 = log(D_g3 + 1);
D_b_log3 = log(D_b3 + 1);
R3 = I_r_log - D_r_log3;
G3 = I_g_log - D_g_log3;
B3 = I_b_log - D_b_log3;
R = 0.1*R1 + 0.4*R2 + 0.5*R3;
G = 0.1*G1 + 0.4*G2 + 0.5*G3;
B = 0.1*B1 + 0.4*B2 + 0.5*B3;
R = exp(R);
MIN = min(min(R));
MAX = max(max(R));
R = (R - MIN)/(MAX - MIN);
R = adapthisteq(R);
G = exp(G);
MIN = min(min(G));
MAX = max(max(G));
G = (G - MIN)/(MAX - MIN);
G = adapthisteq(G);
B = exp(B);
MIN = min(min(B));
MAX = max(max(B));
B = (B - MIN)/(MAX - MIN);
B = adapthisteq(B);
J = cat(3, R, G, B);
figure;
subplot(121);imshow(I);
subplot(122);imshow(J,[]);

Python の実装:

import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']

# 读取图像
I = cv2.imread('origin.jpg')

# 将图像拆分为R,G,B通道
I_r = I[:, :, 0].astype(float)
I_g = I[:, :, 1].astype(float)
I_b = I[:, :, 2].astype(float)

# 对每个通道进行对数变换
I_r_log = np.log(I_r + 1)
I_g_log = np.log(I_g + 1)
I_b_log = np.log(I_b + 1)

# 获取图像大小
m, n = I_r.shape

# 定义三个不同的高斯滤波核
sigma1 = 15
sigma2 = 80
sigma3 = 200
f1 = cv2.getGaussianKernel(m, sigma1)
f2 = cv2.getGaussianKernel(m, sigma2)
f3 = cv2.getGaussianKernel(m, sigma3)
f1 = f1.dot(f1.T)
f2 = f2.dot(f2.T)
f3 = f3.dot(f3.T)

# 对高斯滤波核进行FFT
efft1 = np.fft.fft2(f1)
efft2 = np.fft.fft2(f2)
efft3 = np.fft.fft2(f3)

# 对R,G,B通道进行FFT
Rfft1 = np.fft.fft2(I_r)
Gfft1 = np.fft.fft2(I_g)
Bfft1 = np.fft.fft2(I_b)

# 对每个通道进行频域滤波
D_r1 = np.fft.ifft2(Rfft1 * efft1)
D_g1 = np.fft.ifft2(Gfft1 * efft1)
D_b1 = np.fft.ifft2(Bfft1 * efft1)
D_r_log1 = np.log(D_r1 + 1)
D_g_log1 = np.log(D_g1 + 1)
D_b_log1 = np.log(D_b1 + 1)
R1 = I_r_log - D_r_log1
G1 = I_g_log - D_g_log1
B1 = I_b_log - D_b_log1

D_r2 = np.fft.ifft2(Rfft1 * efft2)
D_g2 = np.fft.ifft2(Gfft1 * efft2)
D_b2 = np.fft.ifft2(Bfft1 * efft2)
D_r_log2 = np.log(D_r2 + 1)
D_g_log2 = np.log(D_g2 + 1)
D_b_log2 = np.log(D_b2 + 1)
R2 = I_r_log - D_r_log2
G2 = I_g_log - D_g_log2
B2 = I_b_log - D_b_log2

D_r3 = np.fft.ifft2(Rfft1 * efft3)
D_g3 = np.fft.ifft2(Gfft1 * efft3)
D_b3 = np.fft.ifft2(Bfft1 * efft3)
D_r_log3 = np.log(D_r3 + 1)
D_g_log3 = np.log(D_g3 + 1)
D_b_log3 = np.log(D_b3 + 1)
R3 = I_r_log - D_r_log3
G3 = I_g_log - D_g_log3
B3 = I_b_log - D_b_log3

# 对每个通道

おすすめ

転載: blog.csdn.net/qq_39183034/article/details/130243593