Get Started¶
Install uv¶
SketchKit uses uv to manage Python dependencies and the project environment. Install uv before installing SketchKit.
macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
If curl is not available, you can use wget instead:
wget -qO- https://astral.sh/uv/install.sh | sh
Windows PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
After installation, restart your terminal or reload your shell, then verify that uv is available:
uv --version
Install SketchKit¶
Step 1: Prepare SketchKit Files¶
Extract SketchKit.zip to a folder named SketchKit
Step 2: Open Terminal¶
Navigate to the SketchKit folder in your terminal:
Method 1 (File Manager):
Right-click in the
SketchKitfolder and select “Open in Terminal” or “Open PowerShell here”
Method 2 (Command Line):
cd /path/to/SketchKit
Replace /path/to/SketchKit with the actual path to your SketchKit folder.
Step 3: Install SketchKit¶
Run the following commands in the working directory:
# Install the environment
uv sync
# Activate the environment
source .venv/bin/activate
After installation, you can import sketchkit in your python program.
Step 4: Verify Installation¶
Test your installation:
import sketchkit
from sketchkit.datasets import OpenSketch
print("SketchKit installed successfully!")
Note: Use pip install -e . (with -e) for development installation, which allows you to modify the code and see changes immediately.
Examples¶
Example 1: Dataset Loading and Rendering¶
This example shows how to load a sketch from a dataset and render it into a raster image.
Pipeline¶
Load a sketch dataset.
Get one sketch sample from the dataset.
Render the sketch into a raster image.
Save the rendered result as a PNG file.
Code¶
from sketchkit.datasets import OpenSketch
from sketchkit.renderer import CairoRenderer
if __name__ == "__main__":
# Load a sketch dataset
dataset = OpenSketch(cislab_source=True)
# Get the first sketch from the dataset
sketch = dataset[0]
# Initialize the renderer
renderer = CairoRenderer()
# Render the vector sketch into a raster image
raster_image = renderer.render(sketch)
# Save the rendered result
raster_image.save("rendering.png")
print("Rendered image saved to: rendering.png")
Output¶
After running this script, you should see an output image: rendering.png. This image is the rendered raster version of the loaded sketch.
Example 2: Sketch Vectorization and Stroke Ordering¶
This example shows how to convert a raster sketch into a vector sketch and generate a stroke-by-stroke drawing animation.
Pipeline¶
Load an input raster sketch image.
Convert the raster sketch into a vector sketch.
Estimate a plausible stroke drawing order.
Generate progressive drawing frames.
Save the drawing process as a GIF.
Code¶
import os
import numpy as np
from PIL import Image
from tqdm import tqdm
from sketchkit.ordering import Orderer
from sketchkit.renderer.cairo_renderer import CairoRenderer
from sketchkit.utils.file import save_seq_gif
from sketchkit.vectorization import Vectorizer
if __name__ == "__main__":
# Input raster sketch
img_path = "tests/data/vectorization/butterfly.png"
img_np = np.array(Image.open(img_path).convert("L"))
# Prepare output folders
output_path = "outputs/test"
output_images_path = os.path.join(output_path, "frames")
output_gif_path = os.path.join(output_path, "sketch.gif")
os.makedirs(output_images_path, exist_ok=True)
# Step 1: Vectorize the raster sketch
vectorizer = Vectorizer(method="DeepVecSIG24")
sketch = vectorizer.run(img_np)
# Step 2: Estimate stroke drawing order
orderer = Orderer(method="Fu", device="cpu")
sketch = orderer.run(sketch)
# Step 3: Generate progressive sketch frames
sketch_frames = sketch.get_progressive_frames(length_per_frame=10)
# Step 4: Render each frame
renderer = CairoRenderer()
raster_images = [renderer.render(frame) for frame in tqdm(sketch_frames)]
# Step 5: Save frames as PNG images
for i, raster_image in enumerate(raster_images):
raster_image.save(
os.path.join(output_images_path, f"frame_{i:04d}.png"),
"PNG",
)
# Step 6: Save the drawing process as a GIF
save_seq_gif(raster_images, output_gif_path)
print(f"Drawing animation saved to: {output_gif_path}")
Output¶
After running this script, the generated files will be saved to:
outputs/test/
├── frames/
│ ├── frame_0000.png
│ ├── frame_0001.png
│ └── ...
└── sketch.gif
The file sketch.gif shows the sketch being drawn progressively stroke by stroke.
Example 3: NPR Rendering, Vectorization, and Stylization¶
This example demonstrates a complete pipeline that combines non-photorealistic rendering (NPR), vectorization, and stylization.
Starting from a 3D mesh model, SketchKit first renders sketch-like images from multiple camera viewpoints using an NPR renderer. Then, one rendered raster sketch is converted into a vector sketch. Finally, the vector sketch is stylized into an artistic output image.
Pipeline¶
Render sketch-like images from a 3D object using the NPR renderer.
Save the rendered sequence as a GIF.
Convert one rendered raster sketch into a vector sketch.
Export the vector sketch as an SVG file.
Stylize the vector sketch into a final raster image.
Code¶
import math
import os
import numpy as np
from sketchkit.core.camera import Camera
from sketchkit.renderer.npr_renderer import NPRRenderer, NPRRenderOptions
from sketchkit.stylization import Stylizer
from sketchkit.utils.file import save_seq_gif
from sketchkit.vectorization import Vectorizer
if __name__ == "__main__":
output_path = "outputs/test"
os.makedirs(output_path, exist_ok=True)
# Initialize the NPR renderer with a 3D mesh
renderer = NPRRenderer(obj_path="tests/data/rendering/head.obj")
# Create a set of cameras rotating around the object
cameras = []
radius = 2.5
for angle in range(0, 360, 30):
rad = math.radians(angle)
camera = Camera()
camera.set_look_at([0, 0, 0])
camera.set_xyz([radius * math.cos(rad), radius * math.sin(rad), 0])
cameras.append(camera)
print(f"Starting render for {len(cameras)} cameras...")
# Render sketch-like images using the Suggestive Contour method
print("Rendering with SuggestiveContour method...")
options = NPRRenderOptions(method="SuggestiveContour", threshold=0.005)
images = renderer._render(cameras, options)
# Save the rendering sequence as a GIF
gif_path = os.path.join(output_path, "SuggestiveContour.gif")
save_seq_gif(images, gif_path)
# Save the first rendered image as a raster sketch
raster_sketch_path = os.path.join(output_path, "raster_sketch.png")
images[0].save(raster_sketch_path)
# Convert the raster sketch to a grayscale numpy array
img_gray = images[0].convert("L")
img_array = np.array(img_gray)
# Vectorize the raster sketch
vectorizer = Vectorizer(method="LineDrawer")
sketch = vectorizer.run(img_array)
# Export the vector sketch as an SVG file
vector_sketch_path = os.path.join(output_path, "vector_sketch.svg")
sketch.to_svg(filename=vector_sketch_path)
# Stylize the vector sketch
stylizer = Stylizer(
method="NeuralBrushstroke",
model_name="style2",
style_id="playdoh10",
)
stylized_output_path = os.path.join(output_path, "stylized_sketch.png")
stylized_image = stylizer.run(
sketch,
output_path=stylized_output_path,
canvas_size=512,
)
print(f"Rendering GIF saved to: {gif_path}")
print(f"Raster sketch saved to: {raster_sketch_path}")
print(f"Vector sketch saved to: {vector_sketch_path}")
print(f"Stylized image saved to: {stylized_output_path}")
Output¶
After running this example, the generated files will be saved to:
outputs/test/
├── SuggestiveContour.gif
├── raster_sketch.png
├── vector_sketch.svg
└── stylized_sketch.png