ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Obtaining measurements demo
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

John

USA
94 Posts

Posted - Oct 03 2011 :  08:40:41  Show Profile  Reply
Slightly modifying the measurements demo based on the fact that the embedded standard on the xrays in a millimeter ruler and not a area, I do the following.

I load into ImageEnVect1 an xray with a millimeter ruler embedded to obtain standard lengths. Using the measurement demo as a model I do the following:

a) I set MouseInteract := [miSelect];
b) I measure a 20 millimeter length on the embedded ruler
c) The OnSelection event is then called

procedure TformXrayMeasure.ImageEnVect1SelectionChange(Sender: TObject);
var
tempCalibrationLength: Double;
begin
if tempCalibrationLength = 0 then
begin
tempCalibrationLength := ImageEnVect1.GetSelectionLen;

with ImageEnVect1 do
begin
mUnit := ieuMillimeters;
SetScaleFromSelectionLen(20);
Deselect;
MouseInteractVt := [miDragLen];
end;

MessageDlg('You can now measure lengths.',
mtConfirmation, [mbOk], 0 );
SpeedButtonCalibrate.Enabled := False;
end
end;

The problem is that if I then measure 10 millimeters on the embedded ruler the result is not 10 millimetter, but rather 5 millimeters ( plus or minus some small fraction of a millimeter) not 10 millimeters.

Suggestions?

TIA

John

fab

1310 Posts

Posted - Oct 03 2011 :  10:42:10  Show Profile  Reply
Hi,
SetScaleFromSelectionLen gets a perimeter, not a segment length.
Please try SetScaleFromPixels(number_of_pixels, measure_length) instead.
Go to Top of Page

John

USA
94 Posts

Posted - Oct 03 2011 :  12:44:16  Show Profile  Reply
Fabizio

I looked at SetScaleFromPixils but my question was how to determine the number of pixels encompassed by the reference length measurement which is vertically oriented?

My thought was to use the LMDSysInfo.ScreenHeight property which returns the number of pixels in the screen height. From there I can get pixels per millimeter by dividing LMDSysInfo.ScreenHeight/screen Height in mm.

Does ImageEn contain another mechanism to obtain the number of pixels contained in the reference length (which is vertical in orientation)? Or do you have a better suggestion to obtain the pixel count for the reference length?

TIA

John
Go to Top of Page

fab

1310 Posts

Posted - Oct 03 2011 :  12:58:11  Show Profile  Reply
quote:
My thought was to use the LMDSysInfo.ScreenHeight property which returns the number of pixels in the screen height. From there I can get pixels per millimeter by dividing LMDSysInfo.ScreenHeight/screen Height in mm.


Sorry, I don't understand very well. What has to do the screen with the image?
ImageEn just converts a length in pixels to a length in another measure unit, and this can be done adjusting Scale and DPI (of the background image). This is done automatically by SetScaleFromSelectionLen or by SetScaleFromPixels. No other ways or info are available.

quote:
Does ImageEn contain another mechanism to obtain the number of pixels contained in the reference length (which is vertical in orientation)?


SetScaleFromPixels, no other. Put a ruler over the reference length, and pass the ruler length to SetScaleFromPixels.
Go to Top of Page

John

USA
94 Posts

Posted - Oct 03 2011 :  22:17:12  Show Profile  Reply
Fabrizio

Since the embedded millimeter ruler in the xray images has a know width, I can actually use the code represented with the "MeasureIt" demo to calibrate the values used with ImageEnVect1.MouseInteractVt := [miDragLen];

I am still confused, however, about calibrating the drag measurement functionality with the SetScaleFromPixels function.

The help file defines the function as SetScaleFromPixels(px:integer; mm:double). As I understand it, the first variable "px" is the number of pixels represented by the length of the second variable. I my situation I define ImageEnVect1.mUnit := ieuMillimeters and mm = 10 for a total of 10 millimeters which can be easily read from the millimeter ruler embedded in the xray image;

The problem is that when I load an xray, (althought it has a vertical millimeter ruler embedded in the film), I do not know how many pixels are represented by the distance between millimeter 1 and 10.

The question thus becomes, how to determine the number of pixels between millimeter 1 and 10 on the embedded ruler so that I can correctly define the scale using the SetScaleFromPixels function?

Sorry for the confusion. I certainly appreciate any clarification that you can provide.

John
Go to Top of Page

fab

1310 Posts

Posted - Oct 04 2011 :  01:25:21  Show Profile  Reply
quote:
The problem is that when I load an xray, (althought it has a vertical millimeter ruler embedded in the film), I do not know how many pixels are represented by the distance between millimeter 1 and 10.


You can know the distance, in pixels, of the ruler with:
var
  lx, ly: double;
  r: TRect;
  len: double;
begin
  ImageEnVect1.GetObjRect(ImageEnVect1.SelObjects[0], r);
  lx := abs(r.Right-r.Left);
  ly := abs(r.Bottom-r.Top);
  len := sqrt(lx * lx + ly * ly);
  ...now "len" contains the ruler length in pixels...

end;
Go to Top of Page

John

USA
94 Posts

Posted - Oct 04 2011 :  21:16:50  Show Profile  Reply
That is exactly what I was looking to accomplish.

Thank you very much.

John
Go to Top of Page

John

USA
94 Posts

Posted - Oct 16 2011 :  10:09:24  Show Profile  Reply
Fabrizio

Using the code you supplied earlier in this thread, I can drawn a line through 20 millmeters of a millimeter ruler embedded in an ImageEnVect image, determine the number of pixels in the line and then determine the number of pixels per millimeter for the specific image.

The current issue is as follows: if I set
ImageEnVect1.MouseInteractVt := [miDragLen];
the length displayed in the label as the measurement is made is labeled as millimeters and does not correspond to the embedded millimeter ruler.

Question 1) Exactly what does the displayed miDragLen measurement represent? The physical length of the line in millimeters? A pixel count measurement of the line length divided by a predefined pixels per millimeter length?

Question 2) Is there a mechanism to convert the measurement displayed in the miDragLen text to a millimeter measurement based on the pixels per millimeter standard that I previously established using the embedded millimeter ruler?

I looked at the OnPresentMeasurement event, but the help file does not define whether the "Value" variable is length or pixels and there is no information on the ValType

I appreciate your efforts and await your reply

John
Go to Top of Page

fab

1310 Posts

Posted - Oct 16 2011 :  10:22:07  Show Profile  Reply
About miDragLen, have you set MUnit? You should set:

ImageEnVect1.MUnit := ieuMILLIMETERS;

In my tests ruler length and miDragLen values corresponds.

quote:
I looked at the OnPresentMeasurement event, but the help file does not define whether the "Value" variable is length or pixels and there is no information on the ValType

"Value" is the value to show. For example it is the measured length (in the measure unit you have chosen).
Go to Top of Page

John

USA
94 Posts

Posted - Oct 16 2011 :  15:37:57  Show Profile  Reply
Fabrizio

1. I had set MUnit := ieuMillimeters which explains the unit labeling with MouseInteractVt := [miDragLen].

2. I obtain the correct calibration by using the following calibration code.

Uses tempPixesPerMM: Double;

procedure TformXrayMeasure.Calibrate;
var
lx, ly: double;
tempRect: TRect;
len: double;
begin
ImageEnVect1.GetObjRect(ImageEnVect1.SelObjects[tempObjIndex], tempRect);
lx := abs(tempRect.Right - tempRect.Left);
ly := abs(tempRect.Bottom - tempRect.Top);
len := sqrt(lx * lx + ly * ly);

tempPixelsPerMM := len/20;
ImageEnVect1.SetScaleFromPixels(Trunc(len), 20);

if MessageDlg('Do you wish to remove the calibration line?',
mtConfirmation, [mbYes, mbNo], 0 ) = mrYes then
begin
ImageEnVect1.RemoveObject(ImageEnVect1.SelObjects[0]);
end;

ImageEnVect1.CancelInteracts;
end;

3) I obtain the length of a selected line via the following code.

procedure TformXrayMeasure.SpeedButtonGetLengthClick(Sender: TObject);
var
lx, ly: double;
tempRect: TRect;
len: double;
begin
if ImageEnVect1.ObjectsCount > 0 then
begin
if tempObjIndex >= 0 then
begin
ImageEnVect1.GetObjRect(ImageEnVect1.SelObjects[tempObjIndex], tempRect);
lx := abs(tempRect.Right - tempRect.Left);
ly := abs(tempRect.Bottom - tempRect.Top);
len := sqrt(lx * lx + ly * ly);

showmessage('Length of obj = ' + FloatToStr(len/tempPixelsPerMM));
end
end;
end;


Related question.

Instead of drawing a line and getting the length by either the above proceedure or using miDragLen. Is there a mechanism to select two points/markers ( similar to your "Marker" demo) and from those two points/markers determine the distance between them?

I appreciate your efforts

John
Go to Top of Page

fab

1310 Posts

Posted - Oct 20 2011 :  00:11:05  Show Profile  Reply
quote:
Instead of drawing a line and getting the length by either the above proceedure or using miDragLen. Is there a mechanism to select two points/markers ( similar to your "Marker" demo) and from those two points/markers determine the distance between them?


It is not possible automatically. Anyway you can still put two objects (for example two images) and calculate the distance between them.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: