java 一堆图像上的 ImageJ 亮度和对比度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4473768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:33:06  来源:igfitidea点击:

ImageJ Brightness & Contrast over a stack of images

javaimage-processingimagej

提问by Magsol

I'm looking through a dataset set of images in ImageJ (a stack of .tif images, about 130 frames), and I have a problem with the dataset. It's a series of microscope images, with each frame being a plane about 3-4 micrometers above/below the previous one. As I go deeper into the dataset, light scattering makes for a brighter background, so the main features of the specimen are dimmer.

我正在查看 ImageJ 中的一组图像数据集(一堆 .tif 图像,大约 130 帧),但数据集有问题。这是一系列显微镜图像,每一帧都是一个比前一帧高/低约 3-4 微米的平面。当我深入研究数据集时,光散射使背景更亮,因此标本的主要特征变得更暗。

However, ImageJ's brightness and contrast feature uses a histogram that represents the entirestack of images. When I click "Auto" and "Reset" on an image deep in the stack, the resulting contrast is perfect: all the features light up really well. However, then, back at the start of the stack, most of the features have become saturated.

但是,ImageJ 的亮度和对比度功能使用表示整个图像堆栈的直方图。当我在堆栈深处的图像上单击“自动”和“重置”时,产生的对比度是完美的:所有功能都非常好。然而,回到堆栈的开始,大多数特征已经饱和。

I've tried manually extracting a few images from various points in the stack and performing Auto->Reset in Brightness & Contrast on each one individually and re-converting them to a stack afterwards, and it looks really solid. How can I do this programmatically (e.g. with a plugin) for the entire stack? What are the relevant API calls?

我尝试从堆栈中的各个点手动提取一些图像,并对每个图像分别执行自动->亮度和对比度重置,然后将它们重新转换为堆栈,它看起来非常可靠。我如何以编程方式(例如使用插件)为整个堆栈执行此操作?有哪些相关的 API 调用?

采纳答案by Mark Longair

A good way to start to write such a script is to use ImageJ's macro recorder - you can start this with Plugins > Macros > Record .... For this example, I'm assuming that you've switched the Record:option box to JavaScript, but if you're more familiar with the ImageJ macro language or writing plugins in Java one of the others might be a better choice. If you then open your image and use Image > Stacks > Set Slice ...and select (say) slice 20, you should see:

开始编写此类脚本的一个好方法是使用 ImageJ 的宏记录器 - 您可以从Plugins > Macros > Record .... 对于此示例,我假设您已将Record:选项框切换为JavaScript,但如果您更熟悉 ImageJ 宏语言或使用 Java 编写插件,那么其他之一可能是更好的选择。如果您随后打开图像并使用Image > Stacks > Set Slice ...并选择(例如)切片 20,您应该看到:

imp.setSlice(20);

... appear in the recorder. Now if you run Image > Adjust > Brightness/Contrast...and select Auto, you should see in the recorder that that's the equivalent of running Enhance Contrastkeeping 0.35% saturated pixels. The problem with this, as you've noted, is that this adjusts the minimum and maximum values for the entire stack rather than just that that slice. However, you can run Enhance Contrastwith different options by running Process > Enhance Contrast. The section on that option on the ImageJ documentation wikiexplains that if you want to change the pixel values rather than setting the minimum and maximum for the stack, you need to select the "Normalize" option. If I choose to do that instead, the macro recorder records:

...出现在录音机中。现在,如果您运行Image > Adjust > Brightness/Contrast...并选择Auto,您应该在记录器中看到这相当于运行Enhance Contrast保持 0.35% 的饱和像素。正如您所指出的,问题在于这会调整整个堆栈的最小值和最大值,而不仅仅是那个切片。但是,您可以通过运行Enhance Contrast以不同的选项运行Process > Enhance ContrastImageJ 文档 wiki上有关该选项的部分解释说,如果您想更改像素值而不是设置堆栈的最小值和最大值,则需要选择“标准化”选项。如果我选择这样做,宏记录器会记录:

imp.setSlice(20);
IJ.run(imp, "Enhance Contrast", "saturated=0.35 normalize");

... and you should see that only slice 20 has been altered. You can then wrap that in a loop that runs the same enhancement on every slice with:

...您应该看到只有切片 20 已被更改。然后,您可以将其包装在一个循环中,该循环在每个切片上运行相同的增强功能:

var imp = IJ.getImage();
var n = imp.getStackSize();

for( var i = 0; i < n; ++i) {
    imp.setSlice(i+1);
    IJ.run(imp, "Enhance Contrast", "saturated=4 normalize");
}

(If you're using Fiji, then the Script Editor (e.g. via File > New > Script) is an easy way to experiment with such scripts.)

(如果您使用的是斐济,那么脚本编辑器(例如通过File > New > Script)是试验此类脚本的简单方法。)

Of course, using the normalize option does result in the pixel values being altered, which means in this case that you're losing information, so I wouldn't use the resulting stack for quantitative results.

当然,使用 normalize 选项确实会导致像素值被更改,这意味着在这种情况下您会丢失信息,因此我不会将结果堆栈用于定量结果。

I hope that's of some use.

我希望这有点用。

回答by Adam Fraser

You might also consider using CellProfilerto process the images. Even if CP can't do exactly what you're trying to do directly, you can actually run ImageJ commands, plugins and macros from CP.

您也可以考虑使用CellProfiler来处理图像。即使 CP 不能完全执行您想要直接执行的操作,您实际上也可以从 CP 运行 ImageJ 命令、插件和宏。

At the very simplest, you could create a CP pipeline that just has LoadImages and RunImageJ.

最简单的是,您可以创建一个只有 LoadImages 和 RunImageJ 的 CP 管道。

回答by Miguel

The accepted answer is the best for the OP's question, but a small variant is if you want to change the brightness/contrast as a function of the slices of your specific data.

接受的答案最适合 OP 的问题,但一个小的变体是,如果您想将亮度/对比度更改为特定数据切片的函数。

In my case I wanted to have a threshold effect but the threshold value was changing in each slice of the stack. I went to a few different slices and manually found the threshold value. I then found an approximate function for Threshold value (Tv) as a function of the slice (s) as follows:

在我的情况下,我想要一个阈值效果,但阈值在堆栈的每个切片中都在变化。我去了几个不同的切片,手动找到了阈值。然后我找到了阈值 (Tv) 的近似函数作为切片 (s) 的函数,如下所示:

Tv=4000/s-17

Therefore, Then my script becomes:

因此,然后我的脚本变成:

importClass(Packages.ij.IJ);

var imp = IJ.getImage();
var n = imp.getStackSize();
var miny,maxy;

for( var i = 1; i < n+1; ++i) {
    imp.setSlice(i);
    miny=parseInt(4000/i-17);
    maxy=miny+5;
    IJ.setMinAndMax(imp, miny, maxy);
    IJ.run(imp, "Apply LUT", "slice");
}