File : morphological.adb
-- -*- Mode: Ada -*-
-- Filename : morphological.adb
-- Description : Package d'opérateurs morphologiques
-- Package d'opérators morphologiques
with Open_Image.Greyscale_Image;
use Open_Image.Greyscale_Image;
with Open_Image;use Open_Image;
Package body Morphological is
-- Définition d'un pixel, en autorisant l'attribution d'un pixel en dehors de
-- l'image, le pixel n'est alors pas définit
procedure Set_Pixel_Unbounded(M : in out Unbounded_image ; X,Y:in Integer; Value : in pixel_value_type) is
begin
if X>=1 and X<=Integer(Columns(M)) then
if Y>=1 and Y<=Integer(Rows(M)) then
Set_Pixel(M,Column_Index_Type(X),Row_Index_Type(Y),value);
end if;
end if;
end;
-- Récupération d'un pixel en attribuant une valeur lorsque le pixel
-- est en dehors de l'image
function Get_Pixel_unbounded(Img:in Unbounded_Image;X,Y: in Integer ;Default:in Pixel_Value_Type) return Pixel_Value_Type is
RetVal : pixel_value_type := default;
begin
if X>=1 and X<=Integer(Columns(Img)) then
if Y>=1 and Y<=Integer(rows(Img)) then
Retval := Get_Pixel(Img,Column_Index_Type(X),Row_Index_Type(Y));
end if;
end if;
return Retval;
end;
function Max(X,Y:in pixel_value_type) return pixel_value_type is
begin
if X>Y then
return X;
else
return Y;
end if;
end;
function Min(X,Y:in pixel_value_type) return pixel_value_type is
begin
if X<Y then
return X;
else
return Y;
end if;
end;
function GetMax(M : in unbounded_image;Pattern : in unbounded_image; X: in Column_Index_Type ; Y:in row_index_type ) return pixel_value_type is
PatternMaxpx : Pixel_Value_Type := 255;
Retval : pixel_value_type:= 0;
begin
-- Initialisation De La Premiere Variable
for I in 1..Columns(Pattern) loop
for J in 1..rows(Pattern) loop
-- teste si on est dans la matrice
if Get_Pixel(pattern,i,j)=Patternmaxpx then
Retval := Max(Retval,Get_Pixel_unbounded(M,Integer(X+I-1),Integer(Y+J-1),0));
end if;
end loop;
end loop;
return Retval;
end;
function Dilate(Imgin : in Unbounded_image ;Pattern : in Unbounded_image ) return Unbounded_Image is
RetImg : unbounded_image;
Pixvalue,alt : Pixel_Value_type;
begin
Retimg := Imgin; -- Par copie
for j in 1..Rows(Imgin) loop
for i in 1..Columns(Imgin) loop
-- Récupération de l'altitude maximale
Alt := GetMax(imgin,pattern,I,J);
for K in 1..rows(Pattern) loop
for L in 1..columns(Pattern) loop
Pixvalue := Get_Pixel_unbounded(retimg,Integer(i+L-1),Integer(j+K-1),0);
if Get_Pixel(Pattern,L,k) = 255 then
set_pixel_unbounded(retimg,Integer(I+L-1),Integer(J+K-1),Max(pixvalue,Alt));
end if;
end loop;
end loop;
end loop;
end loop;
return Retimg;
end;
function Inverse(Imgin : in Unbounded_Image) return Unbounded_Image is
Retval : Unbounded_Image;
begin
Set_Size(Retval,Columns(Imgin),Rows(Imgin));
for I in 1..Columns(Imgin) loop
for J in 1..Rows(Imgin) loop
Set_Pixel(Retval,I,J,255-Get_Pixel(Imgin,I,J));
end loop;
end loop;
return Retval;
end;
function "-"(Left,Right:in Unbounded_Image) return Unbounded_Image is
Retval : Unbounded_Image;
begin
if Columns(Left)/=Columns(Right) or Rows(Left)/=Rows(Right) then
raise Invalid_Size;
end if;
Set_Size(Retval,Columns(left),Rows(left));
for I in 1..Columns(left) loop
for J in 1..Rows(left) loop
if Integer(Get_Pixel(left,I,J))-Integer(Get_Pixel(right,I,J))>=0 then
Set_Pixel(Retval,I,J,Max(0,Get_Pixel(left,I,J)-Get_Pixel(right,I,J)));
else
Set_Pixel(Retval,I,J,0);
end if;
end loop;
end loop;
return Retval;
end;
function "+"(Left,Right:in Unbounded_Image) return Unbounded_Image is
Retval : Unbounded_Image;
begin
if Columns(Left)/=Columns(Right) or Rows(Left)/=Rows(Right) then
raise Invalid_Size;
end if;
Set_Size(Retval,Columns(left),Rows(left));
for I in 1..Columns(left) loop
for J in 1..Rows(left) loop
if Integer(Get_Pixel(left,I,J))+Integer(Get_Pixel(right,I,J))>255 then
Set_Pixel(Retval,I,J,255);
else
Set_Pixel(Retval,I,J,Max(0,Get_Pixel(left,I,J)+Get_Pixel(right,I,J)));
end if;
end loop;
end loop;
return Retval;
end;
-- L'erosion est une dilatation en utilisant une inversion
function Erode(Imgin : in Unbounded_image ;Pattern : in Unbounded_image) return Unbounded_Image is
Retval : Unbounded_Image;
begin
Retval := Inverse(Dilate(Inverse(Imgin),Pattern));
return Retval;
end;
function TopHat(Imgin: in Unbounded_image ; Pattern : in Unbounded_image ) return Unbounded_Image is
Retval : Unbounded_Image;
begin
Retval := Imgin-Dilate(Erode(Imgin,pattern),Pattern);
return Retval;
end;
function Closing(Imgin: in Unbounded_image ; Pattern : in Unbounded_image )
return Unbounded_image
is
Result : Unbounded_image;
begin
return Erode(Dilate(Imgin,Pattern),Pattern);
end Closing;
function Opening(Imgin: in Unbounded_image ; Pattern : in Unbounded_image )
return Unbounded_image
is
Result : Unbounded_image;
begin
return Dilate(Erode(Imgin,Pattern),Pattern);
end Opening;
-- Optimized Version for square patterns ..
-- Fonction utilisée pour les opérateur morphologiques accélérés
-- Les Fonctions accélérées fonctionnent avec des patterns rectangulaires
function GetMax( M : in Unbounded_Image ; PatternSizeX : in Column_Index_Type; PatternSizeY : in Row_Index_Type ; X : Column_Index_Type; Y : Row_Index_Type ) return Pixel_Value_Type is
Retval : pixel_value_type:= 0;
begin
for I in 1..PatternSizeX loop
for J in 1..PatternSizeY loop
Retval := Max(Retval,Get_Pixel_unbounded(M,Integer(X+I-1),Integer(Y+J-1),0));
end loop;
end loop;
return Retval;
end ;
-- faster execution
function Dilate(Imgin : in Unbounded_Image ; SizeX, SizeY : in Integer ) return Unbounded_Image is
RetImg : unbounded_image;
Pixvalue,alt : Pixel_Value_type;
begin
Retimg := Imgin; -- Par copie
for j in 1..Rows(Imgin) loop
for i in 1..Columns(Imgin) loop
-- Récupération de l'altitude maximale
Alt := GetMax(imgin,Column_Index_Type(SizeX), Row_Index_Type(SizeY),I,J);
for K in 1..Row_Index_Type(SizeY) loop
for L in 1..Column_Index_Type(SizeX) loop
Pixvalue := Get_Pixel_unbounded(retimg,Integer(i+L-1),Integer(j+K-1),0);
set_pixel_unbounded(retimg,Integer(I+L-1),Integer(J+K-1),Max(pixvalue,Alt));
end loop;
end loop;
end loop;
end loop;
return Retimg;
end;
function Dilate(Imgin : in Unbounded_Image ; Size : in Integer ) return Unbounded_Image is
RetImg : unbounded_image;
begin
Retimg := Dilate(Imgin,Size,1);
Retimg := Dilate(Retimg, 1,Size);
return Retimg;
end;
-- L'erosion est une dilatation en utilisant une inversion
function Erode(Imgin : in Unbounded_image ;Size : in Integer ) return Unbounded_Image is
Retval : Unbounded_Image;
begin
Retval := Inverse(Dilate(Inverse(Imgin),Size));
return Retval;
end;
function TopHat(Imgin: in Unbounded_image ; Size : in Integer ) return Unbounded_Image is
Retval : Unbounded_Image;
begin
Retval := Imgin-Dilate(Erode(Imgin,size),size);
return Retval;
end;
function Closing(Imgin : in Unbounded_Image; Size : in Integer)
return Unbounded_Image
is
Result : Unbounded_image;
begin
return Erode(Dilate(Imgin,Size),Size);
end Closing;
function Opening(Imgin : in Unbounded_Image; Size : in Integer)
return Unbounded_Image
is
Result : Unbounded_image;
begin
return Dilate(Erode(Imgin,Size),Size);
end Opening;
end Morphological;