简体   繁体   English

ImageJ-使用插件链接两个图像的质心的绘制箭头

[英]ImageJ - Drawing arrows linking Centroids of Two Images using a Plugin

So I'm doing a small project for my job where I'm required to take two images, one of nucleuses and one of golgi bodies and link them up by arrows with the two centroids as the endpoints. 因此,我正在为我的工作做一个小项目,需要拍摄两张图像,一个是核,另一个是高尔基体,并通过箭头将两个质心作为端点链接起来。 I've been wracking my brain for sometime now, and here's the source in java for my plugin. 我已经动摇了一段时间,这是我的Java插件源代码。 It's got some errors apparently, and I'm new to both java and imagej, so please bear with me... thanks in advance... 显然有一些错误,我对java和imagej都是新手,所以请多多包涵...预先感谢...

So the idea was that once the measurements were read into a large array, I would then proceed to find the closest corresponding nucleus per golgi body, and then link them up. 因此,我的想法是,一旦将测量结果读入一个大阵列,我便会继续寻找每个高尔基体最接近的相应核,然后将它们链接起来。 To do this, I set up an array and found the minimum distance in that array, and then proceeded to draw it using a method that I found in someone else's plugin. 为此,我设置了一个数组并找到了该数组中的最小距离,然后继续使用在别人的插件中找到的方法进行绘制。

I should say that the results windows shows the x coordinates and y coordinates in two separate columns of a stack of images, one of which are about 1000 blue nucleuses, and 500 red golgi bodies, and the final column is the position in the stack. 我应该说结果窗口在一堆图像的两列中分别显示x坐标和y坐标,其中一列大约是1000个蓝色核和500个红色高尔基体,最后一列是堆栈中的位置。

I'm not quite sure what the issues are... I'm not understanding how drawing an image is done to the image processor... I've been reading some tutorials but I'm finding them relatively confusing... 我不太确定问题是什么...我不了解如何在图像处理器上绘制图像...我一直在阅读一些教程,但发现它们相对令人困惑...

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!

Since your code doesn't compile, it's hard to see what your issue is here without investing into some debugging. 由于您的代码无法编译,因此如果不进行一些调试就很难看到问题所在。

Let me add some suggestions: 让我添加一些建议:

  • Since you say you're new to both ImageJ and Java, you should read this introduction on the Fiji wiki (Fiji is a distribution of ImageJ that includes a lot of useful plugins targeted at life sciences) as well as Albert Cardona's great tutorial . 既然您说自己对ImageJ和Java都是陌生的,那么您应该在Fiji Wiki上阅读此介绍 (Fiji是ImageJ的发行版,其中包含许多针对生命科学的有用插件)以及Albert Cardona的出色教程

  • You are using PlugInFilter which is designed to process single images, ie ImageProcessor s. 您正在使用旨在处理单个图像(即ImageProcessorPlugInFilter Maybe using PlugIn would be more appropriate, since you are using multiple input images (or channels) and your output is yet in another image (although it might be in the same stack) 也许使用PlugIn会更合适,因为您正在使用多个输入图像(或通道)并且您的输出仍在另一个图像中(尽管它可能在同一堆栈中)

  • Your drawArrow method uses a low-level way to manipulate the output image (by the way you're handing over an ImagePlus where it expects an ImageProcessor , which will not work). 您的drawArrow方法使用一种低级方法来处理输出图像(通过您在需要ImageProcessorImagePlus上移交它的方式)。 An easier way would be to first perform your intended process within the GUI while recording the commands, then using these high-level commands in your plugin: 一种更简单的方法是在记录命令的同时先在GUI中执行预期的过程,然后在插件中使用以下高级命令:

    • Within Fiji/ImageJ, click on Plugins > Macros > Record... and, at the 'Record:' dropdown menu, select Plugin . 在Fiji / ImageJ中,单击Plugins > Macros > Record... ,然后在“记录:”下拉菜单中选择Plugin

    • Select the Arrow tool (right-click on the line selection tool), change the settings by double-clicking it, draw an arrow onto an open image, and finally add it to an Overlay via Image > Overlay > Add Selection... . 选择Arrow工具(在线选择工具上单击鼠标右键),双击以更改设置,在打开的图像上绘制箭头,最后通过Image > Overlay > Add Selection...将其添加到Overlay

    • By following these steps, you end up with the following code in the Recorder window, that can easily be used in your plugin without the need of dealing with any pixel arrays: 通过执行以下步骤,您将在Recorder窗口中获得以下代码,可以轻松在插件中使用以下代码,而无需处理任何像素数组:

IJ.run("Arrow Tool...", "width=2 size=10 color=black style=Filled");
        imp.setRoi(new Line(92, 184, 189, 131));
        IJ.run("Add Selection...", "");
  • You should be able to display the arrows in the overlay on top of your original image then. 然后,您应该能够在原始图像顶部的叠加层中显示箭头。

Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM