Skip to main content

Convert images to pencil sketches and extract contour paths for pen plotters and generative art.

Project description

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
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


License

MIT. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

img2sktch-0.1.0.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

img2sktch-0.1.0-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

File details

Details for the file img2sktch-0.1.0.tar.gz.

File metadata

  • Download URL: img2sktch-0.1.0.tar.gz
  • Upload date:
  • Size: 14.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for img2sktch-0.1.0.tar.gz
Algorithm Hash digest
SHA256 195c01ff49aff9a401b2f9846b1b9560ceaaef682cc3e90fd6f11ca4b26b45be
MD5 b31a95aa4a4e4876a1c68eb22541e865
BLAKE2b-256 accaac7b2b66ac93da761c16cf73f9d4f314cda35dc98ff7e95522c61f7401fd

See more details on using hashes here.

File details

Details for the file img2sktch-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: img2sktch-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for img2sktch-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 560efbf1dffb43aabaf2459a2922b316e6bc49c472da1177d08a2cf82ec6509c
MD5 5c92b5d7301f2ae17c594e04fcc4e24c
BLAKE2b-256 3a600384b723f63a0e5d8de72cb4a412ed4572f6f9631075fe1bf3b17c6c8b02

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page