Repository: candycat1992/PencilDrawing
Branch: master
Commit: bca965d1c92a
Files: 6
Total size: 8.2 KB
Directory structure:
gitextract__zisyvfe/
├── GenPencil.m
├── GenStroke.m
├── GenToneMap.m
├── PencilDrawing.m
├── README.md
└── demo.m
================================================
FILE CONTENTS
================================================
================================================
FILE: GenPencil.m
================================================
function T = GenPencil(im, P, J)
% ==============================================
% Compute the pencil map 'T'
%
% Paras:
% @im : input image ranging value from 0 to 1.
% @P : the pencil texture.
% @J : the tone map.
%
%% Parameters
theta = 0.2;
[H, W, ~] = size(im);
%% Initialization
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);
%% Compute matrix A and b
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;
end
================================================
FILE: GenStroke.m
================================================
function S = GenStroke(im, ks, width, dirNum)
% ==============================================
% Compute the stroke structure 'S'
%
% Paras:
% @im : input image ranging value from 0 to 1.
% @ks : kernel size.
% @width : width of the strocke
% @dirNum : number of directions.
%
%% Initialization
[H, W, ~] = size(im);
%% Smoothing
im = medfilt2(im, [3 3]);
%% Image 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;
%% Convolution kernel with horizontal direction
kerRef = zeros(ks*2+1);
kerRef(ks+1,:) = 1;
%% Classification
response = zeros(H,W,dirNum);
for n = 1 : dirNum
ker = imrotate(kerRef, (n-1)*180/dirNum, 'bilinear', 'crop');
response(:,:,n) = conv2(imEdge, ker, 'same');
end
[~, index] = max(response,[], 3);
%% Create the stroke
C = zeros(H, W, dirNum);
for n = 1 : dirNum
C(:,:,n) = imEdge .* (index == n);
end
kerRef = zeros(ks*2+1);
kerRef(ks+1,:) = 1;
for n = 1 : width
if (ks+1-n) > 0
kerRef(ks+1-n,:) = 1;
end
if (ks+1+n) < (ks*2+1)
kerRef(ks+1+n,:) = 1;
end
end
Spn = zeros(H, W, dirNum);
for n = 1 : dirNum
ker = imrotate(kerRef, (n-1)*180/dirNum, 'bilinear', 'crop');
Spn(:,:,n) = conv2(C(:,:,n), ker, 'same');
end
Sp = sum(Spn, 3);
Sp = (Sp - min(Sp(:))) / (max(Sp(:)) - min(Sp(:)));
S = 1 - Sp;
end
================================================
FILE: GenToneMap.m
================================================
function J = GenToneMap(im)
% ==============================================
% Compute the tone map 'T'
%
% Paras:
% @im : input image ranging value from 0 to 1.
%
%% Parameters
Ub = 225;
Ua = 105;
Mud = 90;
DeltaB = 9;
DeltaD = 11;
% groups from dark to light
% 1st group
Omega1 = 42;
Omega2 = 29;
Omega3 = 29;
% 2nd group
Omega1 = 52;
Omega2 = 37;
Omega3 = 11;
% 3rd group
Omega1 = 76;
Omega2 = 22;
Omega3 = 2;
%% Compute the target histgram
histgramTarget = zeros(256, 1);
total = 0;
for ii = 0 : 255
if ii < Ua || ii > Ub
p = 0;
else
p = 1 / (Ub - Ua);
end
histgramTarget(ii+1, 1) = (...
Omega1 * 1/DeltaB * exp(-(255-ii)/DeltaB) + ...
Omega2 * p + ...
Omega3 * 1/sqrt(2 * pi * DeltaD) * exp(-(ii-Mud)^2/(2*DeltaD^2))) * 0.01;
total = total + histgramTarget(ii+1, 1);
end
histgramTarget(:, 1) = histgramTarget(:, 1)/total;
% %% Smoothing
% im = medfilt2(im, [5 5]);
%% Histgram matching
J = histeq(im, histgramTarget);
%% Smoothing
G = fspecial('average', 10);
J = imfilter(J, G,'same');
end
================================================
FILE: PencilDrawing.m
================================================
function I = PencilDrawing(im, ks, width, dirNum, gammaS, gammaI)
% ==============================================
% Generate the pencil drawing I based on the method described in
% "Combining Sketch and Tone for Pencil Drawing Production" Cewu Lu, Li Xu, Jiaya Jia
% International Symposium on Non-Photorealistic Animation and Rendering (NPAR 2012), June, 2012
%
% Paras:
% @im : the input image.
% @ks : the length of convolution line.
% @width : the width of the stroke.
% @dirNum : the number of directions.
% @gammaS : the darkness of the stroke.
% @gammaI : the darkness of the resulted image.
%
%% Read the image
im = im2double(im);
[H, W, sc] = size(im);
%% Convert from rgb to yuv when nessesary
if (sc == 3)
yuvIm = rgb2ycbcr(im);
lumIm = yuvIm(:,:,1);
else
lumIm = im;
end
%% Generate the stroke map
S = GenStroke(lumIm, ks, width, dirNum) .^ gammaS; % darken the result by gamma
% figure, imshow(S)
%% Generate the tone map
J = GenToneMap(lumIm) .^ gammaI; % darken the result by gamma
% figure, imshow(J)
%% Read the pencil texture
P = im2double(imread('pencils/pencil0.jpg'));
P = rgb2gray(P);
%% Generate the pencil map
T = GenPencil(lumIm, P, J);
% figure, imshow(T)
%% Compute the result
lumIm = S .* T;
if (sc == 3)
yuvIm(:,:,1) = lumIm;
% resultIm = lumIm;
I = ycbcr2rgb(yuvIm);
else
I = lumIm;
end
end
================================================
FILE: README.md
================================================
# Introduction
Implement the algorithm presented in [1]. You can use the code like below to get a pencil drawing production:
```C++
I = PencilDrawing(im, ks, width, dirNum, gammaS, gammaI);
```
See demo.m for example.
# Parameters
I added some more parameters for better control of the final image.
* **width**
Control the width of the strokes. See Figure 1 for example.
 
**Figure 1**: Width of the strokes. left: width = 0; right: width = 2.
* **gammaS**
Control the darkness of the strokes. See Figure 2 for example.
 
**Figure 2**: Gamma of the strokes. left: gammaS = 1.0; right: gammaS = 2.0.
* **gammaI**
Control the darkness of the final image. See Figure 3 for example.
 
**Figure 3**: Gamma of the final image. left: gammaI = 1.0; right: gammaI = 0.4.
## Tone Transfer Weights
The paper presented three groups of weights for tone map generation.
1. 
2. 
3. 
These weights will determine the histogram of the tone map. I use the third group by default, which makes the final image lighter. You can change to other groups in GenToneMap.m.
# Folder Organization
* **inputs**
Include some test images from <a href="http://www.cse.cuhk.edu.hk/leojia/projects/pencilsketch/pencil_drawing.htm" target="_blank">the website </a> of the publishers and other images.
* **pencils**
Include 5 pencil textures for demonstration. I use “pencils/pencil0.jpg” by default. You can change it in PencilDrawing.m.
* **results**
Include the results generated by my code. Each image may use different parameters.
* **resultsFromPaper**
Include the results of the paper for comparison. I grabbed them in <a href="http://www.cse.cuhk.edu.hk/leojia/projects/pencilsketch/pencil_drawing.htm" target="_blank">their website</a>.
# Reference
[1] Lu C, Xu L, Jia J. Combining sketch and tone for pencil drawing production[C]//Proceedings of the Symposium on Non-Photorealistic Animation and Rendering. Eurographics Association, 2012: 65-73.
================================================
FILE: demo.m
================================================
im = imread('inputs/15--298.jpg');
I = PencilDrawing(im, 8, 1, 8, 1.0, 1.0);
figure, imshow(I)
gitextract__zisyvfe/ ├── GenPencil.m ├── GenStroke.m ├── GenToneMap.m ├── PencilDrawing.m ├── README.md └── demo.m
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9K chars).
[
{
"path": "GenPencil.m",
"chars": 956,
"preview": "function T = GenPencil(im, P, J)\n% ==============================================\n% Compute the pencil map 'T'\n% \n% "
},
{
"path": "GenStroke.m",
"chars": 1653,
"preview": "function S = GenStroke(im, ks, width, dirNum)\r\n% ==============================================\r\n% Compute the stroke "
},
{
"path": "GenToneMap.m",
"chars": 1292,
"preview": "function J = GenToneMap(im)\n% ==============================================\n% Compute the tone map 'T'\n% \n% Paras:"
},
{
"path": "PencilDrawing.m",
"chars": 1588,
"preview": "function I = PencilDrawing(im, ks, width, dirNum, gammaS, gammaI)\r\n% ==============================================\r\n% "
},
{
"path": "README.md",
"chars": 2849,
"preview": "\n# Introduction\n\nImplement the algorithm presented in [1]. You can use the code like below to get a pencil drawing produ"
},
{
"path": "demo.m",
"chars": 97,
"preview": "\nim = imread('inputs/15--298.jpg');\n\nI = PencilDrawing(im, 8, 1, 8, 1.0, 1.0);\n\nfigure, imshow(I)"
}
]
About this extraction
This page contains the full source code of the candycat1992/PencilDrawing GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 6 files (8.2 KB), approximately 2.8k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.