Skip to content

Instantly share code, notes, and snippets.

@OrganicIrradiation
Created February 8, 2015 13:54
Show Gist options
  • Save OrganicIrradiation/e0759d84106084fea0e5 to your computer and use it in GitHub Desktop.
Save OrganicIrradiation/e0759d84106084fea0e5 to your computer and use it in GitHub Desktop.
GoPro SuperView-like adaptive aspect ratio
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
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&lt;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&lt;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