Commit 9b345841e4633ccf8891aae5d051af07e388e32a
1 parent
c3de2618
put some HTML visualization functions in brpy
Showing
2 changed files
with
61 additions
and
13 deletions
scripts/face_cluster_viz.py renamed to scripts/brpy/face_cluster_viz.py
| 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
| 2 | 2 | ||
| 3 | -from PIL import Image | ||
| 4 | import csv, sys, json, argparse | 3 | import csv, sys, json, argparse |
| 4 | +from brpy.html_viz import crop_to_bb | ||
| 5 | 5 | ||
| 6 | parser = argparse.ArgumentParser(description='Visualize face cluster results in an HTML page.') | 6 | parser = argparse.ArgumentParser(description='Visualize face cluster results in an HTML page.') |
| 7 | parser.add_argument('input_file', type=str, help='Results from clustering (in csv format)') | 7 | parser.add_argument('input_file', type=str, help='Results from clustering (in csv format)') |
| @@ -16,24 +16,15 @@ clustmap = dict() | @@ -16,24 +16,15 @@ clustmap = dict() | ||
| 16 | with open(args.input_file) as f: | 16 | with open(args.input_file) as f: |
| 17 | for line in csv.DictReader(f): | 17 | for line in csv.DictReader(f): |
| 18 | c = int(line[args.cluster_key]) | 18 | c = int(line[args.cluster_key]) |
| 19 | + if c not in clustmap: | ||
| 20 | + clustmap[c] = [] | ||
| 19 | x,y,width,height = [ float(line[k]) for k in ('Face_X','Face_Y','Face_Width','Face_Height') ] | 21 | x,y,width,height = [ float(line[k]) for k in ('Face_X','Face_Y','Face_Width','Face_Height') ] |
| 20 | imname = '%s/%s' % (args.img_loc, line['File']) | 22 | imname = '%s/%s' % (args.img_loc, line['File']) |
| 21 | try: | 23 | try: |
| 22 | - img = Image.open(imname) | ||
| 23 | - imwidth, imheight = img.size | 24 | + html = crop_to_bb(x,y,width,height,imname,maxheight=400) |
| 24 | except IOError: | 25 | except IOError: |
| 25 | print('problem with %s' % imname) | 26 | print('problem with %s' % imname) |
| 26 | continue | 27 | continue |
| 27 | - ratio = maxheight / height | ||
| 28 | - # note for future me: | ||
| 29 | - # image is cropped with div width/height + overflow:hidden, | ||
| 30 | - # resized with img height, | ||
| 31 | - # and positioned with img margin | ||
| 32 | - html = '<div style="overflow:hidden;display:inline-block;width:%ipx;height:%ipx;">' % (width*ratio, maxheight) | ||
| 33 | - html += '<img src="%s" style="height:%ipx;margin:-%ipx 0 0 -%ipx;"/>' % (imname, imheight*ratio, y*ratio, x*ratio) | ||
| 34 | - html += '</div>' | ||
| 35 | - if c not in clustmap: | ||
| 36 | - clustmap[c] = [] | ||
| 37 | clustmap[c].append(html) | 28 | clustmap[c].append(html) |
| 38 | 29 | ||
| 39 | # browsers crash for a DOM with this many img tags, | 30 | # browsers crash for a DOM with this many img tags, |
scripts/brpy/html_viz.py
0 → 100644
| 1 | +''' | ||
| 2 | +Some funcs to generate HTML visualizations. | ||
| 3 | +Run from the folder you intend to save the HTML page so | ||
| 4 | +the relative paths in the HTML file are correct and PIL can find the images on disk. | ||
| 5 | +Requires local images, but should be pretty easy to set up an apache server (or whatev) | ||
| 6 | +and host them as long as the relative paths remain the same on ya serva. | ||
| 7 | +''' | ||
| 8 | + | ||
| 9 | +from PIL import Image | ||
| 10 | + | ||
| 11 | +def crop_to_bb(x, y, width, height, imname, maxheight=None): | ||
| 12 | + ''' | ||
| 13 | + Generates an HTML string that crops to a given bounding box and resizes to maxheight pixels. | ||
| 14 | + A maxheight of None will keep the original size (default). | ||
| 15 | + When two crops are put next to each other, they will be inline. To make each crop its own line, wrap it in a div. | ||
| 16 | + ''' | ||
| 17 | + img = Image.open(imname) | ||
| 18 | + imwidth, imheight = img.size | ||
| 19 | + if not maxheight: | ||
| 20 | + maxheight = height | ||
| 21 | + ratio = maxheight / height | ||
| 22 | + # note for future me: | ||
| 23 | + # image is cropped with div width/height + overflow:hidden, | ||
| 24 | + # resized with img height, | ||
| 25 | + # and positioned with img margin | ||
| 26 | + html = '<div style="overflow:hidden; display:inline-block; width:%ipx; height:%ipx;">' % (width*ratio, maxheight) | ||
| 27 | + html += '<img src="%s" style="height:%ipx; margin:-%ipx 0 0 -%ipx;"/>' % (imname, imheight*ratio, y*ratio, x*ratio) | ||
| 28 | + html += '</div>' | ||
| 29 | + return html | ||
| 30 | + | ||
| 31 | +def bbs_for_image(imname, bbs, maxheight=None, colors=None): | ||
| 32 | + ''' | ||
| 33 | + Generates an HTML string for an image with bounding boxes. | ||
| 34 | + bbs: iterable of (x,y,width,height) bounding box tuples | ||
| 35 | + ''' | ||
| 36 | + img = Image.open(imname) | ||
| 37 | + imwidth, imheight = img.size | ||
| 38 | + if not maxheight: | ||
| 39 | + maxheight = imheight | ||
| 40 | + ratio = maxheight/imheight | ||
| 41 | + html = [ | ||
| 42 | + '<div style="position:relative">', | ||
| 43 | + '<img src="%s" style="height:%ipx" />' % (imname, maxheight) | ||
| 44 | + ] | ||
| 45 | + if not colors: | ||
| 46 | + colors = ['green']*len(bbs) | ||
| 47 | + html.extend([ bb(*box, ratio=ratio, color=color) for color,box in zip(colors,bbs) ]) | ||
| 48 | + html.append('</div>') | ||
| 49 | + return '\n'.join(html) | ||
| 50 | + | ||
| 51 | + | ||
| 52 | +def bb(x, y, width, height, ratio=1.0, color='green'): | ||
| 53 | + ''' | ||
| 54 | + Generates an HTML string bounding box. | ||
| 55 | + ''' | ||
| 56 | + html = '<div style="position:absolute; border:2px solid %s; color:%s; left:%ipx; top:%ipx; width:%ipx; height:%ipx;"></div>' | ||
| 57 | + return html % (color, color, x*ratio, y*ratio, width*ratio, height*ratio) |