Created
February 8, 2015 13:54
-
-
Save OrganicIrradiation/e0759d84106084fea0e5 to your computer and use it in GitHub Desktop.
GoPro SuperView-like adaptive aspect ratio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function [outImage, SAFEZONE] = bSplineResizeWidth(theSize, inImage, SAFEZONE, DEBUG) | |
if nargin < 4 || isempty(DEBUG) | |
DEBUG = 0; % Number of "safe zones" | |
end | |
if nargin < 3 || isempty(SAFEZONE) | |
SAFEZONE = [37.5,62.5]; % Percent of image width | |
end | |
INTERPMETHOD = 'spline'; | |
%% Deal with input and output image sizes | |
oldSize = size(inImage); % Old image size | |
newSize = [size(inImage,1),... % New image size | |
round(theSize(2)/theSize(1)*size(inImage,1))]; | |
fprintf('Input Image Size: %ux%u\n',oldSize(2),oldSize(1)); | |
fprintf('Transitional Image Size: %ux%u\n',newSize(2),newSize(1)); | |
fprintf('Output Image Size: %ux%u\n',theSize(2),theSize(1)); | |
%% Enable interactive selection if DEBUG is greater than 0 | |
if DEBUG > 0 | |
figure(1); clf; | |
imshow(inImage); hold on | |
% With DEBUG greater than 1, we allow for multiple "Safe Zones" | |
for rows = 1:DEBUG | |
[x(rows,1),y] = ginput(1); | |
plot([x(rows,1) x(rows,1)],[1 size(inImage,1)],'r') | |
[x(rows,2),y] = ginput(1); | |
plot([x(rows,2) x(rows,2)],[1 size(inImage,1)],'g') | |
end | |
hold off; | |
SAFEZONE = x/oldSize(2)*100; | |
end | |
%% Create spline remapping function | |
xOld = linspace(1,oldSize(2),newSize(2)); | |
xNew = linspace(1,newSize(2),newSize(2)); | |
xOldOffset = (newSize(2)-oldSize(2))/2; | |
xOld = xOld + xOldOffset; | |
pointsX = xNew(1); | |
pointsY = xOld(1); | |
% Create "Safe Zones" around the regions protected by the user | |
for SNUM = 1:size(SAFEZONE,1) | |
SAFEZONEL = round(SAFEZONE(SNUM,1)/100 * newSize(2)); | |
SAFEZONEH = round(SAFEZONE(SNUM,2)/100 * newSize(2)); | |
diffL = (xNew(SAFEZONEL)-xOld(SAFEZONEL)); | |
diffH = (xNew(SAFEZONEH)-xOld(SAFEZONEH)); | |
theShift = ((diffH+diffL)/2); | |
pointsX = [pointsX,xOld(SAFEZONEL:SAFEZONEH)+theShift]; | |
pointsY = [pointsY,xOld(SAFEZONEL:SAFEZONEH)]; | |
end | |
pointsX = [pointsX,xNew(end)]; | |
pointsY = [pointsY,xOld(end)]; | |
splineF = csape(pointsX,pointsY,'variational'); | |
% Show mapping if DEBUG is not equal to 0 | |
if DEBUG ~= 0 | |
figure(2); clf; | |
plot(xOld-xOldOffset,xOld-xOldOffset,'b', 'LineWidth',1, 'LineSmoothing','on'); hold on | |
plot(xOld-xOldOffset,xNew,'r', 'LineWidth',1, 'LineSmoothing','on'); | |
remapping = fnval(splineF,xNew); | |
plot(remapping-xOldOffset,xNew,'g', 'LineWidth',1, 'LineSmoothing','on'); | |
xlabel('Input') | |
ylabel('Output') | |
title('Input to Output Pixel Mapping') | |
legend('Input Image Mapping','Output Image, Linear Mapping','Output Image, Spline Mapping','Location','SouthEast') | |
end | |
%% Interpolate old pixels to new coordinates | |
newX = fnval(splineF,1:newSize(2),newSize(2))-(newSize(2)-oldSize(2))/2;% New image pixel X coordinates | |
newY = linspace(1,oldSize(1),newSize(1)); % New image pixel Y coordinates | |
oldClass = class(inImage); % Original image type | |
inImage = double(inImage); % Convert image to double precision for interpolation | |
if numel(oldSize) == 2 % Interpolate grayscale image | |
outImage = interp2(inImage,newX,newY(:),INTERPMETHOD); | |
else % Interpolate RGB image | |
outImage = zeros([newSize 3]); % Initialize new image | |
outImage(:,:,1) = interp2(inImage(:,:,1),newX,newY(:),INTERPMETHOD); % Red | |
outImage(:,:,2) = interp2(inImage(:,:,2),newX,newY(:),INTERPMETHOD); % Green | |
outImage(:,:,3) = interp2(inImage(:,:,3),newX,newY(:),INTERPMETHOD); % Blue | |
end | |
inImage = cast(inImage,oldClass); % Convert back to original image type | |
outImage = cast(outImage,oldClass); % Convert back to original image type | |
outImage = imresize(outImage,[theSize(1) theSize(2)]); % Resize to output size | |
if DEBUG > 0 | |
figure(1); clf; | |
subplot(2,1,1); | |
imshow(inImage); | |
subplot(2,1,2); | |
imshow(outImage); | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function [outImage, gradImage, seamImage] = seamCarving(theSize, inImage) | |
addpath('MATLAB_Seam_Carving'); | |
%Remove this for full image seam carving | |
% -------------------- | |
ARin = size(inImage,2)/size(inImage,1); | |
inImage = imresize(inImage,[theSize(1), theSize(1) * ARin]); | |
% -------------------- | |
outImage = double(inImage)/255; | |
newcols = theSize(2); | |
newrows = theSize(1); | |
% Let's just resize the width based upon aspect ratio. Remove this for | |
% full image seam carving | |
% -------------------- | |
newcols = round(size(inImage,1)*theSize(2)/theSize(1)); | |
newrows = size(inImage,1); | |
disp(sprintf('Input Image Size: %ux%u',size(inImage,2),size(inImage,1))); | |
disp(sprintf('Transitional Image Size: %ux%u',newcols,newrows)); | |
disp(sprintf('Output Image Size: %ux%u',theSize(2),theSize(1))); | |
% -------------------- | |
Rcols = size(inImage,2)-newcols; | |
Rrows = size(inImage,1)-newrows; | |
gradImage = findEnergy(outImage); %Finds the gradient image | |
if abs(Rcols)>=size(inImage,2) || abs(Rrows)>=size(inImage,1) | |
disp('Specified dimensions cannot be calculated, minimum image size is 1x1, and maximum is (2xCurrentSize)-1') | |
outImage = inImage; | |
return | |
elseif Rrows==0 && Rcols==0 | |
disp('Specified dimensions are same as original') | |
outImage = inImage; | |
return | |
end | |
if Rcols>0 | |
clear M | |
fprintf('Downsizing image by removing %u vertical seams\n',Rcols) | |
M=removalMap(outImage,Rcols); | |
outImage=SeamCut(outImage,M); | |
gradImage=SeamCut(gradImage,M); | |
seamImage=findSeamImg(gradImage); | |
elseif Rcols<0 | |
clear M | |
fprintf('Increasing image size by adding %u vertical seams\n',-Rcols) | |
M=removalMap(outImage,abs(Rcols)); | |
outImage=SeamPut(outImage,M); | |
gradImage=SeamPut(gradImage,M); | |
seamImage=findSeamImg(gradImage); | |
end | |
if Rrows>0 | |
clear M | |
fprintf('Downsizing image by removing %u horizontal seams\n',Rcols) | |
Y=permute(outImage,[2,1,3]); | |
M=removalMap(Y,Rrows); | |
outImage=permute(SeamCut(Y,M),[2,1,3]); | |
gradImage=SeamCut(gradImage.',M).'; | |
seamImage=findSeamImg(gradImage); | |
elseif Rrows<0 | |
clear M | |
fprintf('Increasing image size by adding %u horizontal seams\n',-Rcols) | |
Y=permute(outImage,[2,1,3]); | |
M=removalMap(Y,abs(Rrows)); | |
outImage=permute(SeamPut(Y,M),[2,1,3]); | |
gradImage=SeamPut(gradImage.',M).'; | |
seamImage=findSeamImg(gradImage); | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment