Author |
Topic |
|
timfa
USA
9 Posts |
Posted - Oct 24 2024 : 10:17:52
|
I think you have a potential bug in the IEApplyThreshold procedure in the imageenproc.pas unit.
I am simply performing a threshold operation where all pixels below ThresholdValue (e.g., 128) are being set to 0 or 255 in one case or the opposite 255 or 0 in an alternate case. I have a TIEBitmap object named ThresholdImage and makes the following call (the alternate case):
ThresholdImage.Proc.Threshold(
CreateRGB(ThresholdValue,ThresholdValue,ThresholdValue),
CreateRGB(ThresholdValue,ThresholdValue,ThresholdValue),
CreateRGB(255,255,255), CreateRGB(0,0,0) );
This function in turn calls:
procedure IEApplyThreshold(Bitmap: TIEBitmap; DownLimit, UpLimit, DownVal, UpVal: TRGB; X1, Y1, X2, Y2: Integer; OnProgress: TIEProgressEvent; Sender: TObject);
And in this procedure the following code executes:
for x := X1 to X2 do
begin
e := pRGB(ei);
if (e^.r <= DownLimit.r) then
e^.r := DownVal.r;
if (e^.g <= DownLimit.g) then
e^.g := DownVal.g;
if (e^.b <= DownLimit.b) then
e^.b := DownVal.b;
if (e^.r > UpLimit.r) then
e^.r := UpVal.r;
if (e^.g > UpLimit.g) then
e^.g := UpVal.g;
if (e^.b > UpLimit.b) then
e^.b := UpVal.b;
inc(ei, i);
end;
What happens in the case I presented is if the first IF for each r, g, b value is true it executes e^.r := DownVal.r which sets the value to 255. Then, further down it executes "if (e^.r > UpLimit.r)" and since we already changed e^.r in the first IF to 255, this second IF is true and sets e^.r := UpVal.r, i.e., it sets it to 0. I think this is wrong.
I think the code should be changed to:
if (e^.r <= DownLimit.r) then
e^.r := DownVal.r
else if (e^.r > UpLimit.r) then
e^.r := UpVal.r;
if (e^.g <= DownLimit.g) then
e^.g := DownVal.g
else if (e^.g > UpLimit.g) then
e^.g := UpVal.g;
if (e^.b <= DownLimit.b) then
e^.b := DownVal.b
else if (e^.b > UpLimit.b) then
e^.b := UpVal.b;
Thank you for considering this issue.
Tim F |
|
xequte
38607 Posts |
Posted - Oct 24 2024 : 18:29:59
|
Thanks for the report, Tim,
I'll need to investigate this when I am back in the office in early November.
Nigel Xequte Software www.imageen.com
|
|
|
xequte
38607 Posts |
Posted - Nov 03 2024 : 21:33:39
|
Hi Tim
Just to clarify, why are you not ordering your up/down values (i.e. CreateRGB(0,0,0) , CreateRGB(255,255,255) ) as would be expected?
Nigel Xequte Software www.imageen.com
|
|
|
timfa
USA
9 Posts |
Posted - Nov 13 2024 : 17:49:23
|
Hello Nigel,
I'm ordering the values as I am because in one case I am looking for a black object in the image or in the other case I'm looking for a white object. In either case, I want the item found to appear in the threshold image as white and the pixels that don't pass the threshold test to be black. The code I wanted to use was:
if aSetting.ThresholdMethod = tmManual then
begin
ThresholdValue := aSetting.Threshold;
if aSetting.MeasureMethod = mmBlackCircle then
begin
MinThreshold := 0;
MaxThreshold := ThresholdValue;
ThresholdImage.Proc.Threshold(
CreateRGB(ThresholdValue,ThresholdValue,ThresholdValue),
CreateRGB(ThresholdValue,ThresholdValue,ThresholdValue),
CreateRGB(255,255,255), CreateRGB(0,0,0) );
end
else
begin
MinThreshold := ThresholdValue;
MaxThreshold := 255;
ThresholdImage.Proc.Threshold(
CreateRGB(ThresholdValue,ThresholdValue,ThresholdValue),
CreateRGB(ThresholdValue,ThresholdValue,ThresholdValue),
CreateRGB(0,0,0), CreateRGB(255,255,255) );
end;
My workaround to this bug was...
// Set all values <= MinThreshold to 0 (black), and all values > MaxThreshold
// also to 0 (black).
ThresholdImage.Proc.Threshold( CreateRGB(MinThreshold,MinThreshold,MinThreshold),
CreateRGB(MaxThreshold,MaxThreshold,MaxThreshold),
CreateRGB(0,0,0), CreateRGB(0,0,0) );
// Set all non-zero values to 255 (White). (Actually, a value of 1 is unaltered.)
ThresholdImage.Proc.Threshold( CreateRGB(0,0,0), CreateRGB(1,1,1),
CreateRGB(0,0,0), CreateRGB(255,255,255) );
The documentation for the Threshold procedure never says anything about expecting values to be in a certain order wrt magnitude... "First overload assigns the DownVal color to all colors smaller or equal to DownLimit, and UpVal to all colors greater than UpLimit." This is not the behavior of this procedure under the conditions I identified.
On another matter, it would be nice if your procedure TImageEnProc.ConvertToBWThreshold were changed to a function that returned the threshold value that was derived when the argument is -1 or -2 or the passed in value when it isn't -1 or -2.
Thank you.
Tim F |
|
|
xequte
38607 Posts |
Posted - Nov 15 2024 : 18:58:36
|
Thanks for the suggestions, Tim. We have implemented both your suggested changes in the current beta. You can email me for it.
Nigel Xequte Software www.imageen.com
|
|
|
|
Topic |
|
|
|