% Taylor Johnson % Sarah McGee % Robert Ortman % Tianhe Yang % ELEC301 % Project - HDR Image Creation Algorithms % 2006-12-10 %hdriCreating Creates an HDR image %param algorithm: string algorithm to use %param fileNPre: base file name prefix %param fileNSuf: base file name suffix %param startIndx: index to start at %param N: number of input images function [mRed, mGreen, mBlue] = hdriCreating(algorithm, algorithmParam, fileNPre, fileNSuf, startIndx, N) bitrate = algorithmParam(1); %iterate over input images for (i=startIndx:N) %read the ith image: expects filenames like img001.jpg, img002.jpg, img003.jpg, ... strNum = strcat(floor(i/100) + '0', floor(i/10) + '0', mod(i,10) + '0'); [imgData, imgMap] = imread(strcat(fileNPre, strNum, fileNSuf)); [x y z] = size(imgData); reds(:,:,i-startIndx+1) = imgData(:,:,1); greens(:,:,i-startIndx+1) = imgData(:,:,2); blues(:,:,i-startIndx+1) = imgData(:,:,3); end switch lower(algorithm) case {'createaverage'} [imgRed, imgGreen, imgBlue] = createAverage(reds, greens, blues, bitrate); case {'createweighted'} [imgRed, imgGreen, imgBlue] = createWeighted(reds, greens, blues, bitrate); case {'createupsample'} [imgRed, imgGreen, imgBlue] = createRandomUpsample(reds, greens, blues, bitrate); case {'createpiece'} [imgRed, imgGreen, imgBlue] = createPiece(reds, greens, blues, bitrate); otherwise [imgRed, imgGreen, imgBlue] = createAverage(reds, greens, blues, bitrate); end %we'll return the composite matrix at this point mRed = imgRed; mGreen = imgGreen; mBlue = imgBlue; end %createAverage %Divides each images' color data by the total number of images and adds them %together, so each part of each image is given equal weight function [mRed, mGreen, mBlue] = createAverage(reds, greens, blues, bitrate) [x y N] = size(reds); %set up output matrices pixels = x*y; imgRed = double(zeros(x,y)); imgGreen = double(zeros(x,y)); imgBlue = double(zeros(x,y)); %iterate over input images for (i=1:N) %add luminance values from ith image to running total imgRed = imgRed + (double(reds(:,:,i)).*(2^bitrate) ./ (N)); imgGreen = imgGreen + (double(greens(:,:,i)).*(2^bitrate) ./ (N)); imgBlue = imgBlue + (double(blues(:,:,i)).*(2^bitrate) ./ (N)); end %return the result mRed = imgRed; mGreen = imgGreen; mBlue = imgBlue; end %createWeighted %Weights each images' color function [mRed, mGreen, mBlue] = createWeighted(reds, greens, blues, bitrate) [x y N] = size(reds); %set up output matrices pixels = x*y; imgRed = (zeros(x,y)); imgGreen = (zeros(x,y)); imgBlue = (zeros(x,y)); bitrateDefault = 8; %iterate over input images to find average and maximum luminance values for (i=1:N) [logAverage(i,:), lWhite(i,:)] = logAverageLuminance(reds(:,:,i), greens(:,:,i), blues(:,:,i)); end lPercentage = logAverage ./ lWhite; lExponent = abs(lPercentage.^2 - lPercentage); %quadratic with roots at 0,1 compositeLogAverage = sum(logAverage)./N; compositeMaxAverage = sum(lWhite)./N; compositePercentage = compositeLogAverage ./ compositeMaxAverage; thresholdMax = 0.9975; thresholdMin = 0.020; thresholdMiddleMin = 0.275; thresholdMiddleMax = 0.525; boundLower = 0.75; boundUpper = 1.25; excludeRed = 0; excludeGreen = 0; excludeBlue = 0; reds = double(reds); greens = double(greens); blues = double(blues); %iterate over input images for (i=1:N) %check for blownout high-lights if (lPercentage(i,1) >= thresholdMax) %'high-red' excludeRed = excludeRed + 1; reds(:,:,i) = reds(:,:,i) .^ 0.9; end if (lPercentage(i,2) >= thresholdMax) %'high-green' excludeGreen = excludeGreen + 1; greens(:,:,i) = greens(:,:,i) .^ 0.9; end if (lPercentage(i,3) >= thresholdMax) %'high-blue' excludeBlue = excludeBlue + 1; blues(:,:,i) = blues(:,:,i) .^ 0.9; end %check for detailless shadows if (lPercentage(i,1) <= thresholdMin) %'low-red' excludeRed = excludeRed + 1; reds(:,:,i) = reds(:,:,i) .^ 1.1; end if (lPercentage(i,2) <= thresholdMin) %'low-green' excludeGreen = excludeGreen + 1; greens(:,:,i) = greens(:,:,i) .^ 1.1; end if (lPercentage(i,3) <= thresholdMin) %'low-blue' excludeBlue = excludeBlue + 1; blues(:,:,i) = blues(:,:,i) .^ 1.1; end %enhance middle-tones if ((lPercentage(i,1) >= thresholdMiddleMin) && (lPercentage(i,1) <= thresholdMiddleMax)) %'middle-red' reds(:,:,i) = reds(:,:,i) .* 1.1; end if ((lPercentage(i,2) >= thresholdMiddleMin) && (lPercentage(i,2) <= thresholdMiddleMax)) %'middle-green' greens(:,:,i) = greens(:,:,i) .* 1.1; end if ((lPercentage(i,3) >= thresholdMiddleMin) && (lPercentage(i,3) <= thresholdMiddleMax)) %'middle-blue' blues(:,:,i) = blues(:,:,i) .* 1.1; end imgRed = double(imgRed) + ((((double(reds(:,:,i))+(2^bitrateDefault*compositePercentage(1))^(lExponent(i,1)))).*(2^bitrate))+helperRandomIntRange((2^bitrate/2^bitrateDefault)*boundLower, (2^bitrate/bitrateDefault)*boundUpper))./N; imgGreen = double(imgGreen) + ((((double((greens(:,:,i)))+(2^bitrateDefault*compositePercentage(2))^(lExponent(i,2)))).*(2^bitrate))+helperRandomIntRange((2^bitrate/2^bitrateDefault)*boundLower, (2^bitrate/bitrateDefault)*boundUpper))./N; imgBlue = double(imgBlue) + ((((double((blues(:,:,i)))+(2^bitrateDefault*compositePercentage(3))^(lExponent(i,3)))).*(2^bitrate))+helperRandomIntRange((2^bitrate/2^bitrateDefault)*boundLower, (2^bitrate/bitrateDefault)*boundUpper))./N; end %return the result mRed = double(imgRed); mGreen = double(imgGreen); mBlue = double(imgBlue); end %createRandomUpsample function [mRed, mGreen, mBlue] = createRandomUpsample(reds, greens, blues, bitrate) [xn yn N] = size(reds); %set up output matrices pixels = xn*yn; bitrateDefault = 8; %8 bits per channel default for most image types boundLower = 0.75; boundUpper = 1.25; imgRed = (zeros(xn,yn)); imgGreen = (zeros(xn,yn)); imgBlue = (zeros(xn,yn)); %iterate over input images for (i=1:N) %iterate over every pixel imgRed = (imgRed) + ((double(reds(:,:,i)).*(2^bitrate)+helperRandomIntRange((2^bitrate/2^bitrateDefault)*boundLower, (2^bitrate/bitrateDefault)*boundUpper)))./N; imgGreen = (imgGreen) + ((double(greens(:,:,i)).*(2^bitrate)+helperRandomIntRange((2^bitrate/2^bitrateDefault)*boundLower, (2^bitrate/bitrateDefault)*boundUpper)))./N; imgBlue = (imgBlue) + ((double(blues(:,:,i)).*(2^bitrate)+helperRandomIntRange((2^bitrate/2^bitrateDefault)*boundLower, (2^bitrate/bitrateDefault)*boundUpper)))./N; end %return the result mRed = double(imgRed); mGreen = double(imgGreen); mBlue = double(imgBlue); end %createPiece function [mRed, mGreen, mBlue] = createPiece(reds, greens, blues, bitrate) end %logAverageLuminance function [logAverage, Lwhite] = logAverageLuminance(inputRed, inputGreen, inputBlue) matrix = cat(3,double(inputRed),double(inputGreen),double(inputBlue)); for (index=1:1:3) Lw = matrix(:,:,index); [x y] = size(Lw); N = x*y; % number of pixels in matrix delta = 0.00001; % some small values for taking the log of a black pixel sum = 0; % finds the log-average luminance for (n = 1:x) for m = 1:y sum = sum + log(delta + Lw(n,m)); end end logAverage(index) = exp(sum / N); % maximum luminance in scene to map to pure white Lwhite(index) = 0; for (n = 1:x) for (m = 1:y) if (matrix(n,m,index) > Lwhite(index)) Lwhite(index) = matrix(n,m,index); end end end end end % function [rr] = helperRandomIntRange(min, max) rmax = (rand()*(max*(2/3)-1)) + min; rr = round(rmax-min); end