def generate(self): if not self.source: raise MissingSource("The spec '%s' has no source file associated" " with it." % self) # TODO: Move into a generator base class # TODO: Factor out a generate_image function so you can create a generator and only override the PIL.Image creating part. (The tricky part is how to deal with original_format since generator base class won't have one.) try: img = open_image(self.source) except ValueError: # Re-open the file -- https://code.djangoproject.com/ticket/13750 self.source.open() img = open_image(self.source) original_format = img.format # Run the processors img = ProcessorPipeline(self.field.processors or []).process(img) #HOOK -- now process instance processors img = InstanceProcessorPipeline(self.field.instance_processors or []).process(img, self.instance) format = self.field.format or img.format or original_format or 'JPEG' options = self.options or {} fobj = img_to_fobj(img, format, self.autoconvert, **options) # print 'fobj? %s - %s - %s'%(fobj, img, format) # print options return fobj
def alg_change(self): algorithms = IntrinsicImagesAlgorithm.objects.filter(active=True) \ .order_by('slug', '-id') algorithm_errors = { alg: [] for alg in algorithms } light_stacks = PhotoLightStack.objects.all() for alg in progress_bar(algorithms): use_alg = True for light_stack in light_stacks: photo_ids = light_stack.photos.values_list('id', flat=True) decompositions = IntrinsicImagesDecomposition.objects.filter( algorithm=alg, photo_id__in=photo_ids) if len(decompositions) != len(photo_ids): use_alg = False break errors = [] for d1 in decompositions: r1 = open_image(d1.reflectance_image) r1 = srgb_to_rgb(np.asarray(r1).astype(float) / 255.0) r1 = np.mean(r1, axis=-1) for d2 in decompositions: if d1.photo_id == d2.photo_id: continue r2 = open_image(d2.reflectance_image) r2 = srgb_to_rgb(np.asarray(r2).astype(float) / 255.0) r2 = np.mean(r2, axis=-1) errors.append(lmse(r1, r2)) algorithm_errors[alg].append(np.mean(errors)) if use_alg: print alg.slug, alg.id, \ np.mean(algorithm_errors[alg]), \ np.median(algorithm_errors[alg]), \ np.std(algorithm_errors[alg]) errors = [ (alg, np.mean(errors), np.median(errors), np.std(errors)) for alg, errors in algorithm_errors.iteritems() if len(errors) == len(light_stacks) ] errors.sort(key=lambda x: x[1]) for alg, e, m, s in errors: print alg.slug, alg.id, e, m, s
def alg_change(self): algorithms = IntrinsicImagesAlgorithm.objects.filter(active=True) \ .order_by('slug', '-id') algorithm_errors = {alg: [] for alg in algorithms} light_stacks = PhotoLightStack.objects.all() for alg in progress_bar(algorithms): use_alg = True for light_stack in light_stacks: photo_ids = light_stack.photos.values_list('id', flat=True) decompositions = IntrinsicImagesDecomposition.objects.filter( algorithm=alg, photo_id__in=photo_ids) if len(decompositions) != len(photo_ids): use_alg = False break errors = [] for d1 in decompositions: r1 = open_image(d1.reflectance_image) r1 = srgb_to_rgb(np.asarray(r1).astype(float) / 255.0) r1 = np.mean(r1, axis=-1) for d2 in decompositions: if d1.photo_id == d2.photo_id: continue r2 = open_image(d2.reflectance_image) r2 = srgb_to_rgb(np.asarray(r2).astype(float) / 255.0) r2 = np.mean(r2, axis=-1) errors.append(lmse(r1, r2)) algorithm_errors[alg].append(np.mean(errors)) if use_alg: print alg.slug, alg.id, \ np.mean(algorithm_errors[alg]), \ np.median(algorithm_errors[alg]), \ np.std(algorithm_errors[alg]) errors = [(alg, np.mean(errors), np.median(errors), np.std(errors)) for alg, errors in algorithm_errors.iteritems() if len(errors) == len(light_stacks)] errors.sort(key=lambda x: x[1]) for alg, e, m, s in errors: print alg.slug, alg.id, e, m, s
def create_image_grid(items, thumb_width=500, thumb_height=500, padding=0, background=(255, 255, 255), resize_to_fill=False): """ Greate a grid of images. :param items: iterable of [(row, col, image), ...] """ # adjust so that the top left is (0, 0) min_row = min(t[0] for t in items) min_col = min(t[1] for t in items) items = [(row - min_row, col - min_col, image) for (row, col, image) in items] # find bottom-right nrows = 1 + max(t[0] for t in items) ncols = 1 + max(t[1] for t in items) # output canvas cell_width = thumb_width + padding cell_height = thumb_height + padding size = (ncols * cell_width, nrows * cell_height) print 'Creating image grid...' print 'nrows:', nrows print 'ncols:', ncols print 'size:', size out = Image.new(mode='RGB', size=size, color=background) # splat images filled = np.zeros((nrows, ncols), dtype=np.bool) for (row, col, image) in items: if filled[row, col]: continue filled[row, col] = True try: if isinstance(image, basestring): thumb = Image.open(image) else: thumb = open_image(image) except Exception as e: print e continue if resize_to_fill: thumb = ResizeToFill(thumb_width, thumb_height).process(thumb) else: thumb = ResizeToFit(thumb_width, thumb_height).process(thumb) thumb = ResizeCanvas(thumb_width, thumb_height, color=background).process(thumb) x = col * cell_width y = row * cell_height out.paste(thumb, box=(x, y, x + thumb_width, y + thumb_height)) return out
def create_image_pair_grid_list( image_pairs, ncols=64, size=64, padding=0, show_progress=False, downsample_ratio=1): """ Greate a grid of images from a list of files """ from pilkit.processors import ResizeToFit, ResizeCanvas nshapes = len(image_pairs) if downsample_ratio > 1: nshapes = (nshapes + downsample_ratio - 1) / downsample_ratio image_pairs = image_pairs[:nshapes] gridsize = size + padding nrows = (nshapes + ncols - 1) / ncols ncols = min(ncols, nshapes) out = Image.new( 'RGBA', (ncols * gridsize, nrows * gridsize * 2), color=(255, 255, 255, 255)) row = 0 col = 0 iterator = progress.bar(image_pairs) if show_progress else image_pairs for pair in iterator: for off, obj in enumerate(pair): try: thumb = open_image(obj) except Exception as e: print e continue thumb = ResizeToFit(size, size).process(thumb) thumb = ResizeCanvas( size, size, color=(255, 255, 255, 255)).process(thumb) out.paste(thumb, box=( col * gridsize, (2 * row + off) * gridsize, col * gridsize + size, (2 * row + off) * gridsize + size, )) col += 1 if col >= ncols: col = 0 row += 1 # fix transparency (composite with pure opaque white) out.putdata([ p if p[3] == 255 else ( (p[0] * p[3] + 255 * (255 - p[3])) / 255, (p[1] * p[3] + 255 * (255 - p[3])) / 255, (p[2] * p[3] + 255 * (255 - p[3])) / 255, 255 ) for p in out.getdata() ]) return out
def create_image_grid_qset(qset, image_attr, ncols=40, size=64, padding=0, show_progress=False, downsample_ratio=1, max_qset_size=None): """ Greate a grid of images from a queryset """ from pilkit.processors import ResizeToFit, ResizeCanvas # clamp number of shapes nshapes = qset.count() if downsample_ratio > 1: nshapes = (nshapes + downsample_ratio - 1) / downsample_ratio if max_qset_size: nshapes = min(nshapes, max_qset_size) qset = qset[:nshapes] gridsize = size + padding nrows = (nshapes + ncols - 1) / ncols ncols = min(ncols, nshapes) out = Image.new( 'RGB', (ncols * gridsize, nrows * gridsize), color=0xffffff) row = 0 col = 0 iterator = queryset_progress_bar(qset) if show_progress else qset for obj in iterator: try: thumb = open_image(getattr(obj, image_attr)) except Exception as e: print e continue thumb = ResizeToFit(size, size).process(thumb) thumb = ResizeCanvas(size, size, color=(255, 255, 255)).process(thumb) out.paste(thumb, box=( col * gridsize, row * gridsize, col * gridsize + size, row * gridsize + size, )) col += 1 if col >= ncols: col = 0 row += 1 return out