该方法的最终图片由stroke layer 和 tonal texture相乘得到。 原文链接
Stroke Layer
求出图像梯度图
G
, 计算出 response map,
Gradient
imX = [abs(im(:,1:(end-1)) - im(:,2:end)),zeros(H,1)];
imY = [abs(im(1:(end-1),:) - im(2:end,:));zeros(1,W)];
imEdge = imX + imY;
Response Map
kerRef = zeros(ks*2+1); % ks, kernel size
kerRef(ks+1,:) = 1;
response = zeros(H, W, dirNum);
for ii = 0 : (dirNum-1)
ker = imrotate(kerRef, ii*180/dirNum, 'bilinear', 'crop');
response(:,:,ii+1) = conv2(imEdge, ker, 'same');
end
Classification
c = zeros(H, W, dirNum);
for n = 1 : dirNum
c(:,:,n) = imEdge .* (index == n);
end
Line Drawing
kerRef = zeros(ks*2+1);
kerRef(ks+1,:) = 1;
Spn = zeros(H, W, dirNum);
for n = 1 : dirNum
ker = imrotate(kerRef, (n-1)*180/dirNum, 'bilinear', 'crop');
Spn(:,:,n) = conv2(cls(:,:,n), ker, 'same');
end
Sp = sum(Spn, 3);
Sp = (Sp - min(Sp(:))) / (max(Sp(:)) - min(Sp(:)));
S = 1 - Sp;
Tonal Texture
Parameter Learning
作者也给出经验值。
试验中对比了这两种参数的取值,自己获取的值较经验取值的图片渐进原图片。经验值的效果也非常好,为了减少计算,经验值当然可取。
[H, W, sc] = size(I);
im = gaussian_filter(I, 1);
N = H * W;
m = mean2(im);
s = std2(im);
delta_b = sum(sum(abs(im - 1))) / N;
delta_d = s;
mu_a = m - 1.4422 * s;
mu_b = m - 1.4422 * s;
mu_d = m;
Model-based Tone Transfer
histgramTarget = zeros(256, 1);
total = 0;
for ii = 0 : 255
p1 = 1/delta_b * exp(-(255-ii)/delta_b);
if ii < mu_a || ii > mu_b
p2 = 0;
else
p2 = 1 / (mu_b - mu_a);
end
p3 = 1/sqrt(2 * pi * delta_d) * exp(-(ii-mu_d)^2/(2*delta_d^2));
histgramTarget(ii+1, 1) = (omega(2, 1) * p1 + ...
omega(2, 2) * p2 + omega(2, 3) * p3) * 0.01;
total = total + histgramTarget(ii+1, 1);
end
histgramTarget(:, 1) = histgramTarget(:, 1)/total;
J = histeq(I, histgramTarget);
Pencil Texture Rendering
这部分不容易懂,看了很多遍,查找作者主页以及github。下列代码中P为texture。
P = imresize(P, [H, W]);
P = reshape(P, H*W, 1);
logP = log(P);
logP = spdiags(logP, 0, H*W, H*W);
J = imresize(J, [H, W]);
J = reshape(J, H*W, 1);
logJ = log(J);
e = ones(H*W, 1);
Dx = spdiags([-e, e], [0, H], H*W, H*W);
Dy = spdiags([-e, e], [0, 1], H*W, H*W);
A = theta * (Dx * Dx' + Dy * Dy') + (logP)' * logP;
b = (logP)' * logJ;
%% Conjugate gradient
beta = pcg(A, b, 1e-6, 60);
%% Compute the result
beta = reshape(beta, H, W);
P = reshape(P, H, W);
T = P .^ beta;
尾巴
[1]https://github.com/fumin/pencil
[2]https://github.com/candycat1992/PencilDrawing
[3]http://www.cse.cuhk.edu.hk/~leojia/projects/pencilsketch/pencil_drawing.htm
[4]http://www.cnblogs.com/Imageshop/p/4285566.html
注:以上代码在matlab编写。