如何测量背景上彩色区域的百分比? ImageJ的?

时间:2018-06-12 22:27:06

标签: image-processing imagej

我想测量这张灰色地图紫色区域的百分比。

enter image description here

我可以粗略地说,代表10%的区域,但我需要一个确切的值。

我知道有一个名为ImageJ的免费工具,但我不知道如何使用它。

也许您可以建议我使用其他工具或如何执行此类任务。

提前致谢。

1 个答案:

答案 0 :(得分:2)

您可以为该任务编写一个小型ImageJ插件:

import ij.gui.DialogListener;
import ij.gui.GenericDialog;
import ij.plugin.filter.ExtendedPlugInFilter;
import ij.plugin.filter.PlugInFilterRunner;
import ij.process.ImageProcessor;
import ij.IJ;
import ij.ImagePlus;
import java.awt.AWTEvent;
import java.awt.Label;
import java.lang.Math;

public class Purple_Counter implements ExtendedPlugInFilter, DialogListener{
    private final int FLAGS = DOES_RGB | PARALLELIZE_STACKS;
    private boolean preview = true;
    private ImagePlus im;
    private int count;
    private double total;
    private int color = 0xff64318a;
    private int background = 0xffd7d7d7;
    private double maxDistanceColor;
    private double maxDistanceBckg ;

    public int setup(String args, ImagePlus im){
        this.im = im;
        maxDistanceColor = 60;
        maxDistanceBckg = 60;
        return FLAGS;
    }

    public void run(ImageProcessor ip){
        int height = ip.getHeight();
        int width = ip.getWidth();
        count = 0;
        total = 0;
        for(int a = 0; a < height; a++){
            for(int b = 0; b < height; b++){
                int p = ip.getPixel(a,b);
                if ( calculateDistance(p,color) < maxDistanceColor){
                    count++;
                    ip.putPixel(a,b,0xffff0000);
                }
                if ( calculateDistance(p,background) < maxDistanceBckg){
                    total++;
                    ip.putPixel(a,b,0xff000000);
                }
            }
        }
        IJ.log("Counted: " + count + "| Total: " + total);
        IJ.log("Percentage: " +  (count/total) * 100f);
        IJ.log("");
    }

    private double calculateDistance(int color1, int color2){
        int red1 = (color1 >> 16)&0xff;
        int red2 = (color2 >> 16)&0xff;
        int green1 = (color1 >> 8)&0xff;
        int green2 = (color2 >> 8)&0xff;
        int blue1 = color1 & 0xff;
        int blue2 = color2 & 0xff;
        double distance = Math.sqrt((red1 * red1 - 2*red1*red2 + red2*red2) + (green1 * green1 - 2*green1*green2 + green2*green2) + (blue1 * blue1 - 2*blue1*blue2 + blue2*blue2));
        return distance;
    }

    public int showDialog(ImagePlus imp, String Command, PlugInFilterRunner pfr){
        //Dialog to control the used color distances
        GenericDialog gd = new GenericDialog("Distance Settings");
        gd.addMessage("Please chose maximal distances to identify POI and background pixels: ");
        gd.addSlider("POI Red: ", 0,255,0x64);
        gd.addSlider("POI Green: ", 0,255,0x31);
        gd.addSlider("POI Blue: ", 0,255,0x8a);
        gd.addSlider("BCKG Red: ", 0,255,0xd7);
        gd.addSlider("BCKG Green: ", 0,255,0xd7);
        gd.addSlider("BCKG Blue: ", 0,255,0xd7);
        gd.addSlider("POI max. Distance: ", 0.001, 1000, maxDistanceColor);
        gd.addSlider("BCKG max. Distance: ", 0.001, 1000, maxDistanceBckg);
        gd.addPreviewCheckbox(pfr, "Preview");
        gd.addDialogListener(this);
        gd.showDialog();

        if(gd.wasCanceled() ||!dialogItemChanged(gd, null)){
            return DONE;
        }
        return IJ.setupDialog(imp, FLAGS);
    }

    public boolean dialogItemChanged(GenericDialog gd, AWTEvent e){
        int alpha = 0xff;
        int colorRed = (int)gd.getNextNumber();
        int colorGreen = (int)gd.getNextNumber();
        int colorBlue = (int)gd.getNextNumber();
        int bckgRed = (int)gd.getNextNumber();
        int bckgGreen = (int)gd.getNextNumber();
        int bckgBlue = (int)gd.getNextNumber();
        color = (alpha << 24 | colorRed << 16 | colorGreen << 8 | colorBlue);
        background = (alpha << 24 | bckgRed << 16 | bckgGreen << 8 | bckgBlue);
        maxDistanceColor = gd.getNextNumber();
        maxDistanceBckg = gd.getNextNumber();
        return true;
    }

    public void setNPasses(int nPasses){
        //Has to be implemented for ExtendedPlugInFilter
    }
}

此插件将打开以下对话框: Image of the dialog window with different sliders to specify the POI color, the background color and the used distances

此对话框允许设置感兴趣的像素(POI)颜色以及背景(bckg)颜色.Via手动设置距离,可以决定插件确定为POI或背景的内容。 参考颜色如下:

POI: Image of the color

背景: Image of the color

要确认您使用的是正确的距离设置,我建议您使用预览功能。使用它时,ImageJ会将它认为是POI红色的每个像素着色,而每个背景像素都将涂成黑色。我使用对话框中给出的设置获得了以下结果:

Processed version of the image given by the author of the question. Background pixels are colored black, whilst pixels of interest are colored red. Image of the plugin output with the calculated percentage of POI pixels

如您所见,由于伪像,一些白色像素也被视为背景。此外,文本被视为背景,因此我建议在使用插件之前将其删除。如果摆脱它,结果会略微变为4.2%左右。