unit filterHistogramContrast;
(* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2004 Durand Emmanuel
* Copyright (C) 2004 Burgel Eric
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact :
* filters@edurand.com
* filters@burgel.com
*
* ***** END LICENSE BLOCK ***** *)
{
edurand (filters@edurand.com)
}
interface
uses
filter, fparameters, filterblur, image, SysUtils, Windows,
filterHistogram, filterStandardDeviation;
type
THistogramContrastAnalyseROI = class
public
diff : array[0..255] of Integer;
diffMax, diffIntegralMax : Integer;
diffIntegral, diffIntegralNormed : Integer;
constructor Create;
destructor Destroy; override;
procedure setImage(aImage:PBitmap32);
procedure setPrecision(aPrecision:Integer);
procedure process(aROI:TRect);
private
filterHistogram1, filterHistogram2 : TFilterHistogram;
histogramme1, histogramme2 : TParameterArraySingles;
t : TParameterArrayIntegers ;
end;
TFilterHistogramContrast = class(TFilter)
public
constructor Create; override;
destructor Destroy; override;
procedure Run(); override;
procedure setParameterImage( const aName: String; const aImage: PBitmap32); override;
procedure setParameterInteger( const aName: String; const aValue:Int64); override;
private
analyseROI : THistogramContrastAnalyseROI;
parameterImageIn : TParameterImage;
outputParameterImageOuts : TParameterImages;
imageOuts : ArrayOfPBitmap32;
parameterMode : TParameterString;
parameterGridSpacingWidth, parameterGridSpacingHeight : TParameterInteger;
parameterPrecision : TParameterInteger;
parameterRectangleWidth,parameterRectangleHeight : TParameterInteger;
parameterBlurIteration : TParameterInteger;
filterBlur : TFilterBlur ;
imageIn : PBitmap32;
imageBlurOut : PBitmap32;
filterStandardDeviation : TFilterStandardDeviation;
imageStandardDeviationOut : PBitmap32;
procedure destroyImageOuts();
procedure createImageOut0(aImageIn:PBitmap32);
procedure runNormal;
procedure runShowdetails;
procedure _run();
end;
implementation
uses
imageIO, Math;
constructor TFilterHistogramContrast.Create;
begin
inherited;
parameterImageIn:=addParameterImage('inImage','explication...');
outputParameterImageOuts:=addOutputParameterImages('outImages','0:normal/1:show_details');
parameterMode:=addParameterString('mode','NORMAL/SHOW_DETAILS','NORMAL');
parameterGridSpacingWidth:=addParameterInteger('gridSpacingWidth','',1,100,10);
parameterGridSpacingHeight:=addParameterInteger('gridSpacingHeight','',1,100,10);
parameterPrecision:=addParameterInteger('precision','',1,15,5);
parameterRectangleWidth:=addParameterInteger('rectangleWidth','',2,100,20);
parameterRectangleHeight:=addParameterInteger('rectangleHeight','',2,100,60);
analyseROI:=THistogramContrastAnalyseROI.Create;
parameterBlurIteration:=addParameterInteger('blurIteration','explication...',0,10,3);
filterBlur:=TFilterBlur.Create ;
filterStandardDeviation:=TFilterStandardDeviation.Create;
SetLength(imageOuts,2);
end;
destructor TFilterHistogramContrast.Destroy;
begin
inherited;
destroyImageOuts();
analyseROI.Free;
image.freeImage(imageBlurOut);
filterBlur.Free;
filterStandardDeviation.Free;
end;
procedure TFilterHistogramContrast.destroyImageOuts();
var
i : Integer;
begin
for i:=Low(imageOuts) to High(imageOuts) do begin
image.freeImage(imageOuts[i]);
end;
end;
procedure TFilterHistogramContrast.setParameterImage( const aName: String; const aImage: PBitmap32);
begin
inherited;
if aName='inImage' then begin
image.freeImage(imageBlurOut);
imageBlurOut:=createImageFromImage(aImage);
analyseROI.setImage(imageBlurOut);
createImageOut0(aImage);
end;
end;
procedure TFilterHistogramContrast.createImageOut0(aImageIn:PBitmap32);
var
imageOutWidth, imageOutHeight : Integer;
begin
if aImageIn<>nil then begin
imageOutWidth:=aImageIn.Width div parameterGridSpacingWidth.Value;
imageOutHeight:=aImageIn.Height div parameterGridSpacingHeight.Value;
if (imageOuts[0]<>nil) then begin
if (imageOuts[0].Width<>imageOutWidth) or
(imageOuts[0].Height<>imageOutHeight) then begin
image.freeImage(imageOuts[0]);
imageOuts[0]:=createImage(imageOutWidth,imageOutHeight);
setOutputParameterImages('outImages',imageOuts);
image.freeImage(imageStandardDeviationOut);
imageStandardDeviationOut:=createImageFromImage(imageOuts[0]);
end;
end else begin
imageOuts[0]:=createImage(imageOutWidth,imageOutHeight);
setOutputParameterImages('outImages',imageOuts);
image.freeImage(imageStandardDeviationOut);
imageStandardDeviationOut:=createImageFromImage(imageOuts[0]);
end;
end;
end;
procedure TFilterHistogramContrast.setParameterInteger( const aName: String; const aValue: Int64);
begin
inherited;
if aName='precision' then begin
analyseROI.setPrecision(aValue);
end else if (aName='gridSpacingWidth') or (aName='gridSpacingHeight') then begin
createImageOut0(parameterImageIn.Image);
end;
end;
procedure TFilterHistogramContrast.Run();
begin
imageIn:=parameterImageIn.Image;
if (imageIn<>nil) then begin
_run();
end;
end;
procedure TFilterHistogramContrast._run();
var
i : Integer;
begin
// blur
if parameterBlurIteration.Value>0 then begin
filterBlur.setParameterImage('inImage',imageIn);
filterBlur.setParameterImage('outImage',imageBlurOut);
i:=parameterBlurIteration.Value;
while i>0 do begin
filterBlur.Run;
Dec(i);
if imageIn<>parameterImageIn.Image then image.freeImage(imageIn);
if i>0 then begin
imageIn:=createImageFromImage(imageBlurOut);
filterBlur.setParameterImage('inImage',imageIn);
end;
end;
end;
if parameterMode.Value='NORMAL' then begin
runNormal;
filterStandardDeviation.setParameterImage('inImage',imageOuts[0]);
filterStandardDeviation.setParameterImage('outImage',imageStandardDeviationOut);
filterStandardDeviation.Run;
copyImageToImage(imageStandardDeviationOut,imageOuts[0]);
end else begin
runShowdetails;
end;
end;
procedure TFilterHistogramContrast.runNormal;
var
rectangleWidth, rectangleHeight : Integer;
rectangleWidthDiv2, rectangleHeightDiv2 : Integer;
roi : TRect;
imageIn, imageOut : PBitmap32 ;
w,h :Integer;
trow, tcol : Integer;
imageInRow, imageInCol : Integer;
trowmax, tcolmax : Integer;
value : Integer;
gridSpacingWidth, gridSpacingHeight : Integer;
begin
imageIn:=parameterImageIn.Image;
eraseImage(imageOuts[0]);
imageOut:=imageOuts[0];
rectangleWidth:=parameterRectangleWidth.Value;
rectangleHeight:=parameterRectangleHeight.Value;
rectangleWidthDiv2:=rectangleWidth div 2;
rectangleHeightDiv2:=rectangleHeight div 2;
h:=imageOut.Height;
w:=imageOut.Width;
gridSpacingWidth:=parameterGridSpacingWidth.Value;
gridSpacingHeight:=parameterGridSpacingHeight.Value;
trowmax:=h-1;
tcolmax:=w-1;
for trow:=0 to trowmax do begin
imageInRow:=trow * gridSpacingHeight;
roi.Top:=imageInRow-rectangleHeightDiv2;
roi.Bottom:=imageInRow+rectangleHeightDiv2;
for tcol:=0 to tcolmax do begin
imageInCol:=tcol * gridSpacingWidth;
roi.Left:=imageInCol-rectangleWidthDiv2;
roi.Right:=imageInCol+rectangleWidthDiv2;
if (roi.Left>=0) and (roi.Right<=imageIn.Width) and (roi.Top>=0) and (roi.Bottom<=imageIn.Height) then begin
// analyse
analyseROI.process(roi);
value:=analyseROI.diffIntegralNormed;
// set gray value with Color32 for optimization
image.setPixel(imageOut,tcol,trow,Color32(value,value,value));
//image.setPixel(imageOut,tcol,trow,clRed32);
end;
end;
end;
end;
procedure TFilterHistogramContrast.runShowdetails;
var
i,j : Integer;
imageOut : PBitmap32;
begin
// analyse the current ROI
analyseROI.process(RegionOfInterest);
// create imageOut
image.freeImage(imageOuts[1]);
imageOuts[1]:=createImage(256,analyseROI.diffMax+1);
setOutputParameterImages('outImages',imageOuts);
imageOut:=outputParameterImageOuts.Images[1];
// show diff
for i:=0 to 255 do begin
for j:=analyseROI.diff[i] downto 0 do begin
image.setPixel(imageOut,i,analyseROI.diffMax-j,clRed32);
end;
end;
// show diff integral
for j:=0 to imageOut.Width-1 do begin
image.setPixel(imageOut,j,imageOut.Height-analyseROI.diffIntegralNormed,clGreen32);
end;
end;
constructor THistogramContrastAnalyseROI.Create;
begin
inherited;
filterHistogram1:=TFilterHistogram.Create;
filterHistogram1.setParameterString('normalize','TRUE');
histogramme1:=filterHistogram1.getOutputParameterArraySingles('histogram');
filterHistogram2:=TFilterHistogram.Create;
filterHistogram2.setParameterString('normalize','TRUE');
histogramme2:=filterHistogram2.getOutputParameterArraySingles('histogram');
end;
destructor THistogramContrastAnalyseROI.Destroy;
begin
inherited;
filterHistogram1.Free;
filterHistogram2.Free;
end;
procedure THistogramContrastAnalyseROI.setImage(aImage: PBitmap32);
begin
filterHistogram1.setParameterImage('inImage',aImage);
filterHistogram2.setParameterImage('inImage',aImage);
end;
procedure THistogramContrastAnalyseROI.setPrecision(aPrecision: Integer);
begin
filterHistogram1.setParameterInteger('precision',aPrecision);
filterHistogram2.setParameterInteger('precision',aPrecision);
end;
procedure THistogramContrastAnalyseROI.process(aROI:TRect);
var
roiWidthDiv2 : Integer;
roi : TRect;
i : Integer;
begin
roiWidthDiv2:=(aROI.Right-aROI.Left) div 2;
roi.Left:=aROI.Left;
roi.Right:=aROI.Left+roiWidthDiv2;
roi.Top:=aROI.Top;
roi.Bottom:=aROI.Bottom;
filterHistogram1.setRegionOfInterest(roi);
filterHistogram1.Run;
roi.Left:=aROI.Left+roiWidthDiv2+1;
roi.Right:=aROI.Right;
roi.Top:=aROI.Top;
roi.Bottom:=aROI.Bottom;
filterHistogram2.setRegionOfInterest(roi);
filterHistogram2.Run;
// calcul diff
FillChar(diff,SizeOf(diff),0);
for i:=0 to 255 do begin
diff[i]:=Abs(Round(histogramme2.Singles[i]-histogramme1.Singles[i]));
end;
// calcul des diff max
//diffMax:=((roi.Right-roi.Left)*(roi.Bottom-roi.Top)) div 2;
diffMax:=255;
diffIntegralMax:=diffMax*20;
// calcul diff integral
diffIntegral:=0;
for i:=0 to 255 do begin
Inc(diffIntegral,diff[i]);
end;
diffIntegralNormed:=(diffIntegral * diffMax) div diffIntegralMax;
if diffIntegralNormed>diffMax then diffIntegralNormed:=diffMax;
end;
end.