老规矩,先上结论:
光影魔术手的补光相当于调整曲线操作,曲线映射关系如下:

连续补光两次,曲线如下:

有时,我会先补光两次,再调整一下gamma值,其曲线如下:

附上补光的映射表的matlab函数封装:
function y=BuGuangTable(x) % 光影魔术手的补光映射表 % Input: % x: 整数,x \in [0, 255] % Output: % y:整数,y \in [0, 255] y_uint8=[0,2,3,5,6,8,10,11,13,14,16,18,19,21,22,23,25,27,28,30,31,32,33,35,36,38,39,41,42,44,45,46,47,49,51,52,53,55,56,57,59,60,62,63,64,65,67,68,70,71,71,73,75,76,77,78,79,81,82,83,84,86,87,88,89,91,92,93,94,95,97,98,99,100,101,102,104,105,106,107,109,109,110,112,113,114,115,116,117,118,120,120,122,123,124,125,126,127,127,129,130,131,132,133,134,135,136,137,138,139,140,141,142,142,144,145,145,146,147,148,149,150,151,152,153,154,155,156,156,157,158,159,160,161,162,163,164,164,166,166,167,168,169,170,171,171,173,173,174,175,176,176,178,178,179,180,181,181,182,182,183,183,184,185,185,186,186,187,188,188,189,190,190,191,192,192,193,193,194,195,195,196,197,197,198,199,199,200,201,201,202,203,203,204,205,205,206,207,207,208,209,210,210,211,212,213,213,214,215,215,216,217,218,218,219,220,221,222,222,223,224,225,226,227,227,228,229,230,231,231,232,233,234,235,236,237,238,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,255]; y=y_uint8(x+1); end
% 测试光影魔术手补光的响应曲线
%%生成测试图像 imr1=0:255; imr2=[1:255 0]; imr3=255:-1:0; im=[imr1; imr1; imr2;imr2; imr3;imr3]; im=uint8(im); imwrite(im,'gray.bmp'); %为了保证像素值不因为jpg的压缩而改变,这里使用bmp格式 %% 验证光影魔术手的补光操作只是一个灰度映射操作; %需要先用 光影魔术手对'gray.bmp'补光后存为'grayDisposed.bmp' imDisposed=imread('grayDisposed.bmp'); imDG=imDisposed(:,:,1); all(imDG(1,:)==imDG(2,:)) all(imDG(3,:)==imDG(4,:)) all(imDG(5,:)==imDG(6,:)) all(imDG(2,:)==[imDG(3,end) imDG(3,1:end-1)]) r2Equal_r5=all(imDG(2,:)==imDG(5,end:-1:1) ) %% 绘制光影魔术手补光的响应曲线 modeName='光影魔术手补光'; x=linspace(0,1,256); y_uint8=imDG(1,:); y=double(y_uint8)/255; figure1 = figure; axes1 = axes('Parent',figure1,'YTick',0:.1:1,'XTick',0:.1:1,... 'PlotBoxAspectRatio',[1 1 1],... 'DataAspectRatio',[1 1 1]); % xlim(axes1,[0 1]); % ylim(axes1,[0 1]); grid on box(axes1,'on'); hold(axes1,'all'); plot(x,y,'Parent',axes1,'LineWidth',3,'Color',[1 0 0], 'DisplayName',modeName); plot(x,x,'Parent',axes1,'LineWidth',2,'LineStyle','--', 'DisplayName','正常模式'); xlabel('补光前的灰度值','FontSize',16); ylabel('补光后的灰度值','FontSize',16); title([modeName ' 响应曲线'],'FontSize',16); legend1 = legend(axes1,'show'); set(legend1,'Location','SouthEast'); % clear all %% modeName='光影魔术手补光2次'; x=linspace(0,1,256); y=BuGuangTable(BuGuangTable(0:255))/255; figure1 = figure; axes1 = axes('Parent',figure1,'YTick',0:.1:1,'XTick',0:.1:1,... 'PlotBoxAspectRatio',[1 1 1],... 'DataAspectRatio',[1 1 1]); % xlim(axes1,[0 1]); % ylim(axes1,[0 1]); grid on box(axes1,'on'); hold(axes1,'all'); plot(x,y,'Parent',axes1,'LineWidth',3,'Color',[1 0 0], 'DisplayName',modeName); plot(x,x,'Parent',axes1,'LineWidth',2,'LineStyle','--', 'DisplayName','正常模式'); xlabel('补光前的灰度值','FontSize',16); ylabel('补光后的灰度值','FontSize',16); title([modeName ' 响应曲线'],'FontSize',16); legend1 = legend(axes1,'show'); set(legend1,'Location','SouthEast'); %% modeName='补光2次, 参数为1.2的gamma校正一次'; x=linspace(0,1,256); y=BuGuangTable(BuGuangTable(0:255))/255; % y=BuGuangTable(0:255)/255; y=y.^1.2; figure1 = figure; axes1 = axes('Parent',figure1,'YTick',0:.1:1,'XTick',0:.1:1,... 'PlotBoxAspectRatio',[1 1 1],... 'DataAspectRatio',[1 1 1]); % xlim(axes1,[0 1]); % ylim(axes1,[0 1]); grid on box(axes1,'on'); hold(axes1,'all'); plot(x,y,'Parent',axes1,'LineWidth',3,'Color',[1 0 0], 'DisplayName',modeName); plot(x,x,'Parent',axes1,'LineWidth',2,'LineStyle','--', 'DisplayName','正常模式'); xlabel('补光前的灰度值','FontSize',16); ylabel('补光后的灰度值','FontSize',16); title([ modeName ' 响应曲线'],'FontSize',16); legend1 = legend(axes1,'show'); set(legend1,'Location','SouthEast');
完整代码、图片见附件~