img2sktch
img2sktch is a Python library for converting images to pencil sketches and extracting contour paths. It grew out of a hardware pen plotter project and works equally well for generative art, image preprocessing, and anywhere you want a clean line representation of a photo.
"if a non-stochastic data-less approach can be taken to solving a problem, then machine learning should never be applied."
Installation
pip install img2sktch
For development:
git clone https://github.com/NacreousDawn596/img2sktch
cd img2sktch
pip install -e ".[dev]"
Quick start
import img2sktch as i2s
# Load from file, bytes, PIL, or numpy — all work the same way
frame = i2s.from_file("photo.jpg")
# Apply a pencil sketch
sketch = i2s.PencilSketch(blur_sigma=21)(frame)
# Save
i2s.to_file(sketch, "sketch.png")
Examples
| Original | Pencil | Edge | Hatch |
|---|---|---|---|
Sketch modes
PencilSketch
Classic dodge-blend effect. Works by blurring the inverted grayscale image and blending it back with the original using a color-dodge formula.
from img2sktch import PencilSketch
sketch = PencilSketch(
blur_sigma=21, # gaussian blur strength on the inverted image
sharpen_value=None, # optional int to apply an unsharp kernel after dodge
)(frame)
EdgeSketch
Canny edge detection, inverted so you get black lines on white.
from img2sktch import EdgeSketch
sketch = EdgeSketch(
threshold1=1,
threshold2=81,
blur_ksize=9,
invert=True,
)(frame)
HatchSketch
Hatching lines overlaid on shadow regions, inspired by pen-and-ink illustration.
from img2sktch import HatchSketch
sketch = HatchSketch(
num_directions=4, # number of hatch angles
spacing=6, # pixels between lines
angle_offset=0.0,
blur_sigma=3,
)(frame)
I/O helpers
The library accepts and returns images in whatever format you have them in.
import img2sktch as i2s
from PIL import Image
import io
# From file path
frame = i2s.from_file("photo.jpg")
# From raw bytes (e.g. received over a network or from an upload)
with open("photo.jpg", "rb") as f:
frame = i2s.from_bytes(f.read())
# From a file-like object (BytesIO, requests.Response.raw, etc.)
buf = io.BytesIO(open("photo.jpg", "rb").read())
frame = i2s.from_bytes(buf)
# From a PIL Image
pil_img = Image.open("photo.jpg")
frame = i2s.from_pil(pil_img)
# From a numpy array (grayscale or BGRA are handled automatically)
frame = i2s.from_numpy(some_array)
Saving is symmetric:
# To file
i2s.to_file(sketch, "out.png")
i2s.to_file(sketch, "out.jpg", quality=90)
# To raw bytes (for serving over HTTP, saving to a database, etc.)
raw = i2s.to_bytes(sketch, fmt=".png")
raw = i2s.to_bytes(sketch, fmt=".jpg", quality=85)
# To a BytesIO buffer
buf = i2s.to_bytesio(sketch, fmt=".png") # returns io.BytesIO, cursor at 0
# To a PIL Image
pil = i2s.to_pil(sketch)
Contour extraction
Extract simplified polylines from a sketch image. Useful for pen plotters, laser cutters, or anywhere that needs vector paths rather than raster output.
from img2sktch import PencilSketch, image_to_contours
sketch = PencilSketch()(frame)
contours = image_to_contours(
sketch,
simplification=1.0, # epsilon as % of arc length; 0 = no simplification
canny_threshold1=50,
canny_threshold2=150,
pen_diameter=2.0,
max_width=2000,
multiplier=4.5,
min_area=10.0,
)
# contours is a list of [(x, y), ...] polylines, centered on the origin
Export to SVG
from img2sktch import contours_to_svg
svg = contours_to_svg(contours, width=800, height=800, stroke="black", stroke_width=1.0)
with open("sketch.svg", "w") as f:
f.write(svg)
Export to Arduino (.ino)
Generate ready-to-flash Arduino code for a 3-motor pen plotter:
from img2sktch.contours import contours_to_arduino
code = contours_to_arduino(contours, scale=1.0, offset_x=0, offset_y=0)
with open("drawing.ino", "w") as f:
f.write(code)
Image transforms
from img2sktch.transform import resize, crop_center, pad_to_square, rotate, auto_contrast
# Resize — aspect-ratio preserved if only one dimension given
small = resize(frame, width=800)
small = resize(frame, scale=0.5)
# Crop the center 512x512 pixels
cropped = crop_center(frame, 512, 512)
# Pad to square with white fill
square = pad_to_square(frame, fill=255)
# Rotate 30 degrees, canvas expands to fit
rotated = rotate(frame, angle=30, expand=True, fill=255)
# Stretch contrast to full range
enhanced = auto_contrast(frame)
Command-line interface
A img2sktch command is installed alongside the package.
# Apply a pencil sketch
img2sktch sketch photo.jpg out.png --mode pencil --blur-sigma 21
# Apply edge sketch, resize first
img2sktch sketch photo.jpg out.png --mode edge --width 1024
# Hatch sketch
img2sktch sketch photo.jpg out.png --mode hatch --hatch-directions 4 --hatch-spacing 8
# Extract contours and export as SVG
img2sktch contours photo.jpg sketch.svg --simplification 1.0
# Extract contours and generate Arduino code
img2sktch contours photo.jpg drawing.ino --max-width 2200 --multiplier 6
# Pipe image bytes from stdin
cat photo.jpg | img2sktch sketch - out.png
Project structure
img2sktch/
img2sktch/
__init__.py # public API
sketch.py # PencilSketch, EdgeSketch, HatchSketch
contours.py # image_to_contours, contours_to_svg, contours_to_arduino
transform.py # resize, crop_center, pad_to_square, rotate, auto_contrast
io.py # from_file, from_bytes, from_pil, to_file, to_bytes, to_pil, ...
cli.py # CLI entry point
pyproject.toml
LICENSE
README.md
Dependencies
- opencv-python >= 4.8
- numpy >= 1.24
- Pillow >= 10.0
License
MIT. See LICENSE for details.
Metadata
Release files for img2sktch 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| img2sktch-0.1.0.tar.gz | 14.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| img2sktch-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.7 kB
Release files / img2sktch-0.1.0.tar.gz
| Download URL | img2sktch-0.1.0.tar.gz |
|---|---|
| Size | 14.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
195c01ff49aff9a401b2f9846b1b9560ceaaef682cc3e90fd6f11ca4b26b45be
|
|
BLAKE2b-256 checksum How to use checksums |
accaac7b2b66ac93da761c16cf73f9d4f314cda35dc98ff7e95522c61f7401fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / img2sktch-0.1.0-py3-none-any.whl
| Download URL | img2sktch-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
560efbf1dffb43aabaf2459a2922b316e6bc49c472da1177d08a2cf82ec6509c
|
|
BLAKE2b-256 checksum How to use checksums |
3a600384b723f63a0e5d8de72cb4a412ed4572f6f9631075fe1bf3b17c6c8b02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|