Skip to content

Instantly share code, notes, and snippets.

@rads
Created February 26, 2010 23:40
Show Gist options
  • Save rads/316317 to your computer and use it in GitHub Desktop.
Save rads/316317 to your computer and use it in GitHub Desktop.
function out = hw3_again(in, tileSize, n, overlap, errorTolerance)
in = double(in);
% Convert to RGB if greyscale.
if (size(in,3) == 1)
in = repmat(in, [1 1 3]);
end
% Initialize default values.
if nargin < 4
overlap = round(tileSize / 6);
end
if nargin < 5
errorTolerance = 0.1;
end
destSize = n * tileSize - (n-1) * overlap;
out = zeros(destSize, destSize, 3);
% Pick a random seed tile.
randY = round(rand*(size(in,1)-tileSize));
randX = round(rand*(size(in,2)-tileSize));
out(1:tileSize, 1:tileSize, 1:3) = in(randY:randY+tileSize-1, randX:randX+tileSize-1, 1:3);
firstRun = 1;
for y = 1:n
% Since matrices start at 1, not 0, we add 1.
startY = (y-1)*tileSize - (y-1)*overlap + 1;
endY = startY+tileSize-1;
overlapY = startY+overlap-1;
for x = 1:n
if (firstRun)
firstRun = 0;
continue;
end
startX = (x-1)*tileSize - (x-1)*overlap + 1;
endX = startX+tileSize-1;
overlapX = startX+overlap-1;
% Create a matrix that will contain each SSD starting at the top left
% point.
ssdHeight = size(in,1)-tileSize;
ssdWidth = size(in,2)-tileSize;
ssdMatrix = zeros(ssdHeight, ssdWidth, 3);
% If x > 1, it's not a left edge and there is an overlap.
if x > 1
leftOverlap = out(startY:endY, startX:overlapX, 1:3);
for b = 1:ssdHeight
for a = 1:ssdWidth
current = in(b:b+tileSize-1, a:a+overlap-1, 1:3);
ssdMatrix(b, a, 1:3) = ssdMatrix(b, a, 1:3) + sum(sum((current - leftOverlap) .^ 2));
end
end
end
% If y > 1, it's not a top edge and there is an overlap.
if y > 1
topOverlap = out(startY:overlapY, startX:endX, 1:3);
for b = 1:ssdHeight
for a = 1:ssdWidth
current = in(b:b+overlap-1, a:a+tileSize-1, 1:3);
ssdMatrix(b, a, 1:3) = ssdMatrix(b, a, 1:3) + sum(sum((current - topOverlap) .^ 2));
end
end
end
% Pick a random eligible tile.
lowest = min(ssdMatrix(:));
valid = find(ssdMatrix <= (lowest*(errorTolerance+1)));
choice = valid(ceil(rand*length(valid)));
[r,c,unused] = ind2sub(size(ssdMatrix), choice);
newTile = in(r:r+tileSize-1, c:c+tileSize-1, 1:3);
% Min-cut
if x > 1
b1 = out(startY:endY, startX:overlapX, 1:3);
b2 = newTile(:,1:overlap,1:3);
e = (b2-b1) .^ 2;
ePaths = zeros(size(e,1), size(e,2), 3);
ePaths(1,:,1:3) = e(1,:,1:3);
for i = 2:size(e,1)
for j = 1:size(e,2)
minList = [ePaths(i-1,j,1:3)];
if j > 1
minList = [minList ePaths(i-1,j-1,1:3)];
end
if j < size(e,2)
minList = [minList ePaths(i-1,j+1,1:3)];
end
lowest = min(minList(:));
ePaths(i,j,1:3) = e(i,j,1:3) + lowest;
end
end
cutpath = zeros(size(e,1), size(e,2), 3);
idx = 1;
minList = ePaths(size(e,1),:,1:3);
currentMin = minList(:,1,1:3);
for j = 1:length(minList)
if minList(1,j,1:3) < currentMin
currentMin = minList(1,j,1:3);
idx = j;
end
end
cutpath(size(e,1), idx, 1:3) = 1;
for i = 2:size(e,1)
newIdx = idx;
currentMin = ePaths(size(e,1)-i+1,idx,1:3);
if idx > 1
left = ePaths(size(e,1)-i+1,idx-1,1:3);
if left < currentMin
currentMin = left;
newIdx = idx-1;
end
end
if idx < size(e,2)
right = ePaths(size(e,1)-i+1,idx+1,1:3);
if right < currentMin
currentMin = right;
newIdx = idx+1;
end
end
idx = newIdx;
cutpath(size(e,1)-i+1,idx,1:3) = 1;
end
for i = 1:size(cutpath,1)
left = 1;
count = 1;
for j = 1:size(cutpath,2)
if cutpath(i,j,1:3) == 1
left = 0;
end
if left
count = count + 1;
end
end
out(startY+i-1, startX+count-1:endX, 1:3) = newTile(i, count:end, 1:3);
image(uint8(out));
axis off;
axis image;
drawnow;
end
end
out(startY:endY, startX:endX, 1:3) = in(r:r+tileSize-1, c:c+tileSize-1, 1:3);
%
% image(uint8(e));
% axis off;
% axis image;
% drawnow;
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment