def __init__(self, root): pn = '/Users/nathaning/Documents/Python/Image Processing/B2 H&E 20X_001.svs' level = 1 i = OpenSlide(pn) # Load an SVS file # dims = i.level_dimensions[level] # k = i.read_region((0,0), level, dims) #Extract the level 1 image as a PIL.Image Object k = i.get_thumbnail(size=(600, 600)) # k.show() self.pi = ImageTk.PhotoImage(k) disp = Label(root, image=self.pi) disp.pack() print 'done'
def get_thumbnail( slide_path: str, downsample: int = None, create_thumbnail: bool = False ) -> Image.Image: """Return thumbnail by using openslide or by creating a new one.""" if slide_path.endswith('czi'): if create_thumbnail: return generate_thumbnail(slide_path, downsample) else: return None else: reader = OpenSlide(slide_path) level_downsamples = [round(x) for x in reader.level_downsamples] if downsample is None: downsample = max(level_downsamples) if downsample in level_downsamples: level = level_downsamples.index(downsample) dims = reader.level_dimensions[level] thumbnail = reader.get_thumbnail(dims) elif create_thumbnail: thumbnail = generate_thumbnail(slide_path, downsample) else: thumbnail = None return thumbnail
def get(self, id): """ Get slide thumbnail --- tags: - Thumbnail parameters: - in: path name: id description: MonogDB ObjectId -- Example 57bf3c092f9b2e1595b29730 type: string - in: query name: size description: Thumbnail size [small, medium, large] type: string responses: 200: description: Returns the slide information 404: description: Invalid slide Id or slide not found """ if not ObjectId.is_valid(id): resp = {"status": 404, "message": "Invalid slide Id " + id} return Response(dumps(resp), status=404, mimetype='application/json') thumbSize = request.args.get("size", "small") image = self.slides.find_one({'_id': ObjectId(id)}) path = image["path"] filename = os.path.splitext( os.path.basename(path))[0] + "." + str(thumbSize) + ".jpg" if not self.gfs.exists(filename=filename): width = int(image["scanProperties"]["openslide_level[0]_width"]) height = int(image["scanProperties"]["openslide_level[0]_height"]) thumbHeight = float(self.config["thumb_" + thumbSize + "_height"]) thumbWidth = int(round(thumbHeight / float(height) * int(width))) try: osr = OpenSlide(path) thumb = osr.get_thumbnail((thumbWidth, thumbHeight)) except OpenSlideError, e: resp = { "status": 404, "message": "OpenSlideError: Thumbnail failed to load" } return Response(dumps(resp), status=404, mimetype='application/json') except ValueError: resp = { "status": 404, "message": "ValueError: Thumbnail failed to load" } return Response(dumps(resp), status=404, mimetype='application/json')
def preview_from_queries( slide: openslide.OpenSlide, queries: Sequence[Patch], min_res: int = 512, color: Tuple[int, int, int] = (255, 255, 0), thickness: int = 2, cell_size: int = 20, size_0: Optional[Coord] = None, ) -> NDByteImage: """ Give thumbnail with patches displayed. Args: slide: openslide object queries: patch objects to preview from min_res: minimum size for the smallest side of the thumbnail (usually the width) color: rgb color for patch boundaries thickness: thickness of patch boundaries cell_size: size of a cell representing a patch in the grid psize: size of a patch at level 0 Returns: Thumbnail image with patches displayed. """ # get thumbnail first slide_size = Coord(slide.dimensions) if size_0 is None: size_0 = Coord(queries[0].size_0) thickness = 2 * (thickness // 2) + 1 res = slide_size / size_0 * (thickness + cell_size) + thickness thumb_w = max(min_res, res.x) thumb_h = max(min_res, res.y) image = slide.get_thumbnail((thumb_w, thumb_h)) thumb_size = Coord(image.size) dsr = slide_size[0] / thumb_size[0] image = numpy.array(image)[:, :, 0:3] # get grid grid = 255 * numpy.ones((thumb_size.y, thumb_size.x), numpy.uint8) for query in queries: # position in queries are absolute x, y = query.position / dsr dx, dy = query.size_0 / dsr startx = min(x, thumb_size.x - 1) starty = min(y, thumb_size.y - 1) endx = min(x + dx, thumb_size.x - 1) endy = min(y + dy, thumb_size.y - 1) # horizontal segments grid[starty, startx:endx] = 0 grid[endy, startx:endx] = 0 # vertical segments grid[starty:endy, startx] = 0 grid[starty:endy, endx] = 0 grid = grid < 255 d = disk(thickness//2) grid = binary_dilation(grid, d) image[grid] = color return image
def get_thumbnails(): import os from openslide import OpenSlide data_dir = '/media/hui/Local Disk1/work/Data/Liver_Multi_Modality/Pathology/SlideImages/20-1018 PURU_VINOD' save_dir = '/media/hui/Local Disk1/work/Data/Liver_Multi_Modality/Pathology/thumbnails' os.makedirs(save_dir, exist_ok=True) filelist = os.listdir(data_dir) for file in filelist: wsi_file = OpenSlide('{:s}/{:s}'.format(data_dir, file)) thumbnail = wsi_file.get_thumbnail((1000, 1000)) thumbnail.save('{:s}/{:s}.png'.format(save_dir, file.split('.')[0]))
def get(self, id): """ Get slide thumbnail --- tags: - Thumbnail parameters: - in: path name: id description: MonogDB ObjectId -- Example 57bf3c092f9b2e1595b29730 type: string - in: query name: size description: Thumbnail size [small, medium, large] type: string responses: 200: description: Returns the slide information 404: description: Invalid slide Id or slide not found """ if not ObjectId.is_valid(id): resp = {"status": 404, "message": "Invalid slide Id " + id} return Response(dumps(resp), status=404, mimetype='application/json') thumbSize = request.args.get("size", "small") image = self.slides.find_one({'_id': ObjectId(id)}) path = image["path"] filename = os.path.splitext(os.path.basename(path))[0] + "." + str(thumbSize) + ".jpg" if not self.gfs.exists(filename=filename): width = int(image["scanProperties"]["openslide_level[0]_width"]) height = int(image["scanProperties"]["openslide_level[0]_height"]) thumbHeight = float(self.config["thumb_" + thumbSize + "_height"]) thumbWidth = int(round(thumbHeight/float(height) * int(width))) try: osr = OpenSlide(path) thumb = osr.get_thumbnail((thumbWidth,thumbHeight)) except OpenSlideError, e: resp = {"status": 404, "message": "OpenSlideError: Thumbnail failed to load"} return Response(dumps(resp), status=404, mimetype='application/json') except ValueError: resp = {"status": 404, "message": "ValueError: Thumbnail failed to load"} return Response(dumps(resp), status=404, mimetype='application/json')
def gen_thumbnail_url(request, slide_id): try: s = Alopecia.objects.get(pk=slide_id) except Alopecia.DoesNotExist: raise Http404 label_name = str(s.LabelUrlPath).split('/')[-1] if label_name != 'placeholder.png': return JsonResponse({ 'thumbnail': request.build_absolute_uri(str(s.LabelUrlPath)), }) else: if s.SlideType == 1: ds = pydicom.dcmread(str(s.UrlPath)) thumbnail = get_PIL_image(ds) response = HttpResponse(content_type='image/png') thumbnail.thumbnail(MAX_THUMBNAIL_SIZE) filename = str(s.UrlPath).split('/')[-1] fWithoutExt = filename.split('.') fWithoutExt.pop() fWithoutExt = ''.join(fWithoutExt) thumbnailName = fWithoutExt + '.thumbnail' dirPath = settings.STATICFILES_DIRS[0] + '/images/thumbnail' thumbnail.save(dirPath + '/' + thumbnailName, 'JPEG') return JsonResponse({ 'thumbnail': request.build_absolute_uri('/static/images/thumbnail/') + thumbnailName, }) else: file = path.join(settings.HISTOSLIDE_SLIDEROOT, str(s.UrlPath)) slide = OpenSlide(file) thumbnail = slide.get_thumbnail((800, 600)) filename = str(s.UrlPath).split('/')[-1] fWithoutExt = filename.split('.') fWithoutExt.pop() fWithoutExt = ''.join(fWithoutExt) thumbnailName = fWithoutExt + '.thumbnail' dirPath = settings.STATICFILES_DIRS[0] + '/images/thumbnail' thumbnail.save(dirPath + '/' + thumbnailName, 'JPEG') return JsonResponse({ 'thumbnail': request.build_absolute_uri('/static/images/thumbnail/') + thumbnailName, })
def getThumbnail(path): """This will return the 0/0 tile later whch in the case of an SVS image is actually the thumbnail..... """ path = os.path.abspath(os.path.join(dz.config['slides_dir'], path)) osr = OpenSlide(path) format = 'jpeg' format = format.lower() if format != 'jpeg' and format != 'png': # Not supported by Deep Zoom abort(404) try: thumb = osr.get_thumbnail((300, 300)) except ValueError: # Invalid level or coordinates abort(404) buf = PILBytesIO() thumb.save(buf, 'jpeg', quality=90) resp = make_response(buf.getvalue()) resp.mimetype = 'image/%s' % format return resp
def generate_thumbnail(image_filepath, thumbnail_filepath): ''' Generates a thumbnail from the specified image. ''' # open image with OpenSlide library image_file = OpenSlide(image_filepath) # extract image dimensions image_dims = image_file.dimensions # make thumbnail 100 times smaller thumb_dims = tuple( (x/100 for x in image_dims) ) # create thumbnail thumb_file = image_file.get_thumbnail(thumb_dims) # save file with desired path, format thumb_file.save(thumbnail_filepath, "png") # cleanup image_file.close()
def getThumbnail(path): """This will return the 0/0 tile later whch in the case of an SVS image is actually the thumbnail..... """ path = os.path.abspath(os.path.join(dz.config['slides_dir'], path)) osr = OpenSlide(path) format = 'jpeg' format = format.lower() if format != 'jpeg' and format != 'png': # Not supported by Deep Zoom abort(404) try: thumb = osr.get_thumbnail( (300,300)) except ValueError: # Invalid level or coordinates abort(404) buf = PILBytesIO() thumb.save(buf, 'jpeg', quality=90) resp = make_response(buf.getvalue()) resp.mimetype = 'image/%s' % format return resp
def print_slide_details( wsi: openslide.OpenSlide, show_thumbnail: bool = True, max_size: Tuple[int, int] = (1200, 800)) -> None: """Informations essentielles de la lame.""" # nombre de pixels par niveaux n_pixels = [w0 * w1 for (w0, w1) in wsi.level_dimensions] n_pixels_ = tuple(format(n, ',d').replace(',', ' ') for n in n_pixels) # taille (Gb) des niveaux t_pixels = tuple(round(24 * n / 1e9, 2) for n in n_pixels) # dimensions réelles (cm) de la lame dim_x = round( float(wsi.properties['openslide.mpp-x']) * wsi.dimensions[0] / 10000, 2) dim_y = round( float(wsi.properties['openslide.mpp-y']) * wsi.dimensions[1] / 10000, 2) # affichage des informations print(f"Fichier : {wsi}") print( f"Grandissement : {wsi.properties['openslide.objective-power']}x" ) print(f"Dimensions en pixel : {wsi.dimensions}") print(f"Dimensions en cm : {(dim_x, dim_y)}") print( f"Microns par pixel : {float(wsi.properties['openslide.mpp-x']):.3f}" ) print(f"Nombre de niveaux de résolution : {wsi.level_count}") print(f"Grandissement des niveaux : {wsi.level_downsamples}") print(f"Dimensions des niveaux : {wsi.level_dimensions}") print(f"Nombre de pixels des niveaux : {n_pixels_}") print(f"Taille (Gb) par niveaux : {t_pixels}") print(f"Taille fichier décompressé (Gb) : {round(sum(t_pixels), 2)}") # optionnel: affiche une image macro de la lame if show_thumbnail: display(wsi.get_thumbnail(size=max_size))
from openslide import OpenSlide svs_path = 'Slide 10.svs' # Open whole slide image img = OpenSlide(svs_path) # Get shape original_dimensions = img.dimensions # Get thumbnail image (t times smaller) t = 512 resize_width = original_dimensions[0] / t resize_height = original_dimensions[1] / t resized_img = img.get_thumbnail( (resize_width, resize_height)) # PIL.Image type resized_img.save('thumbnail_images_sample/' + svs_path.split('.')[0] + '.png') # Get a region of the original image (here [10000:10100,10000:10100]) cropped_img = img.read_region((10000, 10000), 0, (100, 100)) # PIL Image RGBA cropped_img = cropped_img.convert('RGB') # PIL Image RGB cropped_img.save('tmp.png')