opencv之光照补偿和去除光照

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29540745/article/details/74681853

本博客借用了不少其他博客,相当于知识整理

一、光照补偿

1.直方图均衡化

#include "stdafx.h"  
#include<opencv2/opencv.hpp>  
#include<iostream>  
using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
	Mat image = imread("D://vvoo//123.jpg", 1);
	if (!image.data)
	{
		cout << "image loading error" <<endl;
		return -1;
	}
	Mat imageRGB[3];
	split(image, imageRGB);
	for (int i = 0; i < 3; i++)
	{
		equalizeHist(imageRGB[i], imageRGB[i]);
	}
	merge(imageRGB, 3, image);
	imshow("equalizeHist", image);
	waitKey();
	return 0;
}




2.gamma corection:



http://www.cambridgeincolour.com/tutorials/gamma-correction.htm

人眼是按照gamma < 1的曲线对输入图像进行处理的。

原图gamma=1.2ga=1.8ga=2.2ga=3.2


#include<opencv2/opencv.hpp>  
#include<iostream>  
using namespace std;
using namespace cv;
// Normalizes a given image into a value range between 0 and 255.  
Mat norm(const Mat& src) {
	// Create and return normalized image:  
	Mat dst;
	switch (src.channels()) {
	case 1:
		cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
		break;
	case 3:
		cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
		break;
	default:
		src.copyTo(dst);
		break;
	}
	return dst;
}

int main()
{
	Mat image,X,I;

	VideoCapture cap(0);
	while (1)
	{
		cap >> image;
		image.convertTo(X, CV_32FC1); //转换格式
		float gamma = 4;
		pow(X, gamma, I);
		
		imshow("Original Image", image);
		imshow("Gamma correction image", norm(I));
		char key = waitKey(30);
		if (key=='q' )
			break;
	}
	return 0;
}

3.拉普拉斯算子增强


int main(int argc, char *argv[])
{
	Mat image = imread("D://vvoo//123.jpg", 1);
	if (!image.data)
	{
		cout << "image loading error" <<endl;
		return -1;
	}
	imshow("原图", image);
	Mat imageEnhance;
	Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, 0, 7, 0, 0, -1, 0);
	filter2D(image, imageEnhance, CV_8UC3, kernel);
	imshow("拉普拉斯算子图像增强效果", imageEnhance);
	imwrite("C://Users//TOPSUN//Desktop//123.jpg",imageEnhance);
	waitKey();
	return 0;
}
效果不好



4.对数变换

对数图像增强是图像增强的一种常见方法,其公式为: S = c log(r+1),其中c是常数(以下算法c=255/(log(256)),这样可以实现整个画面的亮度增大此时默认v=e,即 S = c ln(r+1)。

如下图,对数使亮度比较低的像素转换成亮度比较高的,而亮度较高的像素则几乎没有变化,这样就使图片整体变亮。



int main(int argc, char *argv[])
{
	double temp = 255 / log(256);
	cout << "doubledouble temp ="<< temp<<endl;

	Mat image = imread("D://vvoo//123.jpg", 1);
	if (!image.data)
	{
		cout << "image loading error" <<endl;
		return -1;
	}
	imshow("原图", image);
	Mat imageLog(image.size(), CV_32FC3);
	for (int i = 0; i < image.rows; i++)
	{
		for (int j = 0; j < image.cols; j++)
		{
			imageLog.at<Vec3f>(i, j)[0] = temp* log(1 + image.at<Vec3b>(i, j)[0]);
			imageLog.at<Vec3f>(i, j)[1] = temp*log(1 + image.at<Vec3b>(i, j)[1]);
			imageLog.at<Vec3f>(i, j)[2] = temp*log(1 + image.at<Vec3b>(i, j)[2]);
		}
	}
	//归一化到0~255    
	normalize(imageLog, imageLog, 0, 255, CV_MINMAX); 
	//转换成8bit图像显示    
	convertScaleAbs(imageLog, imageLog);
	int channel = image.channels();
	cout << channel << endl;
	imshow("Soure", image);
	imshow("after", imageLog);
	imwrite("C://Users//TOPSUN//Desktop//123.jpg", imageLog);
	waitKey();
	return 0;
}

二、去除光照

5.RGB归一化

据说能消除光照,自己实现出来好垃圾啊

int main(int argc, char *argv[])
{
	//double temp = 255 / log(256);
	//cout << "doubledouble temp ="<< temp<<endl;
	
	Mat  image = imread("D://vvoo//sun_face.jpg", 1);
	if (!image.data)
	{
		cout << "image loading error" <<endl;
		return -1;
	}
	imshow("原图", image);
	Mat src(image.size(), CV_32FC3);
	for (int i = 0; i < image.rows; i++)
	{
		for (int j = 0; j < image.cols; j++)
		{
			src.at<Vec3f>(i, j)[0] = 255 * (float)image.at<Vec3b>(i, j)[0] / ((float)image.at<Vec3b>(i, j)[0] + (float)image.at<Vec3b>(i, j)[2] + (float)image.at<Vec3b>(i, j)[1]+0.01);
			src.at<Vec3f>(i, j)[1] = 255 * (float)image.at<Vec3b>(i, j)[1] / ((float)image.at<Vec3b>(i, j)[0] + (float)image.at<Vec3b>(i, j)[2] + (float)image.at<Vec3b>(i, j)[1]+0.01);
			src.at<Vec3f>(i, j)[2] = 255 * (float)image.at<Vec3b>(i, j)[2] / ((float)image.at<Vec3b>(i, j)[0] + (float)image.at<Vec3b>(i, j)[2] + (float)image.at<Vec3b>(i, j)[1]+0.01);
		}
	}
	
	normalize(src, src, 0, 255, CV_MINMAX);
      
	convertScaleAbs(src,src);
	imshow("rgb", src);
	imwrite("C://Users//TOPSUN//Desktop//123.jpg", src);
	waitKey(0);
	return 0;
}




6.另一种去除光照的方法


void unevenLightCompensate(Mat &image, int blockSize)
{
	if (image.channels() == 3) cvtColor(image, image, 7);
	double average = mean(image)[0];
	int rows_new = ceil(double(image.rows) / double(blockSize));
	int cols_new = ceil(double(image.cols) / double(blockSize));
	Mat blockImage;
	blockImage = Mat::zeros(rows_new, cols_new, CV_32FC1);
	for (int i = 0; i < rows_new; i++)
	{
		for (int j = 0; j < cols_new; j++)
		{
			int rowmin = i*blockSize;
			int rowmax = (i + 1)*blockSize;
			if (rowmax > image.rows) rowmax = image.rows;
			int colmin = j*blockSize;
			int colmax = (j + 1)*blockSize;
			if (colmax > image.cols) colmax = image.cols;
			Mat imageROI = image(Range(rowmin, rowmax), Range(colmin, colmax));
			double temaver = mean(imageROI)[0];
			blockImage.at<float>(i, j) = temaver;
		}
	}
	blockImage = blockImage - average;
	Mat blockImage2;
	resize(blockImage, blockImage2, image.size(), (0, 0), (0, 0), INTER_CUBIC);
	Mat image2;
	image.convertTo(image2, CV_32FC1);
	Mat dst = image2 - blockImage2;
	dst.convertTo(image, CV_8UC1);
}
int main(int argc, char *argv[])
{
	//double temp = 255 / log(256);
	//cout << "doubledouble temp ="<< temp<<endl;
	
	Mat  image = imread("C://Users//TOPSUN//Desktop//2.jpg", 1);
	if (!image.data)
	{
		cout << "image loading error" <<endl;
		return -1;
	}
	imshow("原图", image);
	unevenLightCompensate(image, 12);
	imshow("rgb", image);
	imwrite("C://Users//TOPSUN//Desktop//123.jpg", image);
	waitKey(0);
	return 0;
}



7.又找到一个


int highlight_remove_Chi(IplImage* src, IplImage* dst)
{
	int height = src->height;
	int width = src->width;
	int step = src->widthStep;
	int i = 0, j = 0;
	unsigned char R, G, B, MaxC;
	double alpha, beta, alpha_r, alpha_g, alpha_b, beta_r, beta_g, beta_b, temp = 0, realbeta = 0, minalpha = 0;
	double gama, gama_r, gama_g, gama_b;
	unsigned char* srcData;
	unsigned char* dstData;
	for (i = 0; i<height; i++)
	{
		srcData = (unsigned char*)src->imageData + i*step;
		dstData = (unsigned char*)dst->imageData + i*step;
		for (j = 0; j<width; j++)
		{
			R = srcData[j * 3];
			G = srcData[j * 3 + 1];
			B = srcData[j * 3 + 2];

			alpha_r = (double)R / (double)(R + G + B);
			alpha_g = (double)G / (double)(R + G + B);
			alpha_b = (double)B / (double)(R + G + B);
			alpha = max(max(alpha_r, alpha_g), alpha_b);
			MaxC = max(max(R, G), B);// compute the maximum of the rgb channels
			minalpha = min(min(alpha_r, alpha_g), alpha_b);                 beta_r = 1 - (alpha - alpha_r) / (3 * alpha - 1);
			beta_g = 1 - (alpha - alpha_g) / (3 * alpha - 1);
			beta_b = 1 - (alpha - alpha_b) / (3 * alpha - 1);
			beta = max(max(beta_r, beta_g), beta_b);//将beta当做漫反射系数,则有                 // gama is used to approximiate the beta
			gama_r = (alpha_r - minalpha) / (1 - 3 * minalpha);
			gama_g = (alpha_g - minalpha) / (1 - 3 * minalpha);
			gama_b = (alpha_b - minalpha) / (1 - 3 * minalpha);
			gama = max(max(gama_r, gama_g), gama_b);

			temp = (gama*(R + G + B) - MaxC) / (3 * gama - 1);
			//beta=(alpha-minalpha)/(1-3*minalpha)+0.08;
			//temp=(gama*(R+G+B)-MaxC)/(3*gama-1);
			dstData[j * 3] = R - (unsigned char)(temp + 0.5);
			dstData[j * 3 + 1] = G - (unsigned char)(temp + 0.5);
			dstData[j * 3 + 2] = B - (unsigned char)(temp + 0.5);
		}
	}
	cvShowImage("src", src);
	cvShowImage("dst", dst);
	
	return 1;
}

void main()
{
	IplImage *src = cvLoadImage("C://Users//TOPSUN//Desktop//2.jpg");
	IplImage *dst = cvCreateImage(cvSize(src->width, src->height), src->depth, 3);
	if (!src)
	{
		printf("请确保图像输入正确;");
		return;
	}
	highlight_remove_Chi(src, dst);
	cvSaveImage("C://Users//TOPSUN//Desktop//123.jpg", dst);
	cvWaitKey(0);
}



未完待续。。。


猜你喜欢

转载自blog.csdn.net/qq_29540745/article/details/74681853