Painterly Rendering with
Curved Brush Strokes of
Multiple Sizes
Aaron Hertzman, NYU
Presented by: Shreeganesh Ramanan
Introduction
• Painterly Rendering is a method of reproducing artistic style and expression of a painting using a source image and/or 3D models
• An Image Space Technique
• A few steps beyond what
Photoshop TM offers.
A Sampler
A Sampler
Things to discuss
• “curved brush strokes of multiple sizes”
• Implementation details(as little as possible )
• Various parameters and what they can do
So you want to be an artist ?
• Do you have lot of time ?
• A huge smattering of skill ?
• That elusive thing called talent
• And some canvas, paints, a subject, and a dirty rag you call work clothes
Or we can turn to NPR
Previous Work…
• One brush size only
• No multiple passes to refine style
• Support for one style only
• Image looks “flattened”
Previous Work..
• But details need different sized strokes
CBS of MS improves quality
Advantages
• Faster than painting
– Can be used for interactive rendering
• Multiple brush sizes allow for varying detail and continuous color regions
• Multipass method similar to how artist paint
• Different parameters create different styles
Main Loop function paint (sourceImage, R
1
{
… R n
) canvas := a new constant color image
// paint the canvas for each brush radius R i
, from largest to smallest do
{
// apply Gaussian blur referenceImage = sourceImage * G(f
σ
R i
)
}
// paint a layer paintLayer(canvas, referenceImage, Ri)
} return canvas
Painting a Layer function paintLayer(canvas, referenceImage, R) {
S := a new set of strokes, initially empty
D := difference(canvas, referenceImage) grid := f g
R for x=0 to imageWidth stepsize grid do { for y=0 to imageHeight stepsize grid do {
M := the region(x-grid/2…x+grid/2, y-grid/2…y+grid/2) areaError := sumOfError(M, D) / grid 2 if (areaError > T) then {
(x
1
, y
1
) := maxPoint(areaError) stroke := makeStroke(R, x
1
, y
1
, referenceImage) add stroke to S
}
} } paint all strokes S on canvas – random order
}
Curved Brush Strokes
• Anti-aliased cubic B-Splines
• Each stroke models the color gradient of reference image
• Representation
– Control Points
– Color
– Size of brush
Spline Stroke Algorithm function makeSplineStroke(x
0
, y
0
, R, refImage) { strokeColor = refImage.color(x
0
, y
0
)
K := new stroke, radius R, color strokeColor add point (x
0
, y
0
) to K
(x, y) := (x
0
, y
0
)
(lastDx, lastDy) := (0, 0) for i=1 to maxStrokeLength do { if (i > minStrokeLength and (|refImage.color(x,y) – canvas.color(x,y)| < |refImage.color(x,y)strokeColor)) then return K if (refImage.gradientMag(x,y) ==0) then return K
(gx, gy) := refImage.gradientDirection(x, y)
(dx, dy) := (-gy, gx) if (lastDx * dx + lastDy * dy < 0) then
(dx, dy) = (-dx, -dy)
(dx, dy) := f c
* (dx,dy) + (1-f c
) * (lastDx,lastDy)
(dx, dy) := (dx,dy)/(dx2 + dy2)1/2
(x, y) := (x + R*dx, y + R*dy)
(lastDx, lastDy) := (dx, dy) add the point (x, y) to K
} return K }
Calculating Control Points
G
2
D
(x
2
1
, y
2
)
(x
1
, y
D
1
)
0
θ
1
G
1
(x
0
, y
0
)
θ
0
G
0
Parameters of Style
• Approximation Threshold ( T )
• Brush Sizes – Smallest ( R i
), Number ( n ) ,
Size Ratio ( R i
-1 / R i
)
• Curvature Filter ( f c
)
• Blur Factor ( f
σ
)
• Min and max stroke lengths ( minLength , maxLength )
• Opacity (
α
)
• Grid size ( f g
)
• Color Jitter ( j h
, j s
, j v
, j r
, j g
, j b
)
Experiments in Style
Source Image
Experiments in Style
Impressionist
Experiments in Style
Expressionist
Experiments in Style
Colorist Wash
Experiments in Style
Pointillist