Outlier removal not sticking

Hi everybody,

I’m new to using ImageJ for my work and have been really impressed by it. However, I’m having one small issue.

Whenever I remove outliers, I click okay and they’re gone, great.But, as soon as I try to adjust colour thresholds the outlier removal completely disappears. I want to apply the colour threshold adjustment after the outlier removal.

The only work around I have is to save the image after outlier removal and then start again, but that means that I won’t be able to create a macro for my process.

Essentially, the goal is to measure the area of meat (red). The image needs adjusting as the fine bits of fat within the meat are not an issue, we’re looking for the main red area. Also there is a gloss/sheen to the meat which picks up as bright (as the fat does) hence the need for removing those as outliers. What I want was possible, it just required me to save and reopen.

Many thanks.

Good day,

sorry but in order to help you we need a MWE that reproduces the problem.

  1. Please post a small image (in th eoriginal TIF- or PNG-format) for which the effect is clearly visible and describe in detail and step by step what you are doing and what went wrong in your opinion.

  2. Furthermore, you can post the image you want to process and tell us what you want to achieve in the end. Perhaps there are ways to do it differently or even better.

  3. Please don’t mix 1. and 2.

Regards

Herbie

Hi Herbie, thanks for the response. I’ve changes the description so hopefully this is now better.

Thanks again.

Thanks for the image which of course is a screen shot and the image originally was JPG-compressed which is a no-no for any kind of scientific image evaluation.

Anyhow, I can’t confirm the described problem:

Perhaps we should concentrate on my point 2. and you explain what you like to achieve in the end.

Regards

Herbie

As you say this is a relatively now project for you, if you’re interested in solutions in other software, CellProfiler can pretty easily identify and measure the red areas and if you turn on “hole filling” you wouldn’t need to bother removing the small bits of fat (you can turn it off if you DO want to exclude them). Here’s the very beginnings of a pipeline, but it would of course need to be tuned by you to your original images (not screenshots- and as @anon96376101 wisely said, please do avoid JPGs!).

If you prefer to stick with ImageJ (always understandable, as it’s a great program that has a lot of other advantages), best of luck and hopefully your issue is quickly resolved!

Meat.cppipe (8.9 KB)

Excuse me Beth,

but as long as we don’t know what the OP likes to obtain it is premature to make any suggestions. Presently, it is not even clear why the OP uses “Remove Outliers” and what should come after this operation, especially since Color Thresholding is a tricky operation.

My present feeling is that the OP isn’t really interested in scientific image processing/evaluation but in image cosmetics. But time will perhaps tell …

Best

Herbie

The OP said they are interested in measuring the area of the meat.

OK, Beth the OP added this information later which is not the correct way of posting.

Of course the red meat area can be obtained with other means as well.

Thanks for pointing me to the later added information of the OP

Herbie

Apologies for adding the detail to the description.

I am removing the outliers due to the sheen of the moisture in the meet which. These bits are picked up as white and whilst individually very small, add up to a significant area of the red section.

Thanks for your reply!

I shall post an approach that works without “Color Threshold” and any other manually set parameters. One problem will remain and tha’s the bone on the left top that most likely will be included with the area measurement.

Regards

Herbie

Finally I’m able to present an ImageJ-macro that should do what you want and it definitely does for the provided sample image:

Please note that you first need to install the ImageJ-plugin “RGB_to_CMYK.class” that you can download from here: https://imagej.nih.gov/ij/plugins/cmyk/index.html

Here is the macro code:

// imagej-macro "fleshAndFat" (Herbie G., 17. Dec. 2018)
requires( "1.52i" );
updateResults();
setBackgroundColor(0, 0, 0);
setOption("BlackBackground", true);
orig=getImageID;
setBatchMode(true);
run("Duplicate...", "title=cpy");
run("RGB to CMYK");
stck=getTitle();
run("Make Substack...", "channels=3");
resetMinAndMax();
ch3=getTitle();
close(stck);
setAutoThreshold("Li dark");
run("Convert to Mask");
doWand(0, 0.5*getHeight());
run("Fill Holes");
area("Total Area");
selectImage("cpy");
run("Restore Selection");
close(ch3);
run("Make Inverse");
run("Set...", "value=255");
run("Select None");
run("8-bit");
setAutoThreshold("Default dark");
run("Convert to Mask");
run("Invert");
run("Fill Holes");
run("Analyze Particles...", "size=1000-Infinity add");
roiManager("combine");
roiManager("Add");
roiManager("select", roiManager("count")-1);
area("Red Area");
selectImage(orig);
run("Restore Selection");
close("cpy");
run("Add Selection...");
run("Select None");
setBatchMode(false);
exit();
function area(col) {
   getRawStatistics(N, mean);
   if (lengthOf(col)<10) re=1; else re=0;
   setResult(col, nResults-re, (N*mean/255));
}
// imagej-macro "fleshAndFat" (Herbie G., 17. Dec. 2018)

Paste the above macro code to an empty macro window (Plugins >> New >> Macro) and run it with an image open in ImageJ.

The Results table gives you the total area (here in blue: 419108 pixel^2) of the piece and the area of red meat (bone parts included) (here in green: 271709 pixel^2). The latter area is outlined as an overlay that can either be hidden or deleted or may be flattened to appear permanently imprinted onto the image.

Please report if it works for you.

HTH

Herbie

Wow that’s a nice elegant solution. steak%20outline It pretty much worked for me, but with some differences:

It reported a “total area” of 419433 and a “red area” of 271708. So similar to you numbers.

The green boundary was actually in yellow and the blue boundary was non-existent. I checked and there were no hidden overlays.

I added the blue contour for illustration only. It is not actually drawn by the macro!
The color of the red meat contour depends on your default setting and this is yellow.

The slight differences in the area measurements are due to the fact that you used your image and I had to extract the top image from the screenshot compilation in your first post. Consequently, your and my image will differ slightly.

Here is a streamlined macro code:

// imagej-macro "fleshAndFat" (Herbie G., 17./18. Dec. 2018)
requires( "1.52i" );
updateResults();
setOption("BlackBackground", true);
orig=getImageID;
setBatchMode(true);
run("Duplicate...", "title=cpy");
run("RGB to CMYK");
run("8-bit");
setSlice(3);
resetMinAndMax();
setAutoThreshold("Li dark");
run("Convert to Mask", "method=Li background=Dark only black");
run("Fill Holes", "slice");
doWand(0, 0.5*getHeight());
area("Total Area",0);
olay(orig);
selectImage("cpy");
run("Restore Selection");
run("8-bit");
setAutoThreshold("Default");
run("Convert to Mask");
run("Fill Holes");
run("Analyze Particles...", "size=1000-Infinity add");
roiManager("combine");
roiManager("Add");
roiManager("select", roiManager("count")-1);
area("Red Area",1);
olay(orig);
run("Overlay Options...", "stroke=blue width=1 fill=none apply");
setBatchMode(false);
exit();
function area(col,rw) {
   getRawStatistics(N, mean);
   setResult(col, nResults-rw, round(N*mean/255));
}
function olay(img) {
   selectImage(img);
   run("Restore Selection");
   run("Add Selection...");
   run("Select None");
}
// imagej-macro "fleshAndFat" (Herbie G., 17./18. Dec. 2018)

For my posted sample image it gives me a total area of 419313 pixel^2 and an area of red meat of 271709 pixel^2.

Regards

Herbie

Fair enough, makes sense.

In which case… many many thanks for this. It’s a far more efficient and accurate solution than I would have come up with.

Glad to hear that the macro works as desired!

Three remarks:

  1. Robustness of the area evaluation can be increased if the shadows from the illumination are decreased. Ideally, the illumination should be done by a ring-light around the camera optics.
  2. As you may have realized, the macro doesn’t make use of the Color Threshold functionality thereby avoiding manually set thresholds. Automatic threshold schemes applied to achromatic images are used instead. Automatic thresholds adapt to the individual gray value statistics of an image, i.e. they generalize. The schemes differ in the way they compute the threshold from the individual image statistics. If you are unhappy with some results, you should play with the available automatic schemes but never set thresholds manually.
  3. The Analyze Particles operation excludes red areas that are smaller than 1000 pixels^2. This value may be changed to a size that perhaps better fits your needs.

Regards

Herbie

Thanks Herbie,

This was a stock photo I found online, I’ve also ran the macro against another 3 images I found online and it performed well against all of them.

When I take my own images I will be aware of the lighting. That’s where the blue outline would come in use so I can see that it hasn’t picked up any shadows. May I ask what you ran to do that? I tried a few things and can do it in photoshop, but didn’t get anything as accurate as you did in ImageJ.

I will also include a reference object so I can convert the area in pixels to a real world measure. I will of course have to check if your macro picks up these objects in the calculation too.

Would you accept if both contours are in blue?

I’ve updated today’s macro code accordingly.

Concerning scale, you normally should use the scale-setting feature of ImageJ. If you include a reference bar of known length (no ruler but a simple high contrast bar) at a defined image position, the scale can automatically be set by an addition to the macro. Maybe some further changes of the macro are required to get the areas in scaled units, but it is possible.

If you are starting with the real stuff please post an image with scale bar and we shall see!

Regards

Herbie

Blue’s great, the colour doesn’t make a difference, it just helps to be able to assess visually to make sure the right stuff is captured each time. I’m going to have a read through your macro and see how much I can make sense of it myself.

Not sure when I’ll get around to looking at real world samples. I’ll look at making a scale bar. It might sound silly but I’m tempted to make it out of Lego to allow me to adjust it’s height level with the top of the steak for improved accuracy.

Good day!

In fact it is very important to think about the details of image acquisition because optimum acquisition eases image analysis and can make it more robust.

Please try to realize the following:

  1. Use a professional camera that provides lossless image file formats such as TIF, PNG or Raw (in any case no JPG)
  2. Use optics with a large focal length (in any case no wide-angle optics).
    Ideally you should use telecentric optics
  3. Use an F-number of 8 to 11
  4. If possible use a ring-light around the optics.
    Experiment with color filtered light to increase the contrast (start with greenish filters)
  5. Use a stable camera stand that provides a fixed spatial relation to the object board and the scale-bar
  6. Use an object board that is easy to clean and that provides good contrast to the object (fat and meat)
  7. The scale-bar should appear at the same position in every image taken and it should be aligned with the image border (minimize rotations)
    I don’t think that you need to lift the scale-bar to the object level but if you do, don’t use a LEGO brick but use a larger block, e.g. of the board material and of sufficient thickness onto which you paint the scale-bar

Good luck

Herbie

Here is a further refined and even shorter ImageJ-macro that doesn’t need a “RGB to CMYK”-conversion:

// imagej-macro "fleshAndFat" (Herbie G., 19. Dec. 2018)
requires( "1.52i" );
updateResults();
setOption("BlackBackground", true);
orig=getImageID;
setBatchMode(true);
run("Duplicate...", "title=cpy");
run("HSB Stack");
run("Make Substack...", "  slices=2");
close("cpy");
setAutoThreshold("Huang dark");
doWand(0, 0.5*getHeight());
resetThreshold();
area("Total Area",0);
olay(orig);
selectImage("Substack (2)");
setAutoThreshold("MaxEntropy dark");
run("Convert to Mask");
run("Fill Holes");
run("Analyze Particles...", "size=300-Infinity add");
roiManager("combine");
roiManager("Add");
roiManager("select", roiManager("count")-1);
area("Red Area",1);
olay(orig);
run("Overlay Options...", "stroke=blue width=1 fill=none apply");
setBatchMode(false);
exit();
function area(col,rw) {
   List.setMeasurements;
   setResult(col, nResults-rw, round(List.getValue("Area")));
}
function olay(img) {
   selectImage(img);
   run("Restore Selection");
   run("Add Selection...");
   run("Select None");
}
// imagej-macro "fleshAndFat" (Herbie G., 19. Dec. 2018)

For my posted sample image it gives me a total area of 417969 pixel^2 and an area of red meat of 272345 pixel^2. The difference to the previously measured area values appears tolerable.

Regards

Herbie