Java图像处理最快技术:ImageJ 学习第一篇

2023-05-30,,

ImageJ是世界上最快的纯Java的图像处理程序

它能够过滤一个2048x2048的图像在0.1秒内(*)。

这是每秒40万像素!ImageJ的扩展通过使用内置的文本编辑器和Java编译器的ImageJ的开发插件。500多插件可用。

数据类型:8位灰度或索引色,16位无符号整数,32位浮点和RGB色彩。

文件格式:读写全部支持的数据类型为TIFF(非压缩)或原始数据。

打开和保存GIF,JPEG,BMP,PNG。PGM,FITS和ASCII。打开DICOM。使用URL打开的TIFF、GIF文件、JPEG文件、DICOMs和原始数据。也能够扩展很多其它格式 的插件。

图像增强:支持平滑。锐化,边缘检測。中值滤波和阈值的8位灰度和RGB彩色图像。

交互方式调整亮度和8位,16位和32位图像的对照度。

几何操作:裁剪,缩放。调整大小和旋转。翻转垂直或水平。

分析:測量面积。平均值,标准偏差,最小的选择和最大或整个图像。

測量长度和角度。使用现实世界中的度量单位。如毫米。校准使用密度标准。生成柱状图和剖面图。

色彩处理:分裂一个32位彩色图像转换成RGB或HSV分量。

合并8位组件成彩色图像。RGB图像转换为8位索引颜色。应用伪彩色调色板为灰度图像。

基于ImageJ的项目有、CellProfiler(细胞图像分析)、idoimaging(医学影像)、ImageSurfer(3D可视化和分析)、MIPAV(3D成像和可视化)、NITRC(神经影像学工具和资源)等。

以下对ImageJ的编程基础介绍一下。

一、ImageJ的图像剖析

ImageJ的 图像由三个部分组成:
1、ImageProcessor对象实例:持有并提供了訪问像素的方法。
2、Image对象实例:即java.awt.Image画在屏幕上。

3、ImagePlus对象实例:包括全部的元数据(标题,属性)、ImageProcessor和Image。
ImageJ的 图像堆栈由四部分组成:
1、ImageStack对象实例:持有像素阵列的阵列(LUT变化通过暂时实例StackProcessor)
2、Image对象实例:即java.awt.Image画在屏幕上。

3、ImageProcessor对象实例:提供訪问当前切片像素。

4、ImagePlus对象实例:持有ImageStack、ImageProcessor和Image。

使用堆栈时,要谨记以下几点:

1、ImagePlus的ImageProcessor实例在不论什么调用setSlice(INT)时都由它的像素替换对象。
2、ImageStack.getProcessor(int)在每次调用时都返回一个新的ImageProcessor。是 一个消耗大的操作。

3、ImagePlus的java.awt.Image中在每次调用setSlice(int)时被更新。

当ImagePlus调用updateAndDraw()时又一次创建 java.awt.Image对象。假设你想改变被反映当前显示在屏幕上的图像,必须改动的像素之后调用updateAndDraw()。

二、创建图像
    1、创建一个图像(具体)

;  
;  
ImageProcessor ip = new ByteProcessor(width, height);  
String title = "My new image";  
ImagePlus imp = new ImagePlus(title, ip);  
imp.show();  

    有几个ImageProcessor类,每一个都有自己专门的构造函数。ByteProcessor,ShortProcessor,FloatProcessor和ColorProcessor。
    2、创建一个图像(简单方式)

        new ImagePlus("My
new image", , )).show(); 

    3、创建随意数量不论什么类型的

         A、一个简单的8位的400x400像素的灰度图像

ImagePlus imp , , );
imp.show();
// or, without getting back a reference:
IJ.newImage(, , );

B、堆栈的400×400像素的10色图片

ImagePlus imp , , );
 
imp.show();  
// again, without getting back a reference:  
IJ.newImage(, , ); 

三、销毁图像

调用flush()将释放所使用的ImagePlus全部内存资源。

ImagePlus imp = ...  
imp.flush();  

注意:假设你持有一个从ImagePlus.getProcessor()方法获得ImageProcessor。即ImageProcessor的像素数组指针将被设置为null。

你应该改为调用ImageProcessor的duplicate()。或直接通过getPixels()得到它的像素。并把它们存储在相同的尺寸的新ImageProcessor。

相同,java.awt.Image中获取自己的flush()方法调用也是如此。

四、打开图像
    全部方法都环绕着ij.io.Opener类展开。

    1、高层次的方式,从文件或URL

ImagePlus imp = IJ.openImage("/path/to/image.tif");  
imp.show();  
  
ImagePlus imp = IJ.openImage("http://www.example.org/path/to/image.tif");  
imp.show();  
  
// Without getting back a pointer, and automatically showing it:  
IJ.open("/path/to/image.tif");  
// Same but from an URL  
IJ.open("http://www.example.org/path/to/image.tif"); 

    2、从文件打开

Opener opener = new Opener();  
ImagePlus imp = opener.openImage("/path/to/image.tif");  
imp.show();  

    3、从URL打开

Opener opener = new Opener();  
ImagePlus imp = opener.openImage("http://www.example.org/path/to/image.tif");  
imp.show(); 

以上注意URL 包括http://怎样的自己主动检測并正确解析。假设须要,能够直接调用:

ImagePlus imp = opener.openURL("http://www.example.org/path/to/image.tif");  

五、编辑像素

1、执行ImageJ命令方式,这是一个高层次的方法,像素能够通过调用ImageJ的命令编辑图像:

ImagePlus imp = ...  
// Making a binary image  
IJ.run(imp, "Convert to Mask", ""); // "" means no arguments  
  
// Resizing, opens a copy in a new window (the 'create' command keyword)  
IJ.run(imp, "Scale...", "x=0.5 y=0.5 width=344 height=345 interpolate create title=[Scaled version of " +imp.getTitle() + "]");
 
  ...  

不论什么ImageJ命令可能被应用。

你能够找出哪些命令来使用,哪些參数通过执行插件,并手动调用的ImageJ打开的图像上的菜单命令。

2、中级层次编辑方式:ImageProcessor(ROIs/selections)
在图像上绘制或填充ROI(感兴趣区域):

ImagePlus imp = ...  
ImageProcessor ip = imp.getProcessor();  
  
// Assuming 8-bit image  
  
// fill a rectangular region with 255 (on grayscale this is white color):  
Roi roi , , , ); //
x, y, width, height of the rectangle  
ip.setRoi(roi);  
ip.setValue();  
ip.fill();  
  
// fill an oval region with 255 (white color when grayscale LUT):  
OvalRoi oroi , , , ); //
x, y, width, height of the oval  
ip.setRoi(oroi);  
ip.setValue();  
ip.fill(ip.getMask()); // notice different fill method  
                       // regular fill() would fill the entire bounding box rectangle of the OvalRoi  
// The method above is valid at least for PolygonRoi and ShapeRoi as well.  
  
  
// draw the contour of any region with 255 pixel intensity  
Roi roi = ...  
ip.setValue();  
ip.draw();  
  
// update screen view of the image  
imp.updateAndDraw();  

3、ROIs的一些事情:
A、有非常多selection/ROI类型:Roi(矩形之中的一个。也是全部其它类型的父类),Line, OvalRoi, PolygonRoi, PointRoi, FreehandRoi, ShapeRoi, TextRoi。

另外有一些子类型。如PolygonRoi里的POLYGON、POLYLINE 类型。

B、大部分的ROI是用于编辑图像非常实用; 一些用于图像分析(Line。PointRoi。TextRoi)。
C、最强大的ROI是ShapeRoi:java.awt.geom.GeneralPath支持它,它能够存储随意数量的不论什么形状的不连续区域的。
D、ip.fill(ip.getMask())方法是最安全的,可在各种场合使用,仅仅须要检查ImageProcessor的mask通过getMask()返回的不为null。

旋转。翻转和缩放图像(或者ROI)

ImagePlus imp = ...  
ImageProcessor ip = imp.getProcessor();  
  
ip.flipHorizontal();  
  
ip.flipVertical();  
  
ip.rotateLeft();  
  
ip.rotateRight();  
  
;  
ip.setInterpolate(true); // bilinear  
ip.rotate();  
  
;  
IJ.run(imp, "Arbitrarily...", "angle=" + angle + " grid=1 interpolate enlarge");  
  
// scale WITHOUT modifying the canvas dimensions  
ip.setInterpolate(true); // bilinear  
ip.scale(., .); // in X and Y  
  
.;  
.;  
int new_width = (int)(ip.getWidth() * sx);  
int new_height = (int)(ip.getHeight() * sy);  
ip.setInterpolate(true); // bilinear  
ImageProcesor ip2 = ip.resize(new_width, new_height); // of the same type as the original  
imp.setProcessor(imp.getTitle(), ip2); // UPDATE the original ImagePlus  
  
// update screen view of the image  
imp.updateAndDraw();  

ImageProcessor类提供了绘制线条、文字和点等。看看在ImageProcessor的API。

4、低层次的编辑方式:像素数组

ImagePlus imp = ...  
ImageProcessor ip = imp.getProcessor();  
  
// Editing the pixel array  
if (imp.getType() == ImagePlus.GRAY8) {  
    byte[] pixels = (byte[])ip.getPixels();  
    // ... do whatever operations directly on the pixel array  
}  
  
// Replacing the pixel array: ONLY if same size  
if (imp.getType() == ImagePlus.GRAY8) {  
    int width = ip.getWidth();  
    int height = ip.getHeight();  
    byte[] new_pixels = new byte[width * height];
 
    // set each pixel value to whatever, between -128 and 127  
    ; y<height; y++)
{  
        ; x<width; x++)
{  
            // Editing pixel at x,y position  
            new_pixels[y * width + x] = ...;  
        }  
    }  
    // update ImageProcessor to new array  
    ip.setPixels(new_pixels);  
}  
  
.);
 
.);
 
ImageProcessor ip2 = ip.createProcessor(new_width, new_height); // of same type  
imp.setProcessor(imp.getTitle(), ip2);  
  
if (imp.getType() == ImagePlus.GRAY8) {  
    byte[] pix = (byte[])imp.getProcessor().getPixels(); // or ip2.getPixels();  
    // .. process pixels ...  
    ; y<height; y++)
{  
        ; x<width; x++)
{  
            // Editing pixel at x,y position  
            new_pixels[y * width + x] = ...;  
        }  
    }  
}  
  
// DON'T forget to update the screen image!  
imp.updateAndDraw();  

假设要显示的ImagePlus,更新图像仅仅有必须的,

六、保存图像

1、高层次的方式

ImagePlus imp = ...  
IJ.saveAs(imp, "tif", "/path/to/image.tif");  
  
// or by using the file format extension:  
IJ.save(imp, "/path/to/image.tif");

    
非常多格式都支持。

在IJ类里搜索方法"saveAs"
2、通过FileSaver类

ImagePlus imp = ...  
new FileSaver(imp).saveAsTiff("/path/to/image.tif"); 

该FileSaver类有很多其它的选择:saveAsTiffStack。saveAsJpeg,saveAsPng。saveAsGif ...等。

这算是ImageJ入门第一篇,介绍一些基本操作,它的扩张机制和实现方式都非常值得研究。希望很多其它的人參与进来。

Java图像处理最快技术:ImageJ 学习第一篇的相关教程结束。

《Java图像处理最快技术:ImageJ 学习第一篇.doc》

下载本文的Word格式文档,以方便收藏与打印。