Automatic color scale of image processing opencv&c++

Automatic color scale

The first step is to count the histograms of each channel (red/green/blue) respectively.

The second step is to calculate the upper and lower limits of each channel according to the given parameters. What does it mean? For example, for the blue channel, we accumulate the statistical histogram from level 0 upwards. When the accumulated value is greater than the number of pixels in LowCut , the level value at this time is counted as BMin. Then accumulate the histogram from the gradation level 255 downwards. If the accumulated value is greater than all pixels of HighCut , the gradation value at this time is counted as BMax.

The third step is to construct a mapping table according to the MinBlue/MaxBlue we just calculated. The rule of the mapping table is that for a value smaller than MinBlue, the implicit is 0 (in fact, this sentence is not correct, how much is the implicit It is related to the color set by the shadow in the automatic color correction option dialog box. By default, it is black, and the corresponding RGB components are all 0, so we will imply 0 here. If you are interested, you can also specify other Parameter), for a value greater than MaxBlue, the implicit is 255 (similarly, this value is related to the color setting of the highlight), for a value between MinBlue and MaxBlue, linear implicit is performed, and the default is implicit It is between 0 and 255 (Of course, it is actually related to our dark tone and highlight settings, and here is actually not a linear implicit, there is a Gamma correction, for simplicity, there is no big problem with the linear replacement effect).

The last step is to infer the image data of each channel.

// AutoLevel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
#include<vector>
#include <algorithm>
using namespace cv;

void AutoLevelsAdjust(cv::Mat& src, cv::Mat& dst)
{
    
    
	CV_Assert(!src.empty() && src.channels() == 3);

	//统计灰度直方图
	int BHist[256] = {
    
     0 };	//B分离
	int GHist[256] = {
    
     0 };	//G分量
	int RHist[256] = {
    
     0 };	//R分量
	cv::MatIterator_<Vec3b> its, ends;
	for (its = src.begin<Vec3b>(), ends = src.end<Vec3b>(); its != ends; its++)
	{
    
    
		BHist[(*its)[0]]++;
		GHist[(*its)[1]]++;
		RHist[(*its)[2]]++;
	}

	//设置LowCut和HighCut
	float LowCut = 0.5;
	float HighCut = 0.5;

	//根据LowCut和HighCut查找每个通道最大值最小值
	int BMax = 0, BMin = 0;
	int GMax = 0, GMin = 0;
	int RMax = 0, RMin = 0;

	int TotalPixels = src.cols * src.rows;
	float LowTh = LowCut * 0.01 * TotalPixels;
	float HighTh = HighCut * 0.01 * TotalPixels;

	//B通道查找最小最大值
	int sumTempB = 0;
	for (int i = 0; i < 256; i++)
	{
    
    
		sumTempB += BHist[i];
		if (sumTempB >= LowTh)
		{
    
    
			BMin = i;
			break;
		}
	}
	sumTempB = 0;
	for (int i = 255; i >= 0; i--)
	{
    
    
		sumTempB += BHist[i];
		if (sumTempB >= HighTh)
		{
    
    
			BMax = i;
			break;
		}
	}

	//G通道查找最小最大值
	int sumTempG = 0;
	for (int i = 0; i < 256; i++)
	{
    
    
		sumTempG += GHist[i];
		if (sumTempG >= LowTh)
		{
    
    
			GMin = i;
			break;
		}
	}
	sumTempG = 0;
	for (int i = 255; i >= 0; i--)
	{
    
    
		sumTempG += GHist[i];
		if (sumTempG >= HighTh)
		{
    
    
			GMax = i;
			break;
		}
	}

	//R通道查找最小最大值
	int sumTempR = 0;
	for (int i = 0; i < 256; i++)
	{
    
    
		sumTempR += RHist[i];
		if (sumTempR >= LowTh)
		{
    
    
			RMin = i;
			break;
		}
	}
	sumTempR = 0;
	for (int i = 255; i >= 0; i--)
	{
    
    
		sumTempR += RHist[i];
		if (sumTempR >= HighTh)
		{
    
    
			RMax = i;
			break;
		}
	}

	//对每个通道建立分段线性查找表
	//B分量查找表
	int BTable[256] = {
    
     0 };
	for (int i = 0; i < 256; i++)
	{
    
    
		if (i <= BMin)
			BTable[i] = 0;
		else if (i > BMin && i < BMax)
			BTable[i] = cvRound((float)(i - BMin) / (BMax - BMin) * 255);
		else
			BTable[i] = 255;
	}

	//G分量查找表
	int GTable[256] = {
    
     0 };
	for (int i = 0; i < 256; i++)
	{
    
    
		if (i <= GMin)
			GTable[i] = 0;
		else if (i > GMin && i < GMax)
			GTable[i] = cvRound((float)(i - GMin) / (GMax - GMin) * 255);
		else
			GTable[i] = 255;
	}

	//R分量查找表
	int RTable[256] = {
    
     0 };
	for (int i = 0; i < 256; i++)
	{
    
    
		if (i <= RMin)
			RTable[i] = 0;
		else if (i > RMin && i < RMax)
			RTable[i] = cvRound((float)(i - RMin) / (RMax - RMin) * 255);
		else
			RTable[i] = 255;
	}

	//对每个通道用相应的查找表进行分段线性拉伸
	cv::Mat dst_ = src.clone();
	cv::MatIterator_<Vec3b> itd, endd;
	for (itd = dst_.begin<Vec3b>(), endd = dst_.end<Vec3b>(); itd != endd; itd++)
	{
    
    
		(*itd)[0] = BTable[(*itd)[0]];
		(*itd)[1] = GTable[(*itd)[1]];
		(*itd)[2] = RTable[(*itd)[2]];
	}
	dst = dst_;
}

int main()
{
    
    
	Mat image = imread("E:\\picture\\wutian.jpg");
	Mat dst = Mat::zeros(image.rows, image.cols, CV_8UC1);
	AutoLevelsAdjust(image, dst);
	imshow("src", image);
	imshow("dst", dst);
	while (char(waitKey(1)) != 'q') {
    
    }
}


Insert picture description here

Automatic color gradation is used for defogging, which is still the most stable. Although there are many other enhancement methods, such as dark channel defogging, optimizing contrast defogging, and Color-Lines-based defogging, these algorithms are still not very stable. When the prior knowledge is invalid, the processing distortion is more serious. But the automatic color scale is relatively stable.

Guess you like

Origin blog.csdn.net/qq_36587495/article/details/108582564