一般的光照补偿算法
结合网上的资料发现比较多的去光照不均匀算法
基于二维伽马函数的光照不均匀图像自适应校正算法
本文发表于北京理工大学学报
该算法流程如图:
将图片投影到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<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); }
opencv函数illuminationChange
这个函数需要提供mask,也就意味着需要预先进行二值化,从而确定需要修正光照的位置,所以不太好用。
亮度均衡与sgm结果
3D暂时不需要亮度均衡
1. 速度慢
2. 效果没有肉眼可见的提升
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(); }
网上的代码应该是缺少了优化迭代的过程,对于大块的反光几乎没有办法处理
————————————————
版权声明:本文为CSDN博主「VeraWin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/TiffanyXYf/article/details/106543238

