Closed Yuvi-416 closed 3 years ago
Hi @Yuvi-416, are you looking to do this from an ImageJ macro? If so the below code snippets will need modified a little, I can help you with that if needed.
If you do not want to save the file again with all of the resolutions then it will mean downsampling the original on the fly. There is a SimpleImageScaler
class which we use internally for downsampling. A good example of how to read a downsampled tile would be the getTile method here: https://github.com/ome/bioformats/blob/develop/components/bio-formats-tools/src/loci/formats/tools/ImageConverter.java#L1070
I have added a few additional comments to it below:
// If the reader has enough resolutions then read the original data
if (resolution < reader.getResolutionCount()) {
reader.setResolution(resolution);
return reader.openBytes(no, x, y, w, h);
}
// Otherwise set the reader to the highest resolution image
reader.setResolution(0);
// Create an ImageScaler
IImageScaler scaler = new SimpleImageScaler();
int scale = (int) Math.pow(pyramidScale, resolution);
// Read the original full resolution tile
byte[] tile =
reader.openBytes(no, x * scale, y * scale, w * scale, h * scale);
int type = reader.getPixelType();
// Return the downsampled tile
return scaler.downsample(tile, w * scale, h * scale, scale,
FormatTools.getBytesPerPixel(type), reader.isLittleEndian(),
FormatTools.isFloatingPoint(type), reader.getRGBChannelCount(),
reader.isInterleaved());
Hi there, Thanks for your quick reply. I was looking to perform downsampling to the original image in a python environment using Python-bioformats, not in an ImageJ. I don´t know whether there is a function like SimpleImageScaler or a getTile in a 4.0 version Python-bioformats. You can share some idea how can I achieve my goal on python env? Is there any function which can handle these things? The code which you have shared above looks cool and interesting too. can I use that code using a python-bioformats?
The first section of the code should be as normal for reading your image tile in python.
The last bit, the call to downsample I'm afraid doesn't have an easy helper method yet. You should however be able to use the javabridge in a similar way to python-bioformats
to wrap the java class and function to allow you to use it in python (https://pythonhosted.org/javabridge/highlevel.html#wrapping-java-objects-using-reflection). I have not yet tested it but it should look something similar to the below:
class SimpleImageScaler:
new_fn = javabridge.make_new("loci/common/image/SimpleImageScaler", "()V")
def __init__(self):
self.new_fn()
downsample = javabridge.make_method("downsample", "([B, I, I, D, I, Z, Z, I, Z)[B", "")
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
Hi there, I tried your suggestion but I get an unknown error related to self.o (I didn't understand much about this) Code:
class SimpleImageScaler:
new_fn = javabridge.make_new("loci/common/image/SimpleImageScaler", "()V")
def __init__(self):
self.new_fn()
downsample = javabridge.make_method("downsample", "([B, I, I, D, I, Z, Z, I, Z)[B", "")
##############################
# Read the Tiles
# Series---»z-stack---
##############################
for series in range(reader.rdr.getSeriesCount()):
series += 3
width = reader.rdr.getSizeX()
height = reader.rdr.getSizeY()
reader.rdr.setSeries(series)
# read the z-stack
for zstack in range(reader.rdr.getImageCount()):
width = reader.rdr.getSizeX()
height = reader.rdr.getSizeY()
# Determined the number of tiles to read and write
nXTiles = int(math.floor(width / tile_SizeX))
nYTiles = int(math.floor(height / tile_SizeY))
if nXTiles * tile_SizeX != width:
nXTiles = nXTiles + 1
if nYTiles * tile_SizeY != height:
nYTiles = nYTiles + 1
encoded_framed_items = []
for y in range(nYTiles):
for x in range(nXTiles):
# The x and y coordinates for the current tile
tileX = x * tile_SizeX
tileY = y * tile_SizeY
effTileSizeX = tile_SizeX
if (tileX + tile_SizeX) >= width:
effTileSizeX = width - tileX
effTileSizeY = tile_SizeY
if (tileY + tile_SizeY) >= height:
effTileSizeY = height - tileY
# Read and write tiles
i = reader.rdr.openBytes(zstack, tileX, tileY, effTileSizeX, effTileSizeY)
buf1 = reader.read(zstack, rescale=False, XYWH=(tileX, tileY, effTileSizeX, effTileSizeY))
scale = 2
ds = SimpleImageScaler
ds. downsample(i, width * scale, height * scale, scale)
Error:
Traceback (most recent call last):
File "/snap/pycharm-community/219/plugins/python-ce/helpers/pydev/pydevd.py", line 1448, in _exec
pydev_imports.execfile(file, globals, locals) # execute the script
File "/snap/pycharm-community/219/plugins/python-ce/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "/home/yuvi/PycharmProjects/task-1/temp/Temp-2-others.py", line 99, in <module>
ds. downsample(i, width * scale, height * scale, scale)
File "/home/yuvi/anaconda3/envs/task-1/lib/python3.7/site-packages/javabridge/jutil.py", line 960, in method
assert isinstance(self.o, _javabridge.JB_Object)
AttributeError: 'numpy.ndarray' object has no attribute 'o'
python-BaseException
Process finished with exit code 130 (interrupted by signal 2: SIGINT)
Error part:
def make_method(name, sig, doc='No documentation', fn_post_process=None):
'''Return a class method for the given Java class. When called,
the method expects to find its Java instance object in ``self.o``,
which is where ``make_new`` puts it.
:param name: method name
:param sig: calling signature
:param doc: doc string to be attached to the Python method
:param fn_post_process: a function, such as a wrapper, that transforms
the method output into something more useable.
'''
def method(self, *args):
assert isinstance(self.o, _javabridge.JB_Object)
result = call(self.o, name, sig, *args)
if fn_post_process is not None:
result = fn_post_process(result)
return result
method.__doc__ = doc
return method
I have another question too. As my input image is 186496 x 36608 and I want the downsampled image in a size 93248 x 18304. And the extracted tile size is: 1024* 1024 So, what should be the value of scale, height and weight in the downsample function?
Hi there, I have a ndpi image. I want to resize .ndpi image whose first stack has a size of 186496 x 36608 into 93248 x 18304. I don't want to save it. I just want to load it into memory and later wants to read the resized image in the form of a tile.
I study about write_image function but it's not letting me select the desired size.
Any help