Images from Code
A picture you load in Python can be changed in code: cut out its subject, resize it, crop, rotate, trace it into vector shapes, read what is in it. Each change gives you a new picture in memory, ready to draw, to show in a Pymations scene, or to save beside your .py file.
img = load_image("shoe.jpg") # a picture beside this .py
cut = await img.remove_background() # the shoe, background transparent
small = await cut.resize(width=800) # one step after another
await small.save("shoe cutout.png") # optional: write it beside the .py
How it works
load_image("name.png")loads a picture from the folder your.pyis saved in (or a web address). You can draw it straight away, as before:ctx.drawImage(img, 0, 0), orSprite(img).- Every method is awaited:
await img.resize(width=800). Put the code at the top level of the file, or inside anasync def(in Pymations,async def construct(self)). - A method never changes the picture you called it on. It returns a new one, so you can keep both, or chain:
await (await img.remove_background()).resize(width=800). - The work happens in the app, not in Python, so even big photos stay quick and nothing is copied into your program.
- Results are remembered. Running the file again, or recording a video of it, reuses the results instead of redoing the work, as long as the picture file and the settings are the same.
- Nothing is written to disk unless you call
save().
Remove a background
product = load_image("bottle.jpg")
cutout = await product.remove_background()
ctx.drawImage(cutout, 100, 80)
remove_background() finds the main subject (a product, a person, a pet) and makes everything else transparent. It uses Apple's own on-device subject lifting, so it needs the Circuitry app on a Mac, iPhone or iPad, or a browser connected to Circuit running on a Mac. Anywhere else the line stops with: remove_background() needs an Apple device. On iPhone and iPad it needs a real device; it does not run in the iOS Simulator.
Resize a picture
hero = await img.resize(width=1280) # height follows the shape
thumb = await img.resize(percent=25)
square = await img.resize(width=1080, height=1080) # whole picture, centred
cover = await img.resize(width=1080, height=1080, fit="cover") # fill the square, trim the edges
Give width, height or percent. With both width and height, fit says how the picture fills the box: "contain" (the default: the whole picture, with clear margins), "cover" (fills the box and trims the edges) or "stretch". Big reductions are made in halves before the final size, so detail and text stay sharp. Transparency is kept.
Trace a picture into shapes
logo = load_image("logo.png")
vec = await logo.trace(colors=6, detail="medium")
await vec.save("logo.svg")
trace() turns a picture into flat-colour vector shapes, the same tracing 2Vec uses. colors is how many colours to keep; detail is "low" (smoother, fewer points), "medium" or "high". A logo or an illustration with clear areas of colour traces best; a photo becomes a poster-like picture. The result is a Vector: vec.svg is its SVG text, vec.shapes how many shapes it has.
In Pymations
from pymations import *
class Product(Scene):
async def construct(self):
shoe = await load_image("shoe.jpg").remove_background()
self.play(FadeIn(ImageMobject(shoe).scale(0.8)))
vec = await load_image("logo.png").trace(colors=5)
logo = SVGMobject(vec) # or vec.to_mobject()
self.play(DrawBorderThenFill(logo))
ImageMobject(picture)shows any picture, loaded or changed.SVGMobject(vec)(orvec.to_mobject()) turns a traced picture into one shape per traced region, each with its own colour, so animations that draw outlines and fill shapes work on it.- In an ordinary
def construct(self)(noawait), give the changes to the object itself and the scene waits for them:ImageMobject("shoe.jpg", remove_background=True, resize=800),ImageMobject("photo.jpg", ops=[("crop", {"x": 0, "y": 0, "width": 600, "height": 400}), ("sepia",)]), orSVGMobject("logo.png", trace={"colors": 5, "detail": "medium"})for traced shapes.remove_backgroundruns first, thenops, thenresize(a number is a width).
Data from a picture
Some methods read a picture instead of changing it, and return Python data. classify, find_faces, read_codes and photo_details run in the iPhone and iPad app; find_contours and detect_shapes run everywhere.
info = await img.classify()
for item in info.labels: # e.g. {"label": "shoe", "confidence": 0.93}
print(item["label"], item["confidence"])
codes = await img.read_codes(overlay=False)
for code in codes.codes: # each has "symbology" and "payload"
print(code["payload"])
Methods that can draw what they found (find_faces, read_codes, find_contours, detect_shapes) return {"found": ..., "overlay": picture} when overlay=True (their default), so you can show the finds; pass overlay=False for the data alone.
Saving
await pic.save("name.png") writes beside your .py (.png, .jpg or .webp; the format follows the name) and returns the path. It replaces a file of that name. A traced Vector saves as .svg. favicon_set() and app_icon_set() make a set of files: await icons.save("icons") writes them into a folder. Save the .py first: saving uses the folder it is in.
What this device can run
print(await img.available()) # the method names this device can run
Most methods run everywhere. Apple's effects need an Apple device (the Mac app, iPhone or iPad, or Circuit on a Mac), and a few photo tools run only in the iPhone and iPad app. Calling one where it cannot run stops with a message that says where it does.
Every method
Every picture has these methods. Each is awaited (await img.resize(width=800)); keywords you leave out take the default shown. await img.run("name", **keywords) runs any of them by name.
| Method | What it does | Gives | Runs on |
|---|---|---|---|
remove_background() | Cut out the main subject; everything else becomes transparent. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
resize(width=None, height=None, percent=None, fit="contain") | Scale it. Give width, height (the other follows the shape) or percent. width: px; height: px; percent: e.g. 50 for half size; fit: with both width and height: "contain" (whole picture), "cover" (fill and crop) or "stretch". | a new picture | every device |
enhance() | Improve exposure, colour and contrast automatically. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
sepia(intensity=0.8) | Warm brown old-photo tone. intensity: 0 to 1. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
mono() | Black and white. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
noir() | High-contrast black and white. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
vintage() | Faded, warm film look. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
blur(radius=10) | Soften the whole picture. radius: how far to blur, px. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
sharpen(radius=2.5, intensity=0.5) | Crisper edges. radius: px; intensity: 0 to 1. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
vibrance(amount=1) | Richer colours, gently. amount: -1 to 1. | a new picture | Apple devices (Mac app, iPhone, iPad, or Circuit on a Mac) |
rotate(angle=90, background="#00000000") | Rotate by 90/180/270 or any arbitrary angle. angle: degrees, clockwise; background: colour for the corners a turn uncovers. | a new picture | every device |
flip(axis="horizontal") | Mirror horizontally, vertically, or both. axis: "horizontal", "vertical" or "both". | a new picture | every device |
crop(x=0, y=0, width=256, height=256) | Cut a rectangular region from an image. x: left edge, px; y: top edge, px; width: px; height: px. | a new picture | every device |
convert(format="webp", quality=0.9) | Re-encode as PNG / JPG / WebP / AVIF / HEIC. format: "png", "jpg", "webp", "avif" or "heic"; quality: 0 to 1, for lossy formats. | a new picture | every device |
strip_metadata(keep_orientation=True) | Remove EXIF / GPS / camera info by re-encoding. keep_orientation: keep the picture upright. | a new picture | every device |
edge_detect(kernel="sobel", threshold=80) | Sobel / Prewitt / Laplacian edge map. kernel: "sobel", "prewitt" or "laplacian"; threshold: 0 to 255. | a new picture | every device |
watermark(text="Sample", anchor="bottom-right", opacity=0.75, font_size=28, color="#ffffff") | Write text over the picture. text: the words; anchor: "bottom-right", "top-left", "center"…; opacity: 0 to 1; font_size: px; color: hex colour. | a new picture | every device |
canny_edges(low=50, high=150) | Hysteresis edge detector — cleaner, connected edges vs the kernel filter. low: lower edge threshold; high: upper edge threshold. | a new picture | every device |
threshold(mode="otsu", value=127, invert=False) | Binarize via fixed value, Otsu (auto), or local adaptive thresholding. mode: "otsu" (automatic), "binary" or "adaptive"; value: 0 to 255, for "binary"; invert: swap black and white. | a new picture | every device |
find_contours(low=50, high=150, min_area=64, overlay=True) | Detect blobs/shapes; returns exact count + per-region area, bbox, centroid. low: lower edge threshold; high: upper edge threshold; min_area: ignore shapes smaller than this, px²; overlay: also return a picture with the finds drawn on. | data | every device |
detect_shapes(min_area=64, epsilon=0.04, overlay=True) | Classify each contour as triangle / rectangle / square / circle / polygon. min_area: ignore shapes smaller than this, px²; epsilon: corner tolerance, share of the outline; overlay: also return a picture with the finds drawn on. | data | every device |
find_faces(overlay=True) | Count the faces in a photo and return where each one is. overlay: also return a picture with the faces marked. | data | iPhone and iPad app |
read_codes(overlay=True) | Read every QR code and barcode in the picture. overlay: also return a picture with the codes marked. | data | iPhone and iPad app |
classify(max_labels=10, min_confidence=0.1) | Name what is in the picture (dog, beach, food…) with a confidence for each label. max_labels: most labels to return; min_confidence: drop labels below this, 0 to 1. | data | iPhone and iPad app |
photo_details() | Date taken, location, camera and exposure, as data. | data | iPhone and iPad app |
hide_faces(style="blur") | Blur, pixelate or black out every face in the photo. style: "blur", "pixelate" or "solid". | a new picture | iPhone and iPad app |
scan_document(enhance=True) | Find the page in a photo and flatten it to a straight-on scan. enhance: even out the lighting like a scanner. | a new picture | iPhone and iPad app |
smart_crop(aspect="1:1") | Crop to the part of the photo that draws the eye. aspect: "1:1", "4:5", "3:2", "16:9", "9:16" or "tight". | a new picture | iPhone and iPad app |
straighten() | Level a tilted horizon. | a new picture | iPhone and iPad app |
favicon_set(include_ico=True, include_manifest=True) | Generate web favicons: 16/32/48/192/512 PNGs + apple-touch + favicon.ico + manifest icons. include_ico: add favicon.ico; include_manifest: add the web manifest icons. | a set of files | every device |
app_icon_set(platform="ios") | Generate iOS .appiconset and/or Android mipmap density buckets with Contents.json. platform: "ios", "android" or "both". | a set of files | every device |
trace(colors=16, detail="medium") | Turn it into flat-colour vector shapes (as 2Vec does): a Vector you can save as .svg or animate in Pymations. colors: how many colours to keep; detail: "low" (smoother, fewer points), "medium" or "high". | a Vector | every device |
save(name) | Write the picture beside your .py (.png, .jpg or .webp; a Vector as .svg; a file set as a folder). Returns the path. | the path | every device |
size() | The picture's width and height in pixels. | (width, height) | every device |
run(name, **keywords) | Run any method above by its name. | as that method | as that method |
available() | The names of the methods this device can run. | a list | every device |
Related
- Using Your Files: read and write other files beside your script.
- Maths Animations (Pymations): explainer videos in Python.
- Drawing in 2D: drawing pictures with
ctx.