Created
July 21, 2013 05:11
-
-
Save huy10/6047563 to your computer and use it in GitHub Desktop.
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 I_texture=drawObject(base_points,texturesize) | |
% Draw the contour as one closed line white line in an image, and make | |
% the object (hand) white using imfill | |
I_texture=false(texturesize+2); | |
% Loop through all line coordinates | |
x=round([base_points(:,1);base_points(1,1)]); x=min(max(x,1),texturesize(1)); | |
y=round([base_points(:,2);base_points(1,2)]); y=min(max(y,1),texturesize(2)); | |
for i=1:(length(x)-1) | |
% Calculate the pixels needed to construct a line of 1 pixel thickness | |
% between two coordinates. | |
xp=[x(i) x(i+1)]; yp=[y(i) y(i+1)]; | |
dx=abs(xp(2)-xp(1)); dy=abs(yp(2)-yp(1)); | |
if(dx==dy) | |
if(xp(2)>xp(1)), xline=xp(1):xp(2); else xline=xp(1):-1:xp(2); end | |
if(yp(2)>yp(1)), yline=yp(1):yp(2); else yline=yp(1):-1:yp(2); end | |
elseif(dx>dy) | |
if(xp(2)>xp(1)), xline=xp(1):xp(2); else xline=xp(1):-1:xp(2); end | |
yline=linspace(yp(1),yp(2),length(xline)); | |
else | |
if(yp(2)>yp(1)), yline=yp(1):yp(2); else yline=yp(1):-1:yp(2); end | |
xline=linspace(xp(1),xp(2),length(yline)); | |
end | |
% Insert all pixels in the fill image | |
I_texture(round(xline+1)+(round(yline+1)-1)*size(I_texture,1))=1; | |
end | |
I_texture=bwfill(I_texture,1,1); I_texture=~I_texture(2:end-1,2:end-1); | |
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
filename = 'twins'; | |
OUTPUT = 'C:\\Users\\huy\\Desktop\\matlab\\'; | |
TRAIN = 'C:\\Users\\huy\\Desktop\\matlab\\faces\\'; | |
INPUT = 'C:\\Users\\huy\\Desktop\\matlab\\'; | |
% load the training data set (60 faces) | |
load('data60_256.mat'); | |
% read in original image, face and eyes coordinates/sizes data (from OpenCV's | |
% facedetect.cpp output) | |
im = im2double(imread([INPUT filename '.jpg'])); | |
% read in face coords | |
fid = fopen([TRAIN filename '_coords.txt']); | |
C = textscan(fid, '%d %d %d %d'); % each C{i} = [xmin ymin width height] | |
fclose(fid); | |
positions = cell2mat(C); | |
positions(:, 1:2) = positions(:, 1:2) + 1; % match indices | |
if size(positions, 1) < 2 % if not at least 2 faces, then exit | |
'Less than 2 faces found'; | |
return; | |
end | |
% read in eye coords | |
fid = fopen([TRAIN filename '_eyes.txt']); | |
C = textscan(fid, '%d %d %d %d %d %d %d %d'); | |
fclose(fid); | |
eyes = cell2mat(C); | |
eyes(:, 1:2) = eyes(:, 1:2) + 1; | |
% choose largest faces as the ones to swap | |
[index1, index2] = ChooseFaces(positions); | |
index1str = int2str(index1); | |
index2str = int2str(index2); | |
if index1 == index2 % if it is same face, then exit | |
'Chosen faces to swap are the same face'; | |
return; | |
end | |
% read in faces (cropped automatically from OpenCV's facedetect.cpp) | |
face1original = im2double(imread([TRAIN filename '_face_' index1str '.jpg'])); | |
face2original = im2double(imread([TRAIN filename '_face_' index2str '.jpg'])); | |
% resize and normalize for better ASM inputs (determined experimentally) | |
R = 175; C = R; | |
im1 = imresize(face1original, [R C]); | |
im2 = imresize(face2original, [R C]); | |
im1 = NormalizeFaceIntensities(im1, intensities); | |
im2 = NormalizeFaceIntensities(im2, intensities); | |
% initial position offset and rotation, of the initial/mean contour | |
ROTATION = -0.84; | |
tform.offsetr = ROTATION; | |
x = .6*C; | |
y = .5*R; | |
tform.offsetx = -x; tform.offsety = -y; | |
%ASM | |
options.nsearch = [10, 5]; % num of iterations | |
options.ns = [10, 15]; % num of pixels to search in gradient direction | |
options.nscales = 2; | |
[mask1, tf1] = ASM_ApplyModel(im1, tform, ShapeData, AppearanceData, options, 1); | |
[mask2, tf2] = ASM_ApplyModel(im2, tform, ShapeData, AppearanceData, options, 1); | |
% pre-swap-processing, swapping the faces, and additional post-processing | |
[face1original, face2original] = MatchSkinTone(mask1, face1original, mask2, face2original); | |
masks = cell(1, 2); | |
masks{1} = mask1; masks{2} = mask2; | |
ang = ComputeHeadAngle(eyes, [index1, index2], [tf1, tf2], ROTATION); %HU YANG | |
%ang = ComputeHeadAngle(eyes, [index1, index2], [tf1, tf2], masks, ROTATION); | |
[im, rmin1, cmin1] = SwapFaces(im, mask2, mask1, face2original, positions, index1, -ang); | |
[im, rmin2, cmin2] = SwapFaces(im, mask1, mask2, face1original, positions, index2, +ang); | |
im = SmoothEdges(im, positions, [index1, index2], [rmin1, rmin2], [cmin1, cmin2]); | |
imwrite(im, [OUTPUT filename '_output.jpg']); % save modified image | |
imshow(im); | |
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 P = getPyramids(I, numLevels, ptype) | |
% gaussian | |
P = cell(1, numLevels); | |
P{1} = I; | |
for i = 2:numLevels | |
P{i} = impyramid(P{i-1}, 'reduce'); | |
end | |
if strcmp(ptype, 'gauss') | |
return; | |
end | |
% resize | |
for i = numLevels-1:-1:1 | |
s = size(P{i+1})*2-1; | |
P{i} = P{i}(1:s(1),1:s(2),:); | |
end | |
% laplacian | |
for i = 1:numLevels-1 | |
P{i} = P{i} - impyramid(P{i+1}, 'expand'); | |
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 F = Laplacian(A, B, M, ang) | |
[r c] = size(M); | |
A = imresize(A, [r c]); | |
B = imresize(B, [r c]); % original face | |
% pyramids | |
numLevels = 4; | |
LA = getPyramids(A, numLevels, 'laplace'); | |
LB = getPyramids(B, numLevels, 'laplace'); | |
GM = getPyramids(M, numLevels, 'gauss'); | |
% Pout = rot(LA*GM) + LB*(1-rot(GM)) | |
Pout = cell(1, numLevels); | |
for i = 1:numLevels | |
for j = 1:3 | |
mask = imresize(GM{i}, [size(LA{i},1) size(LA{i},2)]); | |
rotmaskedLA = imrotate(LA{i}(:,:,j).*mask, ang, 'nearest', 'crop'); | |
rotmask = imrotate(mask, ang, 'nearest', 'crop'); | |
Pout{i}(:,:,j) = rotmaskedLA + LB{i}(:,:,j).*(1-rotmask); | |
end | |
%figure;imshow(GM{i}); | |
%figure;imshow(LA{i}); | |
end | |
% reconstruct | |
for i = numLevels-1:-1:1 | |
Pout{i} = Pout{i} + impyramid(Pout{i+1}, 'expand'); | |
end | |
F = Pout{1}; | |
F = imresize(F, [r c]); | |
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 x = linspace_multi(d1,d2,n) | |
d1=d1(:); | |
d2=d2(:); | |
x=[repmat(d1,1,n-1)+repmat((0:n-2),length(d1),1).*repmat((d2-d1),1,n-1)/(floor(n)-1) d2]; | |
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
filename = 'twins'; | |
load('data60_256.mat'); | |
OUTPUT = 'C:\\Users\\huy\\Desktop\\matlab\\'; | |
TRAIN = 'C:\\Users\\huy\\Desktop\\matlab\\faces\\'; | |
INPUT = 'C:\\Users\\huy\\Desktop\\matlab\\'; | |
% read | |
im = im2double(imread([INPUT filename '.jpg'])); | |
fid = fopen([TRAIN filename '_coords.txt']); | |
C = textscan(fid, '%d %d %d %d'); % each C{i} = [xmin ymin width height] | |
fclose(fid); | |
positions = cell2mat(C); | |
positions(:, 1:2) = positions(:, 1:2) + 1; | |
%eye | |
fid = fopen([TRAIN filename '_eyes.txt']); | |
C = textscan(fid, '%d %d %d %d %d %d %d %d'); | |
fclose(fid); | |
eyes = cell2mat(C); | |
eyes(:, 1:2) = eyes(:, 1:2) + 1; | |
[index1, index2] = ChooseFaces(positions); | |
index1str = int2str(index1); | |
index2str = int2str(index2); | |
% read in faces | |
face1 = im2double(imread([TRAIN filename '_face_' index1str '.jpg'])); | |
face2 = im2double(imread([TRAIN filename '_face_' index2str '.jpg'])); | |
R = 175; | |
C = R; | |
im1 = imresize(face1, [175 175]); | |
im2 = imresize(face2, [175 175]); | |
im1 = NormalizeIntensities(im1, intensities); | |
im2 = NormalizeIntensities(im2, intensities); | |
ROTATION = -0.84; | |
tform.offsetr = ROTATION; | |
x = 0.6*C; | |
y = 0.5*R; | |
tform.offsetx = -x; | |
tform.offsety = -y; | |
%ASM | |
options.nsearch = [10, 5]; | |
options.ns = [10, 15]; | |
options.nscales = 2; | |
[mask1, tf1] = ASM_ApplyModel(im1, tform, ShapeData, AppearanceData, options, 1); | |
[mask2, tf2] = ASM_ApplyModel(im2, tform, ShapeData, AppearanceData, options, 1); | |
[face1, face2] = ColorTransfer(mask1, face1, mask2, face2); | |
% masks = cell(1, 2); | |
% masks{1} = mask1; | |
% masks{2} = mask2; | |
ang = Angle(eyes, [index1, index2], [tf1, tf2], ROTATION); %HU YANG | |
%ang = ComputeHeadAngle(eyes, [index1, index2], [tf1, tf2], masks, ROTATION); | |
[im, xmin1, ymin1] = SwapFaces(im, mask2, mask1, face2, positions, index1, 0-ang); | |
[im, xmin2, ymin2] = SwapFaces(im, mask1, mask2, face1, positions, index2, 0+ang); | |
im = Smooth(im, positions, [index1, index2], [xmin1, xmin2], [ymin1, ymin2]); | |
imwrite(im, [OUTPUT filename '_final.jpg']); | |
imshow(im); | |
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 im = NormalizeIntensities(im,intensities) | |
mtemp = mean(mean(im)); | |
for color=1:3 | |
im(:,:,color) = im(:,:,color) + intensities(1,1,color) - mtemp(1,1,color); | |
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 im = Smooth(im, positions, indexes, ymins, xmins) | |
BLURSIZE = 5; | |
border = BLURSIZE; | |
for i = 1:2 | |
index = indexes(i); | |
xmin = xmins(i); | |
xmax = xmin+positions(index,3); | |
ymin = ymins(i); | |
ymax = ymin+positions(index,4); | |
blur = ones(BLURSIZE,1)/BLURSIZE; | |
for color = 1:3 | |
if ymin-border-(BLURSIZE-1)/2 > 0 | |
im(ymin-border:ymin+border,xmin:xmax,color) = conv2(im(ymin-border-(BLURSIZE-1)/2:ymin+border+(BLURSIZE-1)/2,xmin:xmax,color),blur,'valid'); | |
end | |
if ymax+border+(BLURSIZE-1)/2 < size(im,1) | |
im(ymax-border:ymax+border,xmin:xmax,color) = conv2(im(ymax-border-(BLURSIZE-1)/2:ymax+border+(BLURSIZE-1)/2,xmin:xmax,color),blur,'valid'); | |
end | |
end | |
blur = ones(1,BLURSIZE)/BLURSIZE; | |
for color = 1:3 | |
if xmin-border-(BLURSIZE-1)/2 > 0 | |
im(ymin:ymax,xmin-border:xmin+border,color) = conv2(im(ymin:ymax,xmin-border-(BLURSIZE-1)/2:xmin+border+(BLURSIZE-1)/2,color),blur,'valid'); | |
end | |
if xmax+border+(BLURSIZE-1)/2 < size(im,2) | |
im(ymin:ymax,xmax-border:xmax+border,color) = conv2(im(ymin:ymax,xmax-border-(BLURSIZE-1)/2:xmax+border+(BLURSIZE-1)/2,color),blur,'valid'); | |
end | |
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 [image,rmin,cmin] = SwapFaces(image, maskIn, maskOut, faceoriginal, positions, indexOut, ang) | |
r = positions(indexOut,2); | |
c = positions(indexOut,1); | |
h = positions(indexOut,4); | |
w = positions(indexOut,3); | |
% maskIn = fliplr(maskIn); | |
% maskOut = fliplr(maskOut); | |
% resize | |
maskIn = imresize(maskIn, [h w]); | |
maskOut = imresize(maskOut, [h w]); | |
rotmask = imrotate(maskIn,ang,'nearest','crop'); | |
[rotR,rotC]=size(rotmask); | |
stats = regionprops(rotmask,'Centroid'); | |
centIn = stats(1).Centroid; | |
stats = regionprops(maskOut,'Centroid'); | |
centOut = stats(1).Centroid; | |
centIn = centIn - size(rotmask)/2; | |
centOut = centOut - size(maskOut)/2; | |
centerrow = r + h/2 + centOut(2) - centIn(2); | |
centercol = c + w/2 + centOut(1) - centIn(1); | |
rmin = round(centerrow - rotR/2); | |
rmax = rmin + rotR - 1; | |
cmin = round(centercol - rotC/2); | |
cmax = cmin + rotC - 1; | |
%imshow(maskIn); | |
%imshow(maskOut); | |
final_face = Laplacian(faceoriginal, image(rmin:rmax,cmin:cmax,:), maskIn, ang); | |
% for color = 1:3 | |
% final_face(:,:,color) = fliplr(final_face(:,:,color)); | |
% end | |
% finish the swap | |
image(rmin:rmax,cmin:cmax,:) = final_face; | |
how to run this project?
@huy10
whould you please say where is data60_256.mat?
OK!
i found data60_256.mat from some where else.
where did you find "data60_256.mat"? @tarannomeghazal
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
where to load data60_256.mat file?