unit filterMedian;
(* ***** 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
* Site :
* http://filters.sourceforge.net/
*
* ***** END LICENSE BLOCK ***** *)
{
edurand (filters@edurand.com)
}
interface
uses
filter, fparameters, image, SysUtils;
type
TFilterMedian = class(TFilter)
public
constructor Create; override;
destructor Destroy; override;
procedure Run(); override;
private
parameterPrecision : TParameterInteger;
parameterImageIn, parameterImageOut : TParameterImage;
procedure _run();
end;
implementation
uses
imageIO, Math;
constructor TFilterMedian.Create;
begin
inherited;
parameterImageIn:=addParameterImage('inImage','image to process');
parameterImageOut:=addParameterImage('outImage','output image');
parameterPrecision:=addParameterInteger('precision','',0,10,2);
end;
destructor TFilterMedian.Destroy;
begin
end;
procedure TFilterMedian.Run();
begin
if (parameterImageIn.Image<>nil) and (parameterImageOut.Image<>nil) then begin
_run();
end;
end;
procedure TFilterMedian._run();
var
pSrc, PDest : PColor32Array;
w,h :Integer;
value : Integer;
tIntensity : Integer;
neighbor :Integer;
imageSrcRow, imageSrcCol : Integer;
imageSrcRowmax, imageSrcColmax : Integer;
imageSrcNeighborRow, imageSrcNeighborCol : Integer;
imageSrcNeighborRowmin, imageSrcNeighborColmin : Integer;
imageSrcNeighborRowmax, imageSrcNeighborColmax : Integer;
table : array [0..255] of Integer;
tableColor : array [0..255] of TColor32;
indexOfMedian : Integer;
counter, counterMax : Integer;
indexMin, indexMax : Integer;
begin
h:=parameterImageIn.Image.Height;
w:=parameterImageIn.Image.Width;
neighbor:=parameterPrecision.Value;
pSrc:=parameterImageIn.Image.Bits;
imageSrcRowmax:=h-1;
imageSrcColmax:=w-1;
for imageSrcRow:=0 to imageSrcRowmax do begin
pDest:=parameterImageOut.Image.Bits;
Inc(pDest,imageSrcRow*w);
for imageSrcCol:=0 to imageSrcColmax do begin
FillChar(table,256*SizeOf(Integer),0);
//FillChar(table,256*SizeOf(Integer),0);
//FillChar(tableColor,256*SizeOf(TColor32),0);
counterMax:=0;
indexMin:=256;
indexMax:=-1;
//
imageSrcNeighborRowmin:=imageSrcRow-neighbor; if imageSrcNeighborRowmin<0 then imageSrcNeighborRowmin:=0;
imageSrcNeighborColmin:=imageSrcCol-neighbor; if imageSrcNeighborColmin<0 then imageSrcNeighborColmin:=0;
imageSrcNeighborRowmax:=imageSrcRow+neighbor; if imageSrcNeighborRowmax>imageSrcRowmax then imageSrcNeighborRowmax:=imageSrcRowmax;
imageSrcNeighborColmax:=imageSrcCol+neighbor; if imageSrcNeighborColmax>imageSrcColmax then imageSrcNeighborColmax:=imageSrcColmax;
for imageSrcNeighborRow:=imageSrcNeighborRowmin to imageSrcNeighborRowmax do begin
for imageSrcNeighborCol:=imageSrcNeighborColmin to imageSrcNeighborColmax do begin
value:=pSrc[imageSrcNeighborRow*w+imageSrcNeighborCol];
tIntensity:=Intensity(value);
Inc(table[tIntensity]);
tableColor[tIntensity]:=value;// ok, eraze last one if exist, but not inportant
Inc(counterMax);
if tIntensity<indexMin then indexMin:=tIntensity;
if tIntensity>indexMax then indexMax:=tIntensity;
end;
end;
// search the median
counterMax:=Trunc(counterMax/2)+1;
counter:=0;
indexOfMedian:=indexMin;
while (indexOfMedian<=indexMax) and (counter<=counterMax) do begin
Inc(counter,table[indexOfMedian]);
Inc(indexOfMedian);
end;
Dec(indexOfMedian);
// set the color of the nucleus to the color of the median
pDest^[0]:=tableColor[indexOfMedian];
Inc(pDest);
end;
end;
end;
{ method by ordering
procedure TFilterMedian._run();
var
pSrc, PDest : PColor32Array;
w,h :Integer;
value : Integer;
tIntensity : Integer;
neighbor :Integer;
imageSrcRow, imageSrcCol : Integer;
imageSrcRowmax, imageSrcColmax : Integer;
imageSrcNeighborRow, imageSrcNeighborCol : Integer;
imageSrcNeighborRowmin, imageSrcNeighborColmin : Integer;
imageSrcNeighborRowmax, imageSrcNeighborColmax : Integer;
indexOfMedian : Integer;
counter, counterMax : Integer;
table, tableOrdered : array of Integer;
tableColor : array of TColor32;
i, j : Integer;
max, indexMax : Integer;
c : TColor32;
begin
h:=parameterImageIn.Image.Height;
w:=parameterImageIn.Image.Width;
neighbor:=parameterPrecision.Value;
counterMax:=sqr(neighbor*2+1);
SetLength(table,counterMax);
SetLength(tableColor,counterMax);
SetLength(tableOrdered,counterMax);
pSrc:=parameterImageIn.Image.Bits;
imageSrcRowmax:=h-1;
imageSrcColmax:=w-1;
for imageSrcRow:=0 to imageSrcRowmax do begin
pDest:=parameterImageOut.Image.Bits;
Inc(pDest,imageSrcRow*w);
for imageSrcCol:=0 to imageSrcColmax do begin
counter:=0;
//
imageSrcNeighborRowmin:=imageSrcRow-neighbor; if imageSrcNeighborRowmin<0 then imageSrcNeighborRowmin:=0;
imageSrcNeighborColmin:=imageSrcCol-neighbor; if imageSrcNeighborColmin<0 then imageSrcNeighborColmin:=0;
imageSrcNeighborRowmax:=imageSrcRow+neighbor; if imageSrcNeighborRowmax>imageSrcRowmax then imageSrcNeighborRowmax:=imageSrcRowmax;
imageSrcNeighborColmax:=imageSrcCol+neighbor; if imageSrcNeighborColmax>imageSrcColmax then imageSrcNeighborColmax:=imageSrcColmax;
for imageSrcNeighborRow:=imageSrcNeighborRowmin to imageSrcNeighborRowmax do begin
for imageSrcNeighborCol:=imageSrcNeighborColmin to imageSrcNeighborColmax do begin
value:=pSrc[imageSrcNeighborRow*w+imageSrcNeighborCol];
tIntensity:=Intensity(value);
table[counter]:=tIntensity;
tableColor[counter]:=value;
Inc(counter);
end;
end;
indexOfMedian:=Trunc((counter-1)/2)+1;
for i:=0 to indexOfMedian do begin
max:=-1;
j:=0;
while j<counterMax do begin
if table[j]>max then begin
max:=table[j];
indexMax:=j;
end;
Inc(j);
end;
table[indexMax]:=-1;
end;
// search the median
// set the color of the nucleus to the color of the median
pDest^[0]:=tableColor[indexMax];
Inc(pDest);
end;
end;
end;
}
end.