Keeping image values above a certain threshold with OPS

imagej

#1

Hi everybody,

I’m trying to use ops to make some image processing. What I’d like to do for instance is a “half thresholded image” : keeping values above a threshold identical to the original image, and putting the other values to 0.

I tried this:

import net.imagej.ops.Op
import net.imglib2.type.numeric.real.FloatType
#@OpService ops
#@OUTPUT ImgPlus ramp2
#@OUTPUT ImgPlus rampTr

ramp = ops.run("create.img", [100, 100], new FloatType()) 
ramp = ops.image().equation(ramp, "p[0]") // creates a ramp image

// do not work
formula = "(image>10)*image" // keeps points above 10, zeros otherwise
rampTr = ops.eval(formula, ["image": ramp])

However this works:

formula = "image*image" // squares the image
ramp2 = ops.eval(formula, ["image": ramp])

Do you know if the thresholding is doable this way ? Should I use another op ? , like a map op ?

Any suggestions ?

Thanks!


Extract all pixels having certain value (IJ2 ops)
#2

You need to threshold your image with the desired threshold value, then multiply the resulting image with the original.

import net.imagej.ops.Op
import net.imglib2.type.numeric.real.FloatType
#@OpService ops
#@OUTPUT ImgPlus rampTr

ramp = ops.run("create.img", [100, 100], new FloatType()) 
ramp = ops.image().equation(ramp, "p[0]") // creates a ramp image

// I am sure there are nicer ways to do this, but the following works:
thresh = ops.threshold().apply(ramp, new FloatType(10));
thresh = ops.convert().float32(thresh);
rampTr = ops.run("multiply" , thresh,ramp);

#3

It would indeed be nice:

  • if the treshold.apply op could be used (in addition to creating a binary mask) to mask part of the image with leaving the remaining values intact, as well as set the thresholded pixels to some specified value; and
  • if the eval op would interpret this (image>10) type of boolean expression as a [0;1] multiplication factor.

@bnorthan has addressed this in the past:

See also:


#4

Thanks, indeed this would be really useful. I get these useful error message (thanks @ctrueden):

ava.lang.IllegalArgumentException: No matching 'logic.greaterThan' op

Request:
-	logic.greaterThan(
		ArrayImg,
		Integer)

Candidates:
1. 	(boolean result) =
	net.imagej.ops.logic.PrimitiveLogic$IntegerGreaterThan(
==>		int a,
		int b)
	Inconvertible type: net.imglib2.img.array.ArrayImg => int
2. 	(boolean result) =
	net.imagej.ops.logic.PrimitiveLogic$LongGreaterThan(
==>		long a,
		long b)
	Inconvertible type: net.imglib2.img.array.ArrayImg => long
3. 	(boolean result) =
	net.imagej.ops.logic.PrimitiveLogic$FloatGreaterThan(
==>		float a,
		float b)
	Inconvertible type: net.imglib2.img.array.ArrayImg => float
4. 	(boolean result) =
	net.imagej.ops.logic.PrimitiveLogic$DoubleGreaterThan(
==>		double a,
		double b)
	Inconvertible type: net.imglib2.img.array.ArrayImg => double
5. 	(BooleanType out) =
	net.imagej.ops.logic.BooleanTypeLogic$ComparableGreaterThan(
		BooleanType out,
		Comparable in1,
		Comparable in2)
	Not enough arguments: 2 < 3

A matcher between image and a number would be nice.

Or maybe even better, something than recognizes that when NO image vs number op exists but there’s a number vs number op, then the number vs number op is executed for each pixel.


#5

100% agreed. This is planned for the future, but the matcher is not smart enough to auto-map things yet.

There is another problem at the moment here, though: the existing logic ops are not currently functions or computers, but only vanilla ops. So you cannot map them right now.

It would be helpful if someone could go through this thread and file issues in ImageJ Ops according to all the discussion, since it seems like there are multiple different wishes here.