Getting all pixel values in a roi

Greetings,
I’m trying to accomplish a pretty simple task but don’t fully understand the results I’m getting. What I’d like to do is draw a bunch of line ROIs on an image, and then get the values of the pixels that are within the roi for further processing. Can someone explain to me why I cam getting the following output.
I have a segmented line roi (made up of 1 segment) that has a length of 5 and a line width of 5. I have also created a second roi using the original but choosing selection to area. They can be seen in the following ( yellow line is area and solid yellow is original line I drew.

My first question, why is the area shape not a line? Is this because imagej is doing some kind of subpixel processing to figure out what shape to use to contain the area?
Now when I run the following macro

for (k=0;k<roiManager("count");k++){ 
	roiManager("Select",k)	

   Roi.getBounds(x, y, width, height)

	print("x= ",x,"y= ",y,"w= ",width,"height =",height);

	Roi.getContainedPoints(xpoints, ypoints);
	print("xNum= ",xpoints.length," yNum = ",ypoints.length,"total_num",xpoints.length*ypoints.length);
	print("==================");

	  
}

for (k=0;k<roiManager("count");k++){ 
	roiManager("Select",k)	
run("Interpolate", "interval=1");
   Roi.getBounds(x, y, width, height);

print("xInterp= ",x,"yInterp= ",y,"wInterp= ",width,"heightInterp =",height);

	Roi.getContainedPoints(xpoints2, ypoints2);
	print("xNumInterp= ",xpoints2.length," yNumInterp = ",ypoints2.length,"total_num_Interp",xpoints2.length*ypoints2.length);
	print("*************************");
	 
}

I get the following output

x=  286 y=  131 w=  0 height = 5
xNum=  46  yNum =  46 total_num 2116
==================
x=  284 y=  129 w=  5 height = 10
xNum=  46  yNum =  46 total_num 2116
==================
xInterp=  286 yInterp=  131 wInterp=  0 heightInterp = 5
xNumInterp=  46  yNumInterp =  46 total_num_Interp 2116
*************************
xInterp=  284 yInterp=  129 wInterp=  5 heightInterp = 10
xNumInterp=  46  yNumInterp =  46 total_num_Interp 2116
*************************

Now my original line should have a length of 5 and width of 5 which I would guess means that the enclosed area is 5x5=25 pixels. So my first question

  1. Why does roi.getbounds give w=0, h=5 for a line of width 5 and length 5 (width set with line width tool). But when I use line to area I get w=5, h=10 .

  2. using roi.getContainedPoints I would expect 5x5 = 25 points, but I am getting in all cases 46x46 points. , while the number of x * number of y pixels is the same in all cases.

Can someone please clarify this for me. What I’d like to do is get raw pixel values from a roi which is a line of linewidth 5 and arbitrary length (and angle) drawn by a user. It seems that Roi.getContainedPoints is what I want but it seems to be always returning the same number of x and y values ( in to two seperate arrays).

I thought the issue might be my use of a line of linewidth 5 which is why I switched to making it an area also.
Can someone please clear this up for me. I’m hoping it’s pretty simple. I’ve done more complicated things in imageJ but thee results don’t make sense to me.
Thanks,

  • Jeff

Hi,
when using line to area on a segmented or a freehand line something strange seems to happen. The line of length 5 and width five becomes the area-selection of length 10 and width 5 with the missing corner pixels as shown in your image.

If I use straight line instead, everything works as expected and I get an area selection with the area of 25 (it also works for the arrow tool)

I’m not sure if the behavior for segmented and freehand lines is a bug or if there is a reason for it.

Do you need segmented lines or would straight lines do?

Best regards,
Volker

1 Like

Hi,
Thanks for the reply. You are indeed correct, if I use a straight line then turn it to an area it looks correct. (see image below, which was a segmented (left) and staight (right) lines turned to an area. I can work with straight lines for now, but will bring this up on the imageJ mailing list as well.
Thanks.

Perhaps @Wayne has an idea of this implementation difference?

It would help to have a minimal macro that reproduces the issue.

Hi Wayne,
here is a macro that reproduces the issue. Please note that when working manually, the issue occurs even when the segmented line has only one segment. I guess that the macro command makeLine will create a straight line when there is only one segment and the issue does not occur for straight lines.

newImage("Untitled", "8-bit ramp", 512, 512, 1);
makeLine(234,24,234,27,234,29);
setLineWidth(5);
Overlay.addSelection
run("Line to Area");
1 Like

Hi @volker and @jspector,
Here is an improved version of the test macro:

  newImage("Untitled", "8-bit noise", 512, 512, 1);
  makeLine(234,24,234,27,234,29);
  Roi.setStrokeWidth(5);
  Overlay.addSelection("5500ffff")
  run("Line to Area");
  Roi.setStrokeColor("yellow");
  run("To Selection");

It replaces setLineWidth(), which does not set the line width of selections, with Roi.setStrokeWidth().

This is what the output looks like:

Screenshot

The selection created by run(“Line to Area”) is taller and the line ends are rounded because ImageJ converts the line to a polygon by drawing it using a circular brush, which creates a mask that is converted into a selection. This causes the line to be extended at each end by half a circle.

A new method is needed that does not extend the line ends. One way would be to convert each line segment into a rectangle and then combine the rectangles to create a polygon. The following JavaScript code converts a segmented line into a series of rectangles, but it doesn’t do the hard part of combining the rectangles to create a polygon.

  img = IJ.createImage("Untitled", "8-bit noise", 500, 550, 1);
  p = new Polygon();
  p.addPoint(100,40); p.addPoint(290,140); p.addPoint(330,270);
  p.addPoint(260,340); p.addPoint(140,280); p.addPoint(100,400);
  p.addPoint(230,480); p.addPoint(390,410);
  roi = new PolygonRoi(p,Roi.POLYLINE);
  roi.setStrokeWidth(2);
  img.setRoi(roi);
  overlay = new Overlay();
  for (i=1; i<p.npoints; i++) {
     line = new Line(p.xpoints[i-1],p.ypoints[i-1],p.xpoints[i],p.ypoints[i]);
     line.setStrokeWidth(50);
     rect = line.convertToPolygon();
     rect.setLineWidth(2);
     overlay.add(rect);
  }
  img.setOverlay(overlay);
  img.show();

1 Like

This bug should be fixed in the latest ImageJ daily build (1.52t15), thanks to new code for converting lines to areas from Michael Schmid.

2 Likes