
import numpy as np
import math
import cv2
# 감마 보정 함수
def estimate_optimal_gamma(img, std, r):
s = (img ** r)
up = s - std
down = s * np.log1p(img)
optimal_r = r - (up / down)
if (abs(r - optimal_r) < 0.0000001).all:
return optimal_r
else:
estimate_optimal_gamma(img, std, optimal_r)
img = cv2.imread('chair.png')
cv2.imshow('original',img)
height, width, channel = img.shape
B = img[..., 0]
G = img[..., 1]
R = img[..., 2]
Y = np.zeros((height, width), dtype=np.float64)
# A.휘도 정규화
for x in range(height):
for y in range(width):
Y[x][y] = (0.299 * R[x][y] + 0.587 * G[x][y] + 0.114 * B[x][y])
# 'Y' 휘도 정규화
MAX = max(map(max, Y))
for x in range(height):
for y in range(width):
Y[x][y] = math.log((Y[x][y] + 1), MAX)
# B. 감마보정
bright = np.zeros((height, width), dtype=np.float64)
dark = np.zeros((height, width), dtype=np.float64)
# 밝은영역 어두운 영역 나누기
for x in range(height):
for y in range(width):
if Y[x][y] > 0.5:
dark[x][y] = Y[x][y]
else:
bright[x][y] = Y[x][y]
# 표준편차
dark_std = np.std(dark)
bright_std = 1 - np.std(dark)
# 감마보정 적용
dark_r = estimate_optimal_gamma(dark, dark_std, 1.0)
bright_r = estimate_optimal_gamma(bright, bright_std, 1.0)
"""
print(dark_r)
print(bright_r)
"""
# 이미지 합성
w = np.zeros((height, width), dtype=np.float64)
Y_out = np.zeros((height, width), dtype=np.float64)
for x in range(height):
for y in range(width):
w[x][y] = math.exp(-(bright[x][y] ** 2) / (2 * (0.5) ** 2))
Y_out[x][y] = (
(w[x][y]) * (((dark[x][y] ** dark_r[x][y]))) + ((1 - w[x][y]) * ((bright[x][y] ** bright_r[x][y]))))
# 색 복원
for x in range(height):
for y in range(width):
R[x][y] = Y_out[x][y] * np.power((R[x][y] / Y[x][y]), (1 - np.tanh(bright[x][y])))
G[x][y] = Y_out[x][y] * np.power((G[x][y] / Y[x][y]), (1 - np.tanh(bright[x][y])))
B[x][y] = Y_out[x][y] * np.power((B[x][y] / Y[x][y]), (1 - np.tanh(bright[x][y])))
result = (np.dstack((B, G, R)).astype(np.uint8))
cv2.imshow('Output Image', result)
cv2.waitKey(0)
코드
import cv2
import numpy as np
from skimage.metrics import structural_similarity as ssim
def calculate_psnr(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return float('inf')
max_pixel = 255.0
psnr = 20 * np.log10(max_pixel / np.sqrt(mse))
return psnr
def calculate_ssim(img1, img2):
return ssim(img1, img2, multichannel=True)
# 이미지 로드
low_image = cv2.imread('chair.png')
restored_image = cv2.imread('restored_image.png')
# 이미지를 그레이스케일로 변환
low_image_gray = cv2.cvtColor(low_image, cv2.COLOR_BGR2GRAY)
restored_image_gray = cv2.cvtColor(restored_image, cv2.COLOR_BGR2GRAY)
# PSNR 계산
psnr = calculate_psnr(low_image_gray, restored_image_gray)
print(f"PSNR: {psnr} dB")
# SSIM 계산
ssim_score = calculate_ssim(low_image_gray, restored_image_gray)
print(f"SSIM: {ssim_score}")
결과 이미지

결과
PSNR: 30.782334103567116 dB
SSIM: 0.5385916414339124
결과
PSNR: 30.240407956672627 dB
SSIM: 0.6787482216085202
PSNR: 30.36245081307683 dB
SSIM: 0.63387279567819