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

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Calculating Tolerance values for TImageEnProc.Auto

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
xequte Posted - Nov 11 2015 : 20:08:45
function TImageEnProc.AutoCrop(Tolerance: Integer; Background: TRGB; DoCrop: Boolean = True): TRect;

The tolerance value allows you to specify the range of colors that will be matched when performing an automatic crop. So given two color values (e.g. sampled from two corners of an image) how can you calculate the tolerance?


Color1 := ImageEnView1.IEBitmap.Pixels[ 0, 0 ]; // Top-Left
Color2 := ImageEnView1.IEBitmap.Pixels[ 0, ImageEnView1.IEBitmap.Height - 1 ];// Bottom Left

Background.R := ( Color1.R + Color2.R ) div 2; // average R value
RTolerance :=  abs( Ceil( ( Color1.R - Color2.R ) / 2 )) ;
Tolerance := RTolerance;

Background.G := ( Color1.G + Color2.G ) div 2; // average G value
GTolerance :=  abs( Ceil( ( Color1.G - Color2.G ) / 2 )) ;
if GTolerance > Tolerance then
  Tolerance := GTolerance;

Background.B := ( Color1.B + Color2.B ) div 2; // average B value
BTolerance :=  abs( Ceil( ( Color1.B - Color2.B ) / 2 )) ;
if BTolerance > Tolerance then
  Tolerance := BTolerance;

ImageEnView1.Proc.AutoCrop( Tolerance, Background );


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
7   L A T E S T    R E P L I E S    (Newest First)
jrpcguru Posted - Dec 01 2015 : 19:18:13
Wow, things sure can get ugly!

I am scanning to JPG, TIF, or PSD. In most cases I will be autocropping unsaved images in ImageEnView. I do have some older images that I forgot to crop. I hope that helps in determining a better algorithm. In fact that suggests that I need to test the tolerance algorithm with JPG files and with freshly scanned and unsaved images. Too late, tonight. Thanks.

J.R.
Uwe Posted - Dec 01 2015 : 18:49:04
To make things even more confusing: the tolerance level for Autocrop varies depending on the file format as well. PEF, RWL, CRW and JPG files and their embedded previews require a different tolerance level than those of ARW and RAF files for example.

-Uwe
jrpcguru Posted - Dec 01 2015 : 17:43:37
Further information on using AutoCrop:

The revised code that I posted last, does work pretty well at AutoCrop, as long as I use the higher tolerance discovered through trial and error of 110. I'm hoping there is another possible algorithm to calculate the tolerance since it does vary somewhat depending on the color of the platen or other border around the image.

I have been working with AutoCrop2 to see if I can auto crop black borders. I find that using AutoCrop with my own tolerance of 110 or close to that, seems to work pretty well. I've had to guess at the correct tolerance for using Autocrop2. I wonder if there is an algorithm that will calculate that? I also wonder what the limits are for the tolerance used in AutoCrop2? It is a completely different value than with Autocrop. The help defines the limits of the tolerance for Autocrop as 0 to 255, but for Autocrop2 it only says it must be greater than 0. I would like to error trap my code for setting these values.
Thanks for your help so far on getting Autocrop to work well.

J.R.
jrpcguru Posted - Nov 29 2015 : 18:55:01
I used my code only to calculate the values in a clean scan of the platen with no document. I rewrote the code to calculate values only for the full left edge, top edge, bottom edge, or right edge. I also fixed a bug that prevented a proper comparison with the low pixel value:

if inEdge = 'L' then
  begin
    tColorPixel := ImageEnView1.IEBitmap.IECanvas.GDICanvas.Pixels[0,0];
    tColorPixelHigh := tColorPixel;
    tColorPixelLow := tColorPixel; //initialize to allow proper comparison
    for y := 0 to ImageEnView1.IEBitmap.Height - 1 do
      begin
        tColorPixel := ImageEnView1.IEBitmap.IECanvas.GDICanvas.Pixels[0,y];
        if tColorPixel > tColorPixelHigh then
          tColorPixelHigh := tColorPixel;
        if tColorPixel < tColorPixelLow then
          tColorPixelLow := tColorPixel;
      end;

  end

The original code yielded
Epson flatbed
ScannerCropTolerance=127
BorderColor=8356261

The bug fix yielded the following values for all the edges:
border = 15658730
Tolerance = 17

border = 15526887
Tolerance = 19

border = 15132647
Tolerance = 24

border = 15132645
Tolerance = 24

So correcting the bug gave a much different color value but the tolerance was no where near enough to successfully autocrop.

I also tried RemoveChromaKey with a selection to identify the color of the area to autocrop:
if ImageEnView1.Selected then
        begin
//          KeyColorRGB := ImageEnView1.Proc.CalcAverageRGB( 100 );
//          ImageEnView1.Proc.RemoveChromaKey( KeyColorRGB, 0.21, 30, 2, 2,true );

          KeyColorRGB := ImageEnView1.Proc.GuessChromaKeyColor( dbTolerance );
          iTolerance := Trunc(dbTolerance * 1000);
    CropBox := ImageEnView1.Proc.AutoCrop(iTolerance ,KeyColorRGB,true);


RemoveChromakey did not work since it only affected the selection box.
The tolerance for GuessChromaKey is apparently not related to the tolerance for autocrop so that still failed.


I have tried


J.R.
xequte Posted - Nov 29 2015 : 17:28:16
Hi JR

The problem with my code example is that it only samples two pixels, which may not be representative of the border area.

The problem with your code is that it samples the entire image including the non-border area so it will just auto-crop the entire image.

So you need to increase your sample size without including any content. Perhaps you can allow a selection to be made then sample that.


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
jrpcguru Posted - Nov 29 2015 : 10:58:23
I have tried calculating the color and tolerance for the entire platen color of my flatbed scanner, then used those values to autocrop images that were scanned on my scanner, the samples that I sent you. My code looks like this:

function TMainForm.jrGetOverallImageColorAndTolerance(out outTolerance : integer) : TColor;
var
  Color1, Color2 : TRGB;
  tColorPixel, tColorPixelLow, tColorPixelHigh : tColor;
  Background : TRGB;
  Tolerance, RTolerance, GTolerance, BTolerance : integer;
  x,y : integer;
begin

  for x := 0 to ImageEnView1.IEBitmap.Width - 1 do
    begin
      for y := 0 to ImageEnView1.IEBitmap.Height - 1 do
        begin
          tColorPixel := ImageEnView1.IEBitmap.IECanvas.GDICanvas.Pixels[x,y];
          if tColorPixel > tColorPixelHigh then
            tColorPixelHigh := tColorPixel;
          if tColorPixel < tColorPixelLow then
            tColorPixelLow := tColorPixel;
        end;
    end;

//        Color1 := ( ImageEnView1.IEBitmap.Pixels[ x, y ]); // first point
//        Color2 := ( ImageEnView1.IEBitmap.Pixels[ x, y ]);// second point

    Color1 := TColor2TRGB(tColorPixelLow);
    Color2 := TColor2TRGB(tColorPixelHigh);

        Background.R := ( Color1.R + Color2.R ) div 2; // average R value
        RTolerance :=  abs( Ceil( ( Color1.R - Color2.R ) / 2 )) ;
        Tolerance := RTolerance;

        Background.G := ( Color1.G + Color2.G ) div 2; // average G value
        GTolerance :=  abs( Ceil( ( Color1.G - Color2.G ) / 2 )) ;
        if GTolerance > Tolerance then
          Tolerance := GTolerance;

        Background.B := ( Color1.B + Color2.B ) div 2; // average B value
        BTolerance :=  abs( Ceil( ( Color1.B - Color2.B ) / 2 )) ;
        if BTolerance > Tolerance then
          Tolerance := BTolerance;

  outTolerance := Tolerance;
  result := TRGB2TColor(Background);
end;


I then use the following to get the values and store them for use during autocropping:
BorderColor := jrGetOverallImageColorAndTolerance(iScannerCropTolerance);

And I perform the autocrop like this:
ImageEnView1.Proc.AutoCrop(iScannerCropTolerance, BorderColor ,true);

I got the following values as a result:
Epson flatbed with a bluish tinted platen:
ScannerCropTolerance=127
BorderColor=8356261

HP DeskJet F4480 with a more white platen:
border = 8355711
Tolerance = 127

This results in most of the images being completely cropped to nothing! I'm hoping there is something I'm messing up but I'm running out of ideas to make AutoCrop work.






J.R.
jrpcguru Posted - Nov 28 2015 : 15:11:09
I have now tried this code on some of the sample images that I sent to you. I had to remove TColor2TRGB because Pixels[0,0] already returned its values as TRGB. My code turned out like this:

function TMainForm.jrGetImageColorAndTolerance(inX1: integer; inY1 : integer; inX2 : integer; inY2 : integer;
  out outTolerance : integer) : TRGB;
var
  Color1, Color2 : TRGB;
  Background : TRGB;
  Tolerance, RTolerance, GTolerance, BTolerance : integer;
begin

  Color1 := ( ImageEnView1.IEBitmap.Pixels[ inX1, inY1 ]); // first point
  Color2 := ( ImageEnView1.IEBitmap.Pixels[ inX2, inY2 ]);// second point

  Background.R := ( Color1.R + Color2.R ) div 2; // average R value
  RTolerance :=  abs( Ceil( ( Color1.R - Color2.R ) / 2 )) ;
  Tolerance := RTolerance;

  Background.G := ( Color1.G + Color2.G ) div 2; // average G value
  GTolerance :=  abs( Ceil( ( Color1.G - Color2.G ) / 2 )) ;
  if GTolerance > Tolerance then
    Tolerance := GTolerance;

  Background.B := ( Color1.B + Color2.B ) div 2; // average B value
  BTolerance :=  abs( Ceil( ( Color1.B - Color2.B ) / 2 )) ;
  if BTolerance > Tolerance then
    Tolerance := BTolerance;
  outTolerance := Tolerance;
  result := Background;
end;

I call this code with:
ColorBackground := jrGetImageColorAndTolerance(0,0,0,ImageEnView1.IEBitmap.Height - 1,iAutoCropTolerance);
ImageEnView1.Proc.AutoCrop(iAutoCropTolerance ,ColorBackground,true);

The tolerance returns as 3 and no autocropping happens.
My original code measured the color at 0,0 and through trial and error I found that a tolerance of 110 resulted in a successful autocrop. Though it over crops if the document is too close in color to the platen color.

I'm going to try measuring the color and variation of the platen, but I suspect I will need to wait for your new autocrop algorithm.



J.R.