180 lines
4.5 KiB
Mathematica
180 lines
4.5 KiB
Mathematica
|
% Create the color enhancement look-up table and write it to
|
||
|
% file colorEnhancementTable.cpp. Copy contents of that file into
|
||
|
% the source file for the color enhancement function.
|
||
|
|
||
|
clear
|
||
|
close all
|
||
|
|
||
|
|
||
|
% First, define the color enhancement in a normalized domain
|
||
|
|
||
|
% Compander function is defined in three radial zones.
|
||
|
% 1. From 0 to radius r0, the compander function
|
||
|
% is a second-order polynomial intersecting the points (0,0)
|
||
|
% and (r0, r0), and with a slope B in (0,0).
|
||
|
% 2. From r0 to r1, the compander is a third-order polynomial
|
||
|
% intersecting the points (r0, r0) and (r1, r1), and with the
|
||
|
% same slope as the first part in the point (r0, r0) and slope
|
||
|
% equal to 1 in (r1, r1).
|
||
|
% 3. For radii larger than r1, the compander function is the
|
||
|
% unity scale function (no scaling at all).
|
||
|
|
||
|
r0=0.07; % Dead zone radius (must be > 0)
|
||
|
r1=0.6; % Enhancement zone radius (must be > r0 and < 1)
|
||
|
B=0.2; % initial slope of compander function (between 0 and 1)
|
||
|
|
||
|
x0=linspace(0,r0).'; % zone 1
|
||
|
x1=linspace(r0,r1).'; % zone 2
|
||
|
x2=linspace(r1,1).'; % zone 3
|
||
|
|
||
|
A=(1-B)/r0;
|
||
|
f0=A*x0.^2+B*x0; % compander function in zone 1
|
||
|
|
||
|
% equation system for finding second zone parameters
|
||
|
M=[r0^3 r0^2 r0 1;
|
||
|
3*r0^2 2*r0 1 0;
|
||
|
3*r1^2 2*r1 1 0;
|
||
|
r1^3 r1^2 r1 1];
|
||
|
m=[A*r0^2+B*r0; 2*A*r0+B; 1; r1];
|
||
|
% solve equations
|
||
|
theta=M\m;
|
||
|
|
||
|
% compander function in zone 1
|
||
|
f1=[x1.^3 x1.^2 x1 ones(size(x1))]*theta;
|
||
|
|
||
|
x=[x0; x1; x2];
|
||
|
f=[f0; f1; x2];
|
||
|
|
||
|
% plot it
|
||
|
figure(1)
|
||
|
plot(x,f,x,x,':')
|
||
|
xlabel('Normalized radius')
|
||
|
ylabel('Modified radius')
|
||
|
|
||
|
|
||
|
% Now, create the look-up table in the integer color space
|
||
|
[U,V]=meshgrid(0:255, 0:255); % U-V space
|
||
|
U0=U;
|
||
|
V0=V;
|
||
|
|
||
|
% Conversion matrix from normalized YUV to RGB
|
||
|
T=[1 0 1.13983; 1 -0.39465 -0.58060; 1 2.03211 0];
|
||
|
Ylum=0.5;
|
||
|
|
||
|
figure(2)
|
||
|
Z(:,:,1)=Ylum + (U-127)/256*T(1,2) + (V-127)/256*T(1,3);
|
||
|
Z(:,:,2)=Ylum + (U-127)/256*T(2,2) + (V-127)/256*T(2,3);
|
||
|
Z(:,:,3)=Ylum + (U-127)/256*T(3,2) + (V-127)/256*T(3,3);
|
||
|
Z=max(Z,0);
|
||
|
Z=min(Z,1);
|
||
|
subplot(121)
|
||
|
image(Z);
|
||
|
axis square
|
||
|
axis off
|
||
|
set(gcf,'color','k')
|
||
|
|
||
|
R = sqrt((U-127).^2 + (V-127).^2);
|
||
|
Rnorm = R/127;
|
||
|
RnormMod = Rnorm;
|
||
|
RnormMod(RnormMod==0)=1; % avoid division with zero
|
||
|
|
||
|
% find indices to pixels in dead-zone (zone 1)
|
||
|
ix=find(Rnorm<=r0);
|
||
|
scaleMatrix = (A*Rnorm(ix).^2 + B*Rnorm(ix))./RnormMod(ix);
|
||
|
U(ix)=(U(ix)-127).*scaleMatrix+127;
|
||
|
V(ix)=(V(ix)-127).*scaleMatrix+127;
|
||
|
|
||
|
% find indices to pixels in zone 2
|
||
|
ix=find(Rnorm>r0 & Rnorm<=r1);
|
||
|
scaleMatrix = (theta(1)*Rnorm(ix).^3 + theta(2)*Rnorm(ix).^2 + ...
|
||
|
theta(3)*Rnorm(ix) + theta(4)) ./ RnormMod(ix);
|
||
|
U(ix)=(U(ix)-127).*scaleMatrix + 127;
|
||
|
V(ix)=(V(ix)-127).*scaleMatrix + 127;
|
||
|
|
||
|
% round to integer values and saturate
|
||
|
U=round(U);
|
||
|
V=round(V);
|
||
|
U=max(min(U,255),0);
|
||
|
V=max(min(V,255),0);
|
||
|
|
||
|
Z(:,:,1)=Ylum + (U-127)/256*T(1,2) + (V-127)/256*T(1,3);
|
||
|
Z(:,:,2)=Ylum + (U-127)/256*T(2,2) + (V-127)/256*T(2,3);
|
||
|
Z(:,:,3)=Ylum + (U-127)/256*T(3,2) + (V-127)/256*T(3,3);
|
||
|
Z=max(Z,0);
|
||
|
Z=min(Z,1);
|
||
|
subplot(122)
|
||
|
image(Z);
|
||
|
axis square
|
||
|
axis off
|
||
|
|
||
|
figure(3)
|
||
|
subplot(121)
|
||
|
mesh(U-U0)
|
||
|
subplot(122)
|
||
|
mesh(V-V0)
|
||
|
|
||
|
|
||
|
|
||
|
% Last, write to file
|
||
|
% Write only one matrix, since U=V'
|
||
|
|
||
|
fid = fopen('../out/Debug/colorEnhancementTable.h','wt');
|
||
|
if fid==-1
|
||
|
error('Cannot open file colorEnhancementTable.cpp');
|
||
|
end
|
||
|
|
||
|
fprintf(fid,'//colorEnhancementTable.h\n\n');
|
||
|
fprintf(fid,'//Copy the constant table to the appropriate header file.\n\n');
|
||
|
|
||
|
fprintf(fid,'//Table created with Matlab script createTable.m\n\n');
|
||
|
fprintf(fid,'//Usage:\n');
|
||
|
fprintf(fid,'// Umod=colorTable[U][V]\n');
|
||
|
fprintf(fid,'// Vmod=colorTable[V][U]\n');
|
||
|
|
||
|
fprintf(fid,'static unsigned char colorTable[%i][%i] = {\n', size(U,1), size(U,2));
|
||
|
|
||
|
for u=1:size(U,2)
|
||
|
fprintf(fid,' {%i', U(1,u));
|
||
|
for v=2:size(U,1)
|
||
|
fprintf(fid,', %i', U(v,u));
|
||
|
end
|
||
|
fprintf(fid,'}');
|
||
|
if u<size(U,2)
|
||
|
fprintf(fid,',');
|
||
|
end
|
||
|
fprintf(fid,'\n');
|
||
|
end
|
||
|
fprintf(fid,'};\n\n');
|
||
|
fclose(fid);
|
||
|
fprintf('done');
|
||
|
|
||
|
|
||
|
answ=input('Create test vector (takes some time...)? y/n : ','s');
|
||
|
if answ ~= 'y'
|
||
|
return
|
||
|
end
|
||
|
|
||
|
% Also, create test vectors
|
||
|
|
||
|
% Read test file foreman.yuv
|
||
|
fprintf('Reading test file...')
|
||
|
[y,u,v]=readYUV420file('../out/Debug/testFiles/foreman_cif.yuv',352,288);
|
||
|
fprintf(' done\n');
|
||
|
unew=uint8(zeros(size(u)));
|
||
|
vnew=uint8(zeros(size(v)));
|
||
|
|
||
|
% traverse all frames
|
||
|
for k=1:size(y,3)
|
||
|
fprintf('Frame %i\n', k);
|
||
|
for r=1:size(u,1)
|
||
|
for c=1:size(u,2)
|
||
|
unew(r,c,k) = uint8(U(double(v(r,c,k))+1, double(u(r,c,k))+1));
|
||
|
vnew(r,c,k) = uint8(V(double(v(r,c,k))+1, double(u(r,c,k))+1));
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
fprintf('\nWriting modified test file...')
|
||
|
writeYUV420file('../out/Debug/foremanColorEnhanced.yuv',y,unew,vnew);
|
||
|
fprintf(' done\n');
|