人脸图像亮度校正
import os
import cv2
import math
import numpy as np
class FaceEnhance():
"""MobileFace enhance for dark or bright face.
"""
def __init__(self, **kwargs):
super(MobileFaceEnhance, self).__init__(**kwargs)
def hist_statistic(self, img, dark_th=80, bright_th=200, dark_shift=0.4, bright_shift=2.5):
"""Face gamma correction.
Parameters
----------
img: mat
The Mat data format of reading from the original image using opencv.
dark_th: int, default is 80.
Black pixel threshold whith typical values from 50 to 100.
bright_th: int, default is 200.
White pixel threshold whith typical values from 180 to 220.
dark_shift: float, default is 0.4.
Gamma shift value for gamma correction to brighten the face.
The typical values are from 0.3 to 0.5.
bright_shift: float, default is 2.5.
Gamma shift value for gamma correction to darken the face.
The typical values are from 2.0 to 3.0.
Returns
-------
gamma: float
The gamma value for gamma correction.
hist: list
The gray histogram for face.
"""
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# method 1
# hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256])
# method 2
hist = cv2.calcHist(img_gray, [0], None, [256], [0, 256])
dark_rate = np.sum(hist[:dark_th]) / np.sum(hist)
normal_rate = np.sum(hist[dark_th:bright_th]) / np.sum(hist)
bright_rate = np.sum(hist[bright_th:]) / np.sum(hist)
rate = [dark_rate, normal_rate, bright_rate]
if np.max(rate) == dark_rate:
gamma = np.minimum(np.maximum(1.0 - math.pow(dark_rate, 2) + dark_shift, dark_shift), 1.0)
elif np.max(rate) == bright_rate:
gamma = math.pow(bright_rate, 3) + bright_shift
else:
gamma = 1.0
return gamma, hist
def gamma_trans(self, img, gamma):
"""Face gamma correction.
Parameters
----------
img: mat
The Mat data format of reading from the original image using opencv.
gamma: float
The gamma value for gamma correction.
Returns
-------
type: mat
Face BGR image after gamma correction.
"""
gamma_table = [np.power(x / 255.0, gamma)*255.0 for x in range(256)]
gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
return cv2.LUT(img, gamma_table)
C++
cv::Mat gamma(const cv::Mat& src, const float gamma) {
cv::Mat temp, temp1, dst;
src.convertTo(temp, CV_32FC1);
//float gamma = 1 / 2.2;
cv::pow(temp, gamma, temp1);
// Create and return normalized image:
switch (temp1.channels()) {
case 1:
cv::normalize(temp1, dst, 0, 255, cv::NORM_MINMAX, CV_8UC1);
break;
case 3:
cv::normalize(temp1, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3);
break;
default:
temp1.copyTo(dst);
break;
}
return dst;
}
float get_gama_value(cv::Mat roi, int dark_th = 80, int bright_th = 200, float dark_shift = 0.4, float bright_shift = 2.5) {
float gamma = 1.0;
int channels = 0;
cv::MatND dstHist;
int histSize[] = { 256 }; //如果写成int histSize = 256;调用计算直方图的函数的时,该变量需写成&histSize
float midRanges[] = { 0, 256 };
const float *ranges[] = { midRanges };
calcHist(&roi, 1, &channels, cv::Mat(), dstHist, 1, histSize, ranges, true, false);
float sum_dark = 0, sum_normal = 0, sum_bright = 0, sum = 0;
for (size_t i = 0; i < 255; i++)
{
if (i < dark_th) {
sum_dark += dstHist.at<float>(i);
}
else if (i < bright_th) {
sum_normal += dstHist.at<float>(i);
}
else {
sum_bright += dstHist.at<float>(i);
}
}
std::cout << "dark:" << sum_dark << " norm:" << sum_normal << " bright:" << sum_bright << std::endl;
sum = sum_dark + sum_normal + sum_bright;
float dark_rate = sum_dark / sum;
float normal_rate = sum_normal / sum;
float bright_rate = sum_bright / sum;
if (dark_rate > normal_rate && dark_rate > bright_rate) {
gamma = min(max(1.0 - std::pow(dark_rate, 2) + dark_shift, dark_shift), 1.0);
}
else if (bright_rate > dark_rate && bright_rate > normal_rate) {
gamma = std::pow(bright_rate, 3) + bright_shift;
std::cout << ".................................light:"<<gamma << std::endl;
}
return gamma;
}