图像亮度校正方法

人脸图像亮度校正

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;
	}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NineDays66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值