WIP: add quick-draw example sketch
This commit is contained in:
460
quick_draw_api.py
Normal file
460
quick_draw_api.py
Normal file
@@ -0,0 +1,460 @@
|
||||
"""Quick draw dataset
|
||||
|
||||
Example contributed by Blair Morrison (https://github.com/blrm) and adapted by Antoine Beyeler
|
||||
"""
|
||||
|
||||
import pathlib
|
||||
import random
|
||||
import struct
|
||||
import urllib.request
|
||||
from itertools import islice
|
||||
|
||||
import vpype as vp
|
||||
from shapely.geometry import MultiLineString
|
||||
|
||||
import vsketch
|
||||
|
||||
quick_draw_categories = (
|
||||
"aircraft carrier",
|
||||
"airplane",
|
||||
"alarm clock",
|
||||
"ambulance",
|
||||
"angel",
|
||||
"animal migration",
|
||||
"ant",
|
||||
"anvil",
|
||||
"apple",
|
||||
"arm",
|
||||
"asparagus",
|
||||
"axe",
|
||||
"backpack",
|
||||
"banana",
|
||||
"bandage",
|
||||
"barn",
|
||||
"baseball",
|
||||
"baseball bat",
|
||||
"basket",
|
||||
"basketball",
|
||||
"bat",
|
||||
"bathtub",
|
||||
"beach",
|
||||
"bear",
|
||||
"beard",
|
||||
"bed",
|
||||
"bee",
|
||||
"belt",
|
||||
"bench",
|
||||
"bicycle",
|
||||
"binoculars",
|
||||
"bird",
|
||||
"birthday cake",
|
||||
"blackberry",
|
||||
"blueberry",
|
||||
"book",
|
||||
"boomerang",
|
||||
"bottlecap",
|
||||
"bowtie",
|
||||
"bracelet",
|
||||
"brain",
|
||||
"bread",
|
||||
"bridge",
|
||||
"broccoli",
|
||||
"broom",
|
||||
"bucket",
|
||||
"bulldozer",
|
||||
"bus",
|
||||
"bush",
|
||||
"butterfly",
|
||||
"cactus",
|
||||
"cake",
|
||||
"calculator",
|
||||
"calendar",
|
||||
"camel",
|
||||
"camera",
|
||||
"camouflage",
|
||||
"campfire",
|
||||
"candle",
|
||||
"cannon",
|
||||
"canoe",
|
||||
"car",
|
||||
"carrot",
|
||||
"castle",
|
||||
"cat",
|
||||
"ceiling fan",
|
||||
"cello",
|
||||
"cell phone",
|
||||
"chair",
|
||||
"chandelier",
|
||||
"church",
|
||||
"circle",
|
||||
"clarinet",
|
||||
"clock",
|
||||
"cloud",
|
||||
"coffee cup",
|
||||
"compass",
|
||||
"computer",
|
||||
"cookie",
|
||||
"cooler",
|
||||
"couch",
|
||||
"cow",
|
||||
"crab",
|
||||
"crayon",
|
||||
"crocodile",
|
||||
"crown",
|
||||
"cruise ship",
|
||||
"cup",
|
||||
"diamond",
|
||||
"dishwasher",
|
||||
"diving board",
|
||||
"dog",
|
||||
"dolphin",
|
||||
"donut",
|
||||
"door",
|
||||
"dragon",
|
||||
"dresser",
|
||||
"drill",
|
||||
"drums",
|
||||
"duck",
|
||||
"dumbbell",
|
||||
"ear",
|
||||
"elbow",
|
||||
"elephant",
|
||||
"envelope",
|
||||
"eraser",
|
||||
"eye",
|
||||
"eyeglasses",
|
||||
"face",
|
||||
"fan",
|
||||
"feather",
|
||||
"fence",
|
||||
"finger",
|
||||
"fire hydrant",
|
||||
"fireplace",
|
||||
"firetruck",
|
||||
"fish",
|
||||
"flamingo",
|
||||
"flashlight",
|
||||
"flip flops",
|
||||
"floor lamp",
|
||||
"flower",
|
||||
"flying saucer",
|
||||
"foot",
|
||||
"fork",
|
||||
"frog",
|
||||
"frying pan",
|
||||
"garden",
|
||||
"garden hose",
|
||||
"giraffe",
|
||||
"goatee",
|
||||
"golf club",
|
||||
"grapes",
|
||||
"grass",
|
||||
"guitar",
|
||||
"hamburger",
|
||||
"hammer",
|
||||
"hand",
|
||||
"harp",
|
||||
"hat",
|
||||
"headphones",
|
||||
"hedgehog",
|
||||
"helicopter",
|
||||
"helmet",
|
||||
"hexagon",
|
||||
"hockey puck",
|
||||
"hockey stick",
|
||||
"horse",
|
||||
"hospital",
|
||||
"hot air balloon",
|
||||
"hot dog",
|
||||
"hot tub",
|
||||
"hourglass",
|
||||
"house",
|
||||
"house plant",
|
||||
"hurricane",
|
||||
"ice cream",
|
||||
"jacket",
|
||||
"jail",
|
||||
"kangaroo",
|
||||
"key",
|
||||
"keyboard",
|
||||
"knee",
|
||||
"knife",
|
||||
"ladder",
|
||||
"lantern",
|
||||
"laptop",
|
||||
"leaf",
|
||||
"leg",
|
||||
"light bulb",
|
||||
"lighter",
|
||||
"lighthouse",
|
||||
"lightning",
|
||||
"line",
|
||||
"lion",
|
||||
"lipstick",
|
||||
"lobster",
|
||||
"lollipop",
|
||||
"mailbox",
|
||||
"map",
|
||||
"marker",
|
||||
"matches",
|
||||
"megaphone",
|
||||
"mermaid",
|
||||
"microphone",
|
||||
"microwave",
|
||||
"monkey",
|
||||
"moon",
|
||||
"mosquito",
|
||||
"motorbike",
|
||||
"mountain",
|
||||
"mouse",
|
||||
"moustache",
|
||||
"mouth",
|
||||
"mug",
|
||||
"mushroom",
|
||||
"nail",
|
||||
"necklace",
|
||||
"nose",
|
||||
"ocean",
|
||||
"octagon",
|
||||
"octopus",
|
||||
"onion",
|
||||
"oven",
|
||||
"owl",
|
||||
"paintbrush",
|
||||
"paint can",
|
||||
"palm tree",
|
||||
"panda",
|
||||
"pants",
|
||||
"paper clip",
|
||||
"parachute",
|
||||
"parrot",
|
||||
"passport",
|
||||
"peanut",
|
||||
"pear",
|
||||
"peas",
|
||||
"pencil",
|
||||
"penguin",
|
||||
"piano",
|
||||
"pickup truck",
|
||||
"picture frame",
|
||||
"pig",
|
||||
"pillow",
|
||||
"pineapple",
|
||||
"pizza",
|
||||
"pliers",
|
||||
"police car",
|
||||
"pond",
|
||||
"pool",
|
||||
"popsicle",
|
||||
"postcard",
|
||||
"potato",
|
||||
"power outlet",
|
||||
"purse",
|
||||
"rabbit",
|
||||
"raccoon",
|
||||
"radio",
|
||||
"rain",
|
||||
"rainbow",
|
||||
"rake",
|
||||
"remote control",
|
||||
"rhinoceros",
|
||||
"rifle",
|
||||
"river",
|
||||
"roller coaster",
|
||||
"rollerskates",
|
||||
"sailboat",
|
||||
"sandwich",
|
||||
"saw",
|
||||
"saxophone",
|
||||
"school bus",
|
||||
"scissors",
|
||||
"scorpion",
|
||||
"screwdriver",
|
||||
"sea turtle",
|
||||
"see saw",
|
||||
"shark",
|
||||
"sheep",
|
||||
"shoe",
|
||||
"shorts",
|
||||
"shovel",
|
||||
"sink",
|
||||
"skateboard",
|
||||
"skull",
|
||||
"skyscraper",
|
||||
"sleeping bag",
|
||||
"smiley face",
|
||||
"snail",
|
||||
"snake",
|
||||
"snorkel",
|
||||
"snowflake",
|
||||
"snowman",
|
||||
"soccer ball",
|
||||
"sock",
|
||||
"speedboat",
|
||||
"spider",
|
||||
"spoon",
|
||||
"spreadsheet",
|
||||
"square",
|
||||
"squiggle",
|
||||
"squirrel",
|
||||
"stairs",
|
||||
"star",
|
||||
"steak",
|
||||
"stereo",
|
||||
"stethoscope",
|
||||
"stitches",
|
||||
"stop sign",
|
||||
"stove",
|
||||
"strawberry",
|
||||
"streetlight",
|
||||
"string bean",
|
||||
"submarine",
|
||||
"suitcase",
|
||||
"sun",
|
||||
"swan",
|
||||
"sweater",
|
||||
"swing set",
|
||||
"sword",
|
||||
"syringe",
|
||||
"table",
|
||||
"teapot",
|
||||
"teddy-bear",
|
||||
"telephone",
|
||||
"television",
|
||||
"tennis racquet",
|
||||
"tent",
|
||||
"The Eiffel Tower",
|
||||
"The Great Wall of China",
|
||||
"The Mona Lisa",
|
||||
"tiger",
|
||||
"toaster",
|
||||
"toe",
|
||||
"toilet",
|
||||
"tooth",
|
||||
"toothbrush",
|
||||
"toothpaste",
|
||||
"tornado",
|
||||
"tractor",
|
||||
"traffic light",
|
||||
"train",
|
||||
"tree",
|
||||
"triangle",
|
||||
"trombone",
|
||||
"truck",
|
||||
"trumpet",
|
||||
"t-shirt",
|
||||
"umbrella",
|
||||
"underwear",
|
||||
"van",
|
||||
"vase",
|
||||
"violin",
|
||||
"washing machine",
|
||||
"watermelon",
|
||||
"waterslide",
|
||||
"whale",
|
||||
"wheel",
|
||||
"windmill",
|
||||
"wine bottle",
|
||||
"wine glass",
|
||||
"wristwatch",
|
||||
"yoga",
|
||||
"zebra",
|
||||
"zigzag",
|
||||
)
|
||||
|
||||
|
||||
def unpack_drawing(file_handle):
|
||||
(key_id,) = struct.unpack("Q", file_handle.read(8))
|
||||
(country_code,) = struct.unpack("2s", file_handle.read(2))
|
||||
(recognized,) = struct.unpack("b", file_handle.read(1))
|
||||
(timestamp,) = struct.unpack("I", file_handle.read(4))
|
||||
(n_strokes,) = struct.unpack("H", file_handle.read(2))
|
||||
image = []
|
||||
for i in range(n_strokes):
|
||||
(n_points,) = struct.unpack("H", file_handle.read(2))
|
||||
fmt = str(n_points) + "B"
|
||||
x = struct.unpack(fmt, file_handle.read(n_points))
|
||||
y = struct.unpack(fmt, file_handle.read(n_points))
|
||||
image.append((x, y))
|
||||
|
||||
return {
|
||||
"key_id": key_id,
|
||||
"country_code": country_code,
|
||||
"recognized": recognized,
|
||||
"timestamp": timestamp,
|
||||
"image": image,
|
||||
}
|
||||
|
||||
|
||||
def unpack_drawings(filename):
|
||||
with open(filename, "rb") as f:
|
||||
while True:
|
||||
try:
|
||||
yield unpack_drawing(f)
|
||||
except struct.error:
|
||||
break
|
||||
|
||||
|
||||
def quickdraw_to_linestring(qd_image):
|
||||
"""Returns a Shapely MultiLineString for the provided quickdraw image.
|
||||
This MultiLineString can be passed to vsketch
|
||||
"""
|
||||
linestrings = []
|
||||
for i in range(0, len(qd_image["image"])):
|
||||
line = zip(qd_image["image"][i][0], qd_image["image"][i][1])
|
||||
linestrings.append(tuple(line))
|
||||
return MultiLineString(linestrings)
|
||||
|
||||
|
||||
class QuickDrawSketch(vsketch.SketchClass):
|
||||
category = vsketch.Param("crab", choices=quick_draw_categories)
|
||||
page_size = vsketch.Param("a4", choices=vp.PAGE_SIZES.keys())
|
||||
landscape = vsketch.Param(False)
|
||||
margins = vsketch.Param(10, 0, unit="mm")
|
||||
layer_count = vsketch.Param(2, 1)
|
||||
columns = vsketch.Param(9, 1)
|
||||
rows = vsketch.Param(13, 1)
|
||||
scale_factor = vsketch.Param(3.0)
|
||||
|
||||
def draw(self, vsk: vsketch.Vsketch) -> None:
|
||||
vsk.size(self.page_size, landscape=self.landscape)
|
||||
vsk.penWidth("0.5mm")
|
||||
|
||||
# obtain the datafile
|
||||
file_name = self.category + ".bin"
|
||||
file_path = pathlib.Path(file_name)
|
||||
url = "https://storage.googleapis.com/quickdraw_dataset/full/binary/"
|
||||
url += file_name.replace(" ", "%20")
|
||||
if not file_path.exists():
|
||||
urllib.request.urlretrieve(url, file_name)
|
||||
|
||||
# extract some drawings
|
||||
drawing_set = unpack_drawings(file_name)
|
||||
drawing_subset = list(islice(drawing_set, 10000))
|
||||
|
||||
# draw stuff
|
||||
|
||||
width = vsk.width - 2 * self.margins
|
||||
height = vsk.height - 2 * self.margins
|
||||
|
||||
n = self.columns * self.rows
|
||||
samples = random.sample(drawing_subset, n)
|
||||
for j in range(self.rows):
|
||||
with vsk.pushMatrix():
|
||||
for i in range(self.columns):
|
||||
idx = j * self.columns + i
|
||||
with vsk.pushMatrix():
|
||||
vsk.scale(self.scale_factor * min(1 / self.columns, 1 / self.rows))
|
||||
drawing = quickdraw_to_linestring(samples[idx])
|
||||
vsk.stroke((idx % self.layer_count) + 1)
|
||||
vsk.geometry(drawing)
|
||||
vsk.translate(width / self.columns, 0)
|
||||
|
||||
vsk.translate(0, height / self.rows)
|
||||
|
||||
def finalize(self, vsk: vsketch.Vsketch) -> None:
|
||||
vsk.vpype("linemerge linesort")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
QuickDrawSketch.display()
|
||||
Reference in New Issue
Block a user