Choose a photo. For
instance a beautiful photo like this:
We are going to apply
very simple
convolution filters to transform it into something
that recalls a
pencil line drawing effect. The point here is the
simplicity, of course
you can do it better with your favorite image
retouching software.
The filters are applied with a simple matlab code include below but the computations can be imitated using free software. For fast performance a possibility is to write some C/C++ code with the open source FreeImage library. First of all, we convert the photo into a B/W image ( imag
= rgb2gray(imag) ).
A finite 2D convolution filter can be considered as a
matrix. The key
to simulate a pencil drawing is to detect the edges of
the image. Our
first choice is the horizontal-vertical filter:HV=[0, 1, 0; 1, -4, 1;
0, 1, 0]
For an "interior
pixel"
the value (the gray level) of a point is more or less
the average of
the values of the horizontal and vertical
neighbors. Then the
filter gives 0 (that we represent as white in the
following images).
For a sharp edge this valence is lost and we should
see something. The
pixel values are clamped to [0,255] in matlab, then
beyond certain
value we always see black corresponding to 255 in the
following images
(if you are wondering this switching with respect to
the usual
convention, is done by
imagf = 255-imagf ).
The result is not very appealing:What is wrong? Perhaps
the point is that we have to consider also diagonal
(oblique)
directions for the average. Then our next filter is:
Ob=[1, 1, 1; 1, -8, 1;
1, 1, 1]
The zero average
assures
that interior pixels are disregarded. The result
improves a little but
the result seems not dense and a little random.
The explanation is
that
the previous filters detect variations in a range of 3
pixels and this
is really tiny in a usual computer monitor, less than
a millimeter.
This suggests working with double sized blocks.
Consider
HV'= [O, I, O; , -4I,
I; O, I, O] with O=[0, 0; 0, 0] and I=[1, 1; 1, 1]
The result with this 6x6 matrix improves considerably:Ob'=[I, I, I; I, -8I,
I; I, I, I]
to get:imshow( imagf,
[0,240]) ) looks great: |
This is the matlab code that generates the images:
|