关于数字图像处理:本文介绍一种用于解决光照不均匀的图像自适应校正算法。光照不均匀其实是非常常见的一种状况,为了解决图像曝光不足,或者不均衡而提出来的解决方案之一,关于【Retiex解决方案请查看】。
论文原文: ​​​点击查看​

算法原理
论文使用了Retinex的多尺度高斯滤波求取「光照分量」,然后使用了「二维Gamma函数」针对原图的「HSV空间的V(亮度)分量」进行亮度改变,得到结果。

具体实现流程如下:

基于二维伽马函数的光照不均匀图像自适应校正算法_解决方案


其中:

基于二维伽马函数的光照不均匀图像自适应校正算法_javascript_02


上面图像中 基于二维伽马函数的光照不均匀图像自适应校正算法_i++_03 应该是:

基于二维伽马函数的光照不均匀图像自适应校正算法_javascript_04

Mat RGB2HSV(Mat src) {
int row = src.rows;
int col = src.cols;
Mat dst(row, col, CV_32FC3);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
float b = src.at<Vec3b>(i, j)[0] / 255.0;
float g = src.at<Vec3b>(i, j)[1] / 255.0;
float r = src.at<Vec3b>(i, j)[2] / 255.0;
float minn = min(r, min(g, b));
float maxx = max(r, max(g, b));
dst.at<Vec3f>(i, j)[2] = maxx; //V
float delta = maxx - minn;
float h, s;
if (maxx != 0) {
s = delta / maxx;
}
else {
s = 0;
}
if (r == maxx) {
h = (g - b) / delta;
}
else if (g == maxx) {
h = 2 + (b - r) / delta;
}
else {
h = 4 + (r - g) / delta;
}
h *= 60;
if (h < 0)
h += 360;
dst.at<Vec3f>(i, j)[0] = h;
dst.at<Vec3f>(i, j)[1] = s;
}
}
return dst;
}

Mat HSV2RGB(Mat src) {
int row = src.rows;
int col = src.cols;
Mat dst(row, col, CV_8UC3);
float r, g, b, h, s, v;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
h = src.at<Vec3f>(i, j)[0];
s = src.at<Vec3f>(i, j)[1];
v = src.at<Vec3f>(i, j)[2];
if (s == 0) {
r = g = b = v;
}
else {
h /= 60;
int offset = floor(h);
float f = h - offset;
float p = v * (1 - s);
float q = v * (1 - s * f);
float t = v * (1 - s * (1 - f));
switch (offset)
{
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
default:
break;
}
}
dst.at<Vec3b>(i, j)[0] = int(b * 255);
dst.at<Vec3b>(i, j)[1] = int(g * 255);
dst.at<Vec3b>(i, j)[2] = int(r * 255);
}
}
return dst;
}

Mat work(Mat src) {
int row = src.rows;
int col = src.cols;
Mat now = RGB2HSV(src);
Mat H(row, col, CV_32FC1);
Mat S(row, col, CV_32FC1);
Mat V(row, col, CV_32FC1);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
H.at<float>(i, j) = now.at<Vec3f>(i, j)[0];
S.at<float>(i, j) = now.at<Vec3f>(i, j)[1];
V.at<float>(i, j) = now.at<Vec3f>(i, j)[2];
}
}
int kernel_size = min(row, col);
if (kernel_size % 2 == 0) {
kernel_size -= 1;
}
float SIGMA1 = 15;
float SIGMA2 = 80;
float SIGMA3 = 250;
float q = sqrt(2.0);
Mat F(row, col, CV_32FC1);
Mat F1, F2, F3;
GaussianBlur(V, F1, Size(kernel_size, kernel_size), SIGMA1 / q);
GaussianBlur(V, F2, Size(kernel_size, kernel_size), SIGMA2 / q);
GaussianBlur(V, F3, Size(kernel_size, kernel_size), SIGMA3 / q);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
F.at <float>(i, j) = (F1.at<float>(i, j) + F2.at<float>(i, j) + F3.at<float>(i, j)) / 3.0;
}
}
float average = mean(F)[0];
Mat out(row, col, CV_32FC1);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
float gamma = powf(0.5, (average - F.at<float>(i, j)) / average);
out.at<float>(i, j) = powf(V.at<float>(i, j), gamma);
}
}
vector <Mat> v;
v.push_back(H);
v.push_back(S);
v.push_back(out);
Mat merge_;
merge(v, merge_);
Mat dst = HSV2RGB(merge_);
return dst;
}

python实现

import cv2
import numpy as np


def Adaptive_light_correction(img):
height = img.shape[0]
width = img.shape[1]

HSV_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
V = HSV_img[:,:,2]

kernel_size = min(height, width)
if kernel_size % 2 == 0:
kernel_size -= 1

SIGMA1 = 15
SIGMA2 = 80
SIGMA3 = 250
q = np.sqrt(2.0)
F = np.zeros((height,width,3),dtype=np.float64)
F[:,:,0] = cv2.GaussianBlur(V,(kernel_size, kernel_size),SIGMA1 / q)
F[:,:,1] = cv2.GaussianBlur(V,(kernel_size, kernel_size),SIGMA2 / q)
F[:,:,2] = cv2.GaussianBlur(V,(kernel_size, kernel_size),SIGMA3 / q)
F_mean = np.mean(F,axis=2)
average = np.mean(F_mean)
gamma = np.power(0.5,np.divide(np.subtract(average,F_mean),average))
out = np.power(V/255.0,gamma)*255.0
HSV_img[:,:,2] = out
img = cv2.cvtColor(HSV_img,cv2.COLOR_HSV2BGR)
return img


if __name__ == '__main__':
img = cv2.imread("./112.jpg")
result_img = Adaptive_light_correction(img)
cv2.imshow("result_img",result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

测试原图与效果如下:

基于二维伽马函数的光照不均匀图像自适应校正算法_解决方案_05


基于二维伽马函数的光照不均匀图像自适应校正算法_解决方案_06


参考:https://cloud.tencent.com/developer/article/1588007