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

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、创建一个图像(详细)

int width = 400;

int height = 400;

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", new ByteProcessor(400, 400)).show();

3、创建任意数量任何类型的

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

ImagePlus imp = IJ.createImage("My new image", "8-bit black", 400, 400, 1);

imp.show();

// or, without getting back a reference:

IJ.newImage("My new image", "8-bit black", 400, 400, 1);

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

ImagePlus imp = IJ.createImage("My new image", "RGB white", 400, 400, 10);

imp.show();

// again, without getting back a reference:

IJ.newImage("My new image", "RGB white", 400, 400, 10);

三、销毁图像

调用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 = new Roi(30, 40, 100, 100); //
x, y, width, height of the rectangle

ip.setRoi(roi);

ip.setValue(255);

ip.fill();

// fill an oval region with 255 (white color when grayscale LUT):

OvalRoi oroi = new OvalRoi(50, 60, 100, 150); //
x, y, width, height of the oval

ip.setRoi(oroi);

ip.setValue(255);

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(255);

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();

// rotate WITHOUT enlarging the canvas to fit

double angle = 45;

ip.setInterpolate(true); // bilinear

ip.rotate(45);

// rotate ENLARGING the canvas and filling the new areas with background color

double angle = 45;

IJ.run(imp, "Arbitrarily...", "angle=" + angle + " grid=1 interpolate enlarge");

// scale WITHOUT modifying the canvas dimensions

ip.setInterpolate(true); // bilinear

ip.scale(2.0, 2.0); // in X and Y

// scale ENLARGING or SHRINKING the canvas dimensions

double sx = 2.0;

double sy = 0.75;

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

for (int y=0; y<height; y++)
{

for (int x=0; x<width; x++)
{

// Editing pixel at x,y position

new_pixels[y * width + x] = ...;

}

}

// update ImageProcessor to new array

ip.setPixels(new_pixels);

}

// Replacing the pixel array but of different length: for example, to resize 2.5 times in width and height

int new_width = (int)(ip.getWidth() * 2.5);

int new_height = (int)(ip.getHeight() * 2.5);

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 ...

for (int y=0; y<height; y++)
{

for (int x=0; 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 学习第一篇

时间: 2024-10-12 23:07:44

Java图像处理最快技术:ImageJ 学习第一篇的相关文章

ImageJ 学习第一篇

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文件.J

C++的笔记学习第一篇,认识C++

在一个类中包含两种成员: 数据和函数,分别称为C++数据成员和成员函数. 关于类: 类是C++新增加的重要数据类型,有了类,就就可以实现面向对象程序设计方法中的封装.信息隐蔽.继承.派生.多态等功能. 关于函数的重载 在编程时,有时我们要实现的是同一类的功能,只是有些细节不同.例如希望从3个数中找出其中的最大者,而每次求最大数时数据的类型不同,可能是3个整数.3个双精度数或3个长整数. 程序设计者往往会分别设计出3个不同名的函数,其函数原型为:int max1(int a int b, int

Java学习第一篇---Java入门准备

这是我的第一篇博客,以后也会写自己学习Java的过程.一些知识点.心得体会等,以此鼓励自己坚持学习! 现在开始了我学习Java的生涯:[个人下载的Jdk版本是jdk-8u5-windows-x64] 1.安装之后的目录: ->Source Code: 安装这个选项将会安装Java所有核心类库的源代码 ->bin: 该路径下存放了JDK的各种工具命令,常用的Javac.java等命令. ->db: 该路径是安装Java DB的路径[DB(data base,数据库)是依照某种数据模型组织起

javaAgent和Java字节码增强技术的学习与实践

参考文章: https://www.cnblogs.com/chiangchou/p/javassist.html https://blog.csdn.net/u010039929/article/details/62881743 https://www.jianshu.com/p/0f64779cdcea [本文代码下载] 下载代码 [背景] 最近在工作中进行程序的性能调优时,想起之前同事的介绍的阿里的Java在线诊断工具 —— arthas,决定试用一下. 这玩意,是真的好用,能在对被检测程

Android基础学习第一篇—Project目录结构

写在前面的话: 1. 最近在自学Android,也是边看书边写一些Demo,由于知识点越来越多,脑子越来越记不清楚,所以打算写成读书笔记,供以后查看,也算是把自己学到所理解的东西写出来,献丑,如有不对的地方,希望大家给与指正. 2. 由于类似于读书笔记,可能格式神马的会比较随(hen)意(chou),大家看着受不了,可以使劲吐槽. *************************************我只是分割线***************************************

Golang学习-第一篇 Golang的简单介绍及Windows环境下安装、部署

序言 这是本人博客园第一篇文章,写的不到位之处,希望各位看客们谅解. 本人一直从事.NET的开发工作,最近在学习Golang,所以想着之前学习的过程中都没怎么好好的将学习过程记录下来.深感惋惜! 现在将Golang的学习点滴记录分享,废话到此,下面进入正文. 注:此文及以后所有内容中的开发平台为:Windows 开发工具为:JetBrains Gogland x64版本 官方下载地址为:https://www.jetbrains.com/go/download/#section=windows

从.Net到Java学习第一篇

以前我常说,公司用什么技术我就学什么.可是对于java,我曾经一度以为“学java是不可能的,这辈子不可能学java的.”结果,一遇到公司转java,我就不得不跑路了,于是乎,回头一看N家公司交过社保,连我自己都有点惊讶,居然有这么多家公司了.对于java的梗,这是有历史缘由的,大二的时候同一大波人去蓝杰参加java培训,当时一个空心的菱形怎么也写不出来,我写来写去就是一个实心的砖头,结果培训老师实在看不下去了,就说:“唉!你不适合搞java”,我看了下一同前去的几个同学一下子就都写出来了,搞得

Java学习第一篇 -- 安装JDK

1. 下载Oracle JDK        Oracle JDK:http://www.oracle.com/technetwork/java/javase/downloads/index.html 2. 在Windows中安装JDK        安装时请选择目录中不包含空格.中文等特殊字符以免出现未知错误.        假设安装目录:D:\Java\jdk1.8.0\        选择计算机->右击选择属性->高级系统设置->环境变量        方法一:          

Java学习第一篇 — 字符串

package StringTest; public class TestString { public static void main(String[] args){ // String str="aaaddd"; // String str2=str.substring(2,5); // System.out.println(str); // System.out.println(str2); //编译器做了优化,直接在编译的时候将字符串进行拼接 String str1=&quo