def siftImage(url): """ """ image = loadImage(url) handle, sift_filename = tempfile.mkstemp(prefix='decode-', suffix='.sift') os.close(handle) handle, pgm_filename = tempfile.mkstemp(prefix='decode-', suffix='.pgm') os.close(handle) try: # fit to 1000x1000 scale = min(1., 1000. / max(image.size)) # write the PGM pgm_size = int(image.size[0] * scale), int(image.size[1] * scale) image.convert('L').resize(pgm_size, PIL.Image.ANTIALIAS).save(pgm_filename) print >> sys.stderr, 'sift...', pgm_size, basedir = os.path.dirname(os.path.realpath(__file__)).replace(' ', '\ ') status, output = commands.getstatusoutput("%(basedir)s/bin/sift --peak-thresh=8 -o '%(sift_filename)s' '%(pgm_filename)s'" % locals()) data = open(sift_filename, 'r') assert status == 0, 'Sift execution returned %s instead of 0' % status features = [matchup.row2feature(row) for row in data] print >> sys.stderr, len(features), 'features' return image, features, scale finally: os.unlink(sift_filename) os.unlink(pgm_filename)
def main(scan_id, url, markers, apibase, password, qrcode_contents, do_sifting): """ """ scan_url_match = re.match(r'^http://.+/scans/([^/]+)/(.*)$', url, re.I) any_url_match = re.match(r'^http://.+/([^/]+)$', url, re.I) if scan_id and any_url_match: uploaded_file = any_url_match.group(1) elif scan_url_match: scan_id = scan_url_match.group(1) uploaded_file = scan_url_match.group(2) else: print >> sys.stderr, url, "doesn't match expected form" return # shorthand updateStepLocal = lambda step_number, extras: updateStep(apibase, password, scan_id, step_number, extras) try: if do_sifting: # sifting updateStepLocal(STEP_SIFTING, None) yield 60 image, features, scale = siftImage(url) sifted_bytes = StringIO.StringIO() for feature in features: print >> sifted_bytes, matchup.feature2row(feature) sifted_name = 'sift.txt' sifted_bytes = sifted_bytes.getvalue() appendScanFile(scan_id, sifted_name, sifted_bytes, apibase, password) # finding needles updateStepLocal(STEP_FINDING_NEEDLES, None) yield 30 # remove just the sticker from the markers dict stickers, sticker = [], markers.pop('Sticker', None) for marker in sticker.markersInFeatures(features): x, y = int(marker.anchor.x / scale), int(marker.anchor.y / scale) print >> sys.stderr, '->', (x, y) marker.anchor = Point(x, y) stickers.append(marker) for (name, marker) in markers.items(): print >> sys.stderr, name, '...', marker.locateInFeatures(features) x, y = int(marker.anchor.x / scale), int(marker.anchor.y / scale) print >> sys.stderr, '->', (x, y) marker.anchor = Point(x, y) else: image = loadImage(url) stickers = False if qrcode_contents: print_id, north, west, south, east = interpretCode(qrcode_contents) else: # reading QR code updateStepLocal(STEP_READING_QR_CODE, None) yield 10 qrcode = extractCode(image, markers) uploadScanCodeImage(apibase, password, scan_id, qrcode) print_id, north, west, south, east = readCode(qrcode) print 'code contents:', 'Print', print_id, (north, west, south, east) # tiling and uploading updateStepLocal(STEP_TILING_UPLOADING, None) yield 180 gym = ModestMaps.OpenStreetMap.Provider() topleft = gym.locationCoordinate(ModestMaps.Geo.Location(north, west)).zoomTo(20) bottomright = gym.locationCoordinate(ModestMaps.Geo.Location(south, east)).zoomTo(20) print 'Coordinates:', topleft, bottomright print 'Mercator:', poorMansSphericalMercator(topleft), poorMansSphericalMercator(bottomright) uploadScanImages(apibase, password, scan_id, image) uploadGeoTiff(apibase, password, markers, scan_id, image, topleft, bottomright) if stickers: uploadScanStickers(apibase, password, scan_id, markers, stickers, topleft, bottomright) min_zoom, max_zoom = 20, 0 renders = {} for zoom in range(20, 0, -1): localTopLeft = topleft.zoomTo(zoom) localBottomRight = bottomright.zoomTo(zoom) zoom_renders = tileZoomLevel(image, localTopLeft, localBottomRight, markers, renders) for (coord, tile_image) in zoom_renders: x, y, z = coord.column, coord.row, coord.zoom tile_name = '%(z)d/%(x)d/%(y)d.jpg' % locals() tile_bytes = StringIO.StringIO() tile_image.save(tile_bytes, 'JPEG') tile_bytes = tile_bytes.getvalue() appendScanFile(scan_id, tile_name, tile_bytes, apibase, password) renders[str(coord)] = tile_image min_zoom = min(coord.zoom, min_zoom) max_zoom = max(coord.zoom, max_zoom) print 'min:', topleft.zoomTo(min_zoom) print 'max:', bottomright.zoomTo(max_zoom) # finished! updateScan(apibase, password, scan_id, uploaded_file, print_id, bool(stickers), topleft.zoomTo(min_zoom), bottomright.zoomTo(max_zoom)) updateStepLocal(STEP_FINISHED, None) yield ALL_FINISHED except CodeReadException: print 'Failed QR code, maybe will try again?' extras = [(name, marker.anchor) for (name, marker) in markers.items()] extras = [(name, {'x': anch.x, 'y': anch.y}) for (name, anch) in extras] extras = {'image_url': url, 'markers': dict(extras)} updateStepLocal(STEP_BAD_QRCODE, json.dumps(extras)) yield ALL_FINISHED except UpdateScanException: print 'Giving up after many scan update attempts' yield ALL_FINISHED except KeyboardInterrupt, e: yield 1 raise e