【问题标题】:ImageJ - Drawing arrows linking Centroids of Two Images using a PluginImageJ - 使用插件绘制连接两个图像质心的箭头
【发布时间】:2013-02-14 00:06:54
【问题描述】:

所以我正在为我的工作做一个小项目,我需要拍摄两张图像,一张是细胞核,一张是高尔基体,并用两个质心作为端点的箭头将它们连接起来。一段时间以来,我一直在绞尽脑汁,这是我插件的 java 源代码。它显然有一些错误,而且我对 java 和 imagej 都是新手,所以请多多包涵......提前谢谢......

所以我的想法是,一旦将测量值读入一个大数组,我就会继续找到每个高尔基体最接近的对应核,然后将它们连接起来。为此,我设置了一个数组并在该数组中找到了最小距离,然后使用我在其他人的插件中找到的方法继续绘制它。

我应该说结果窗口在一堆图像的两个单独列中显示 x 坐标和 y 坐标,其中一个是大约 1000 个蓝色核和 500 个红色高尔基体,最后一列是位置堆栈。

我不太确定问题出在哪里...我不明白图像处理器是如何绘制图像的...我一直在阅读一些教程,但我发现它们相对混乱。 ..

import ij.*;
import ij.process.*;
import ij.gui.*; 
import java.awt.*;
import java.util.Arrays;
import java.util.Collections;
import ij.plugin.*;
import ij.plugin.filter.*;
import ij.measure.*;

public class CentroidFinder_ implements PlugInFilter {
     protected ImageStack cellstack;
     ImagePlus[] cellImages = cellstack.getImageArray();
     ImagePlus arrowImage = arrowImage.createImage("ArrayFile", 1600,1200,1);

     ResultsTable rt = Analyzer.getResultsTable();
     public int setup(String arg, ImagePlus imp) {
    cellstack = imp.getStack();

    this.imp = imp;
    return STACK_REQUIRED;
 }

public void run(ImageProcessor ip) 
{
    int[] blueCentroidsX = {};
    int[] blueCentroidsY = {};
    int[] redCentroidsX = {};
    int[] redCentroidsY = {};
    int xColumnIndex = rt.getColumnHeading("X");
    int yColumnIndex = rt.getColumnHeading("Y");
    int sliceNumberIndex = rt.getColumnHeading("Slice");


    float[] sliceCategoryPerRow = (rt.getColumn(sliceNumberIndex));

    for (int counter = 0; counter < sliceCategoryPerRow.Length; counter++)
    {
        if (sliceCategoryPerRow[counter] == 1)
        {
            blueCentroidsX[counter] = (int)(rt.getValueAsDouble(xColumnIndex, counter)); //This might be a source of error
            blueCentroidsY[counter] = (int)(rt.getValue(yColumnIndex, counter));
        }
        if (sliceCategoryPerRow[counter] == 2)
        {
            redCentroidsX[counter] = (int)rt.getValue(xColumnIndex, counter); //This might be a source of error
            redCentroidsY[counter] = (int)rt.getValue(yColumnIndex, counter);
        }
    }
    if ((blueCentroidsX.length + redCentroidsX.length) =! sliceCategoryPerRow.length)
    {
        error ("Error Message", "Something is wrong with the columns");
    }

    boolean blueIsBigger = true;

    if (blueCentroidsX.length < redCentroids.length)
        blueIsBigger = false;

    int[][] startingArrow = {};
    int[][] endingArrow = {};
    int[][] tempDistance = {};
    int counterTag;
    float[] distanceList = {};
    for (int j = 0; j < redCentroidsX.length; j++)
    {
        for (int k = 0; k < blueCentroidsX.length; k++)
        {
            tempDistance = distance (redCentroidsX[j], redCentroidsY[j], 
                                   blueCentroidsX[k], blueCentroidsY[k]);
            if (throwAwayDistance (tempDistance))
                continue;
            distanceList = distanceList.addAll({tempDistance, k});
        }
        if (distanceList.length == 0)
        {
            break;
        }
        counterTag = 0; 
        for (int l = 1; l < distanceList.length; l++)
        {
            if ((distanceList[l][0] < distanceList[l-1][0]))
                counterTag = distanceList[l][1];
        }
        startingArrow = startingArrow.addAll(({(int)blueCentroidsX[counterTag],
                                         (int)blueCentroidsY[counterTag])});
        endingArrow = add(endingArrow, {(int)redCentroidsX[j], int()redCentroidsY[j]});
    }
    if ((startingArrow.length != endingArrow.length)
        error ("Error Message", "Something has caused there not to be equal coordinates");

    for (int m = 0; m < startingArrow.length; m++)
    {
        for (int n = 0; n <endingArrow.length; n++)
        {
            drawArrow (imp, startingArrow[m][0], startingArrow[m][0],
                        endingArrow[n][0], endingArrow[n][1], 1)
        }
    }



stack.addSlice(arrowImage);

public void drawArrow(ImageProcessor ip, int x1, int y1, int x2, int y2, double size) 
{
    double dx = x2-x1;
    double dy = y2-y1;
    double ra = java.lang.Math.sqrt(dx*dx + dy*dy);
    dx /= ra;
    dy /= ra;
    int x3 = (int)Math.round(x2-dx*size);
    int y3 = (int)Math.round(y2-dy*size);
    double r = 0.3*size;
    int x4 = (int)Math.round(x3+dy*r);
    int y4 = (int)Math.round(y3-dx*r);
    int x5 = (int)Math.round(x3-dy*r);
    int y5 = (int)Math.round(y3+dx*r);
    ip.moveTo(x1, y1); ip.lineTo(x2, y2);
    ip.moveTo(x4,y4); ip.lineTo(x2,y2); ip.lineTo(x5,y5);
}
//Mathematical Functions:

public boolean throwAwayDistance (float distance)
{
    if (distance >= 25.0)
        return true;
    else return false;
}

public float distance (x1,y1,x2,y2)
{
    int length;
    return length = (((x1-x2)^2 + (y1-y2)^2)^(.5));
}   

}

Thank you all for all your help!

【问题讨论】:

  • 您能否提供一些示例图片来说明您想要做什么?
  • 代码一团糟。由于多种原因,它无法编译。你应该看一些java教程来获得基础知识。例如,java 中的数组在你使用它们时根本就不起作用。

标签: java arrays imaging imagej


【解决方案1】:

由于您的代码无法编译,因此如果不进行一些调试,就很难看出您的问题所在。

让我补充一些建议:

  • 既然您说您是 ImageJ 和 Java 的新手,您也应该阅读 Fiji wiki 上的 this introduction(Fiji 是 ImageJ 的一个发行版,其中包含许多针对生命科学的有用插件)作为 Albert Cardona 的伟大 tutorial

  • 您正在使用PlugInFilter,它旨在处理单个图像,即ImageProcessors。也许使用PlugIn 会更合适,因为您正在使用多个输入图像(或通道)并且您的输出还在另一个图像中(尽管它可能在同一个堆栈中)

  • 您的drawArrow 方法使用低级别的方式来操作输出图像(顺便说一下,您在需要ImageProcessor 的地方移交ImagePlus,这将不起作用)。一种更简单的方法是首先在 GUI 中执行您的预期过程,同时记录命令,然后在您的插件中使用这些高级命令:

    • 在 Fiji/ImageJ 中,单击 Plugins &gt; Macros &gt; Record...,然后在“记录:”下拉菜单中选择 Plugin

    • 选择Arrow工具(右击选线工具),双击更改设置,在打开的图像上画一个箭头,最后通过Overlay添加Image &gt; Overlay &gt; Add Selection...

    • 按照这些步骤,您最终会在“记录器”窗口中得到以下代码,无需处理任何像素数组即可在插件中轻松使用该代码:

IJ.run("箭头工具...", "width=2 size=10 color=black style=Filled"); imp.setRoi(new Line(92, 184, 189, 131)); IJ.run("添加选择...", "");
  • 然后,您应该能够在原始图像顶部的叠加层中显示箭头。

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-27
    相关资源
    最近更新 更多