图片的光照不均匀处理

文章目录

    • 3D相机的图片内容
    • 亮度和对比度与SGM
    • 一般的光照补偿算法
        • 基于二维伽马函数的光照不均匀图像自适应校正算法
        • 一种基于亮度均衡的图像阈值分割技术
    • opencv函数illuminationChange
    • 亮度均衡与sgm结果
    • 利用双边滤波的实时去高光

随笔笔记,比较散乱、不完整

3D相机的图片内容

目前来看,sgm算法对于布匹的计算能力较好。细节越突出,计算结果越好。有些图片内容,相机的聚焦能力以及分辨率不够的话,就会计算的不够好。

亮度和对比度与SGM

亮度对比度在一定范围内改变对于sgm计算视差结果影响不大。如下图是改变亮度对比度之后计算的视差与原视差的差。
图片的光照不均匀处理_第1张图片

一般的光照补偿算法

结合网上的资料发现比较多的去光照不均匀算法

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

本文发表于北京理工大学学报
该算法流程如图:
图片的光照不均匀处理_第2张图片
将图片投影到hsv域,对亮度v进行gamma校正,然后重新融合图片,得到校正后的图片。

参考网上的matlab代码

clc,close all;
tic;
im=imread('srcmpp.bmp');
%im=imread('qqq.jpg');
figure;
imshow(im);
title('原图');
[h,s,v]=rgb2hsv(im);    %转到hsv空间,对亮度v处理
% 高斯滤波
HSIZE= min(size(im,1),size(im,2));%高斯卷积核尺寸
q=sqrt(2);
SIGMA1=15;%论文里面的c
SIGMA2=80;
SIGMA3=250;
F1 = fspecial('gaussian',HSIZE,SIGMA1/q);
F2 = fspecial('gaussian',HSIZE,SIGMA2/q) ;
F3 = fspecial('gaussian',HSIZE,SIGMA3/q) ;
gaus1= imfilter(v, F1, 'replicate');
gaus2= imfilter(v, F2, 'replicate');
gaus3= imfilter(v, F3, 'replicate');
gaus=(gaus1+gaus2+gaus3)/3;    %多尺度高斯卷积,加权,权重为1/3
% gaus=(gaus*255);
figure;
imshow(gaus,[]);
title('光照分量');
%二维伽马卷积
m=mean(gaus(:));
[w,height]=size(v);
out=zeros(size(v));
gama=power(0.5,((m-gaus)/m));%根据公式gamma校正处理,论文公式有误
out=(power(v,gama));
figure;
imshow(out,[]);
rgb=hsv2rgb(h,s,out);   %转回rgb空间显示
figure;
imshow(rgb);
title('处理结果')
toc;

一种基于亮度均衡的图像阈值分割技术

这个方法来自合工大

  1. 图片分块
  2. 分块求均值
  3. 全局均值-分块均值
  4. 对得到的差插值处理
  5. 原图-差值得到亮度均衡后的图片
    针对高亮和反光有比较好的效果,使用C++函数的处理速度也很快。参考博客获得详细解释及代码
    这个方法会导致亮的部分变暗,暗的部分变亮,其实很好理解,因为分块的区域相对于全局的均值的差必定是有正有负的,所以亮的部分会被削弱,暗的部分会被增强
    我个人认为这个算法是比较好一点的,至少处理效果很明显
    参考网上的C++代码
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(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);
}

opencv函数illuminationChange

这个函数需要提供mask,也就意味着需要预先进行二值化,从而确定需要修正光照的位置,所以不太好用。

亮度均衡与sgm结果

3D暂时不需要亮度均衡

  1. 速度慢
  2. 效果没有肉眼可见的提升
  3. 效果的测试并不好量化

利用双边滤波的实时去高光

图片的光照不均匀处理_第3张图片
原图,论文代码,网上代码

int highlight_remove_Chi(IplImage* src, IplImage* dst, double Re)
{
	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);
		}
	}
	return 1;
}

调用该函数需要Mat 与IplImage的相互转化

Mat src=imread("xxx.jpg");
Mat dst;
	IplImage* pBinary = &IplImage(src);
	IplImage* pBinary2 = &IplImage(src);// = &IplImage(dst);
	//深拷贝只要再加一次复制数据:
	IplImage *input = cvCloneImage(pBinary);
	if (highlight_remove_Chi(input, pBinary2, 1.0)) {
		dst = cvarrToMat(pBinary2);
		//	imshow("image1", src);
		imshow("save1", dst);
		waitKey();
	}

网上的代码应该是缺少了优化迭代的过程,对于大块的反光几乎没有办法处理

你可能感兴趣的:(比较乱的笔记,OpenCV)