sclass FaceDataSet { S csvSnippetID = #1032472; class Entry { S imageURL; File imageFile; DoubleRect facePosition; int w, h; BufferedImage image() { var img = loadImage2(imageFile); if (img == null) print(imageFile + " not found"); else { w = img.getWidth(); h = img.getHeight(); } ret img; } Rect absoluteFacePosition() { ret scaleRect_floor(facePosition, w, h); } BufferedImage markedImage(int width default w()) { var img = scaleToWidth(image(), width); int height = img.getHeight(); Rect r = scaleRect_floor(facePosition, width, height); drawBox(img, r, Color.red, 0.5); ret img; } int w() { if (w == 0) image(); ret w; } int h() { if (h == 0) image(); ret h; } } new L entries; File imagesDir() { ret javaxCachesDir("Google Face Data Set"); } File downloadImage(S url) { File file = newFile(imagesDir(), md5FileName(url) + fileExtension(url)); if (file.length() == 0) null; if (!file.exists()) try { loadBinaryPageToFile(url, file); } catch e { if (containsExceptionOfType FileNotFoundException(e)) // as a warning for future generations! saveBinaryFile(file, new byte[0]); } ret file.exists() ? file : null; } void load { for (LS row : parseExtendedCSV_iterator(loadSnippet(csvSnippetID))) { for n to 3: pcall { int i = n*5; new Entry e; e.imageURL = convertHttpToHttps(row.get(i++)); e.imageFile = downloadImage(e.imageURL); if (e.imageFile == null) continue with print("Skipping " + e.imageURL); e.facePosition = doubleRectFromPoints( parseDouble(row.get(i)), // left column (x1) parseDouble(row.get(i+2)), // top row (y1) parseDouble(row.get(i+1)), // right column (x2) parseDouble(row.get(i+3)), // bottom row (y2) ); entries.add(e); } } print("Have " + nEntries(entries)); } } /* Row begins: URL of image1 (string) Top-left column of the face bounding box in image1 normalized by width (float) Bottom-right column of the face bounding box in image1 normalized by width (float) Top-left row of the face bounding box in image1 normalized by height (float) Bottom-right row of the face bounding box in image1 normalized by height (float) */