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
 Calculating Tolerance values for TImageEnProc.Auto
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

xequte

39053 Posts

Posted - Nov 11 2015 :  20:08:45  Show Profile  Reply
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

jrpcguru

USA
273 Posts

Posted - Nov 28 2015 :  15:11:09  Show Profile  Reply
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.
Go to Top of Page

jrpcguru

USA
273 Posts

Posted - Nov 29 2015 :  10:58:23  Show Profile  Reply
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.
Go to Top of Page

xequte

39053 Posts

Posted - Nov 29 2015 :  17:28:16  Show Profile  Reply
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
Go to Top of Page

jrpcguru

USA
273 Posts

Posted - Nov 29 2015 :  18:55:01  Show Profile  Reply
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.
Go to Top of Page

jrpcguru

USA
273 Posts

Posted - Dec 01 2015 :  17:43:37  Show Profile  Reply
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.
Go to Top of Page

Uwe

284 Posts

Posted - Dec 01 2015 :  18:49:04  Show Profile  Reply
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
Go to Top of Page

jrpcguru

USA
273 Posts

Posted - Dec 01 2015 :  19:18:13  Show Profile  Reply
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.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: