數據類型:
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的圖像剖析
當ImagePlus調用updateAndDraw()時重新創建 java.awt.Image對象。 如果你想改變被反映當前顯示在屏幕上的圖像, 必須修改的像素之后調用updateAndDraw()。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)時被更新。
二、創建圖像
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");2、通過FileSaver類ImagePlus imp = ...
new FileSaver(imp).saveAsTiff( "/path/to/image.tif");該FileSaver類有更多的選擇:saveAsTiffStack,saveAsJpeg,saveAsPng,saveAsGif ...等。
這算是ImageJ入門第一篇,介紹一些基本操作,它的擴張機制和實現方式都很值得研究。希望更多的人參與進來。
