Problème pour passer une image en noir et blanc

ender27 Messages postés 7 Date d'inscription mercredi 5 mars 2008 Statut Membre Dernière intervention 2 juin 2008 - 15 mars 2008 à 18:31
ender27 Messages postés 7 Date d'inscription mercredi 5 mars 2008 Statut Membre Dernière intervention 2 juin 2008 - 19 mars 2008 à 21:55
Bonjour à tous,

Je suis un débutant en Delphi (je posséde la version 5).
Je dois réaliser un programme de reconnaissance de caractères pour mon école.

Le problème c'est que je suis coinçé dès le démarrage.
En effet, la reconnaissance de caractères doit s'effectuer sur des images provenant d'une caméra, ce qui signifie que mon programme doit fonctionner pour tout les formats et tailles d'images, mais en plus les images seront en couleurs.

Pour le moment, grâce à tous les codes trouvé sur ce site, j'ai pu réaliser l'ouverture, l'enregistrement, le passage au niveaux de gris et en négatif.
Mon problème se situe au niveau de la binarisation de l'image en niveaux de gris. J'ai utilisé un code trouvé sur votre site, mais j'obtiens une erreur :

"Classe d'exception EInvalidGraphicOperation" et "Indice ligne hors limite"

Il semblerait qu'il y ait un soucis avec le Scanline employé, mais je n'arrive pas à corriger cette erreur.
Voici mon code :

unit ouvrir_image;


interface


uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtDlgs, ExtCtrls, StdCtrls, Menus, Jpeg, FileCtrl, ActnList, ComObj, Buttons,
  ComCtrls;




type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    labelfichierouvert: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Image1: TImage;
    Bevel1: TBevel;
    OpenPictureDialog1: TOpenPictureDialog;
    SavePictureDialog1: TSavePictureDialog;
    binbutton: TButton;
    TrackSeuil: TTrackBar;
    Label4: TLabel;
    procedure Button4Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure binbuttonClick(Sender: TObject);
    procedure TrackSeuilChange(Sender: TObject);
  private
    { Déclarations privées }
    Bmp_Dest:TBitmap;
    Bmp_Dest2:TBitmap;
  public
    { Déclarations publiques }
  end;


var
  Form1: TForm1;
  ARect: TRect;
  Bmp_Src:TBitmap;
  procedure seuil(source:TBitmap;seuil:integer);


implementation


{$R *.DFM}




procedure TForm1.Button4Click(Sender: TObject);  //procédure pour la fermeture du programme
begin
     Close;
end;


procedure TForm1.Button3Click(Sender: TObject); //enregistrement de l'image
begin
     if SavePictureDialog1.Execute then
     begin
          Image1.Picture.SaveToFile(SavePictureDialog1.FileName);
     end;
end;


procedure TForm1.Button1Click(Sender: TObject);  //ouverture d'une image
var
  ImgExt : string;
  Jpeg: TJpegImage;
begin
  if OpenPictureDialog1.Execute then
  begin
    //le traitement se fera d'après l'extension du fichier
    ImgExt := LowerCase(ExtractFileExt(OpenPictureDialog1.FileName));


    //Pour une image Bitmap
    if ImgExt = '.bmp' then
      Image1.Picture.Bitmap.LoadFromFile(OpenPictureDialog1.FileName);


    //Pour une image Jpeg    if (ImgExt '.jpg') or (ImgExt '.jpeg') then
    begin
      Jpeg := TJpegImage.Create;
      try
        Jpeg.LoadFromFile(OpenPictureDialog1.FileName);
        //copie de l'image du jpeg dans un bitmap
        Image1.Picture.Bitmap.Assign(Jpeg);
      finally
        Jpeg.Free;
      end;


    end; {if (ImgExt '.JPG') or (ImgExt '.JPEG')}


    //Pour une icone
    if ImgExt = '.ico' then
      Image1.Picture.Icon.LoadFromFile(OpenPictureDialog1.FileName);


    //Pour une image wmf et emf
    if Pos(ImgExt, GraphicFileMask(TMetaFile)) <> 0 then
      Image1.Picture.Metafile.LoadFromFile(OpenPictureDialog1.FileName);


    //afficher le nom du fichier dans un espace restreint
    Label1.Caption := MinimizeName(OpenPictureDialog1.FileName,
                                             Label1.Canvas,
                                             Label1.Width);
    //Récupère la hauteur et la largeur de l'image et les affiche dans deux labels
    Label2.Caption:=IntToStr(Image1.Picture.Bitmap.Width)+' pixels';
    Label3.Caption:=IntToStr(Image1.Picture.Bitmap.Height)+' pixels';
    end;
end;



procedure seuil(source:TBitmap;seuil:integer);
var
   rw,i,j,k,l:integer;
   p:pbytearray;
   begin
        source.PixelFormat:=pf32bit;
         // calcul la longeur réelle de la ligne en mémoire
         rw := source.Width*4;
         p:=source.ScanLine[source.Height-1];      ///////le message d'erreur s'affiche ici lors de l'utilisation du debugger
         for j:=0 to source.Height-1 do
         for i:=0 to source.Width-1 do
         begin
              k:=i*4+j*rw;
              // passage en niveau de gris
              l:=(76*p[k+2]+150*p[k+1]+30*p[k+0]) div 256;
              //suivant le seuil choisi, c'est noir ou blanc
              if l<seuil then l:=0 else l:=255;
              // on met à jour le bitmap
              p[k+2]:=l;
              p[k+1]:=l;
              p[k+0]:=l;
         end;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
     Bmp_Src:=TBitmap.Create;
     Bmp_Src.Assign(Image1.Picture.Bitmap);
     Bmp_Src.PixelFormat:=pf32bit;
end;


procedure TForm1.binbuttonClick(Sender: TObject);  //binarisation d'une image
begin
     Image1.Picture.Bitmap.Assign(Bmp_Src);
     seuil(Image1.Picture.Bitmap,TrackSeuil.Position);
end;


procedure TForm1.TrackSeuilChange(Sender: TObject);    //pour la Trackbar
begin
     Label4.Caption:='Seuil : '+inttostr(TrackSeuil.Position*100 div 256)+'%';
     Image1.Picture.Bitmap.Assign(Bmp_Src);
     seuil(Image1.Picture.Bitmap,TrackSeuil.Position);
end;


end.

Merci de m'aider

ender27

1 réponse

ender27 Messages postés 7 Date d'inscription mercredi 5 mars 2008 Statut Membre Dernière intervention 2 juin 2008
19 mars 2008 à 21:55
Bonjour à tous,

J'ai réussi à trouver la solution à mon problème à force de chercher.
En effet le scanline était mal placé, regardez ci dessous où j'aurais du le mettre des le début :

procedure seuil(source:TBitmap;seuil:integer);
var
   rw,i,j,k,l:integer;
   p:pbytearray;
   Bitmap_temp : TBitmap;
   begin
        // On crée une bitmap temporaire identique à la bitmap couleur courante
        // Pour pouvoir jouer sur le contraste et le seuil
        Bitmap_temp := TBitmap.Create;
        // affecte les proriétés de BitmapCapturee à BitmapTemp
        Bitmap_temp.Assign(source);
        // On met à jour le format de la bitmap courante
        source.PixelFormat:=pf32bit;
         // calcul la longeur réelle de la ligne en mémoire
         rw := source.Width*4;
         for j:=0 to Bitmap_temp.Height-1 do
         begin
              p:=source.ScanLine[source.Height-1];          //mettre le scanline à l'intérieur de la première boucle for
              for i:=0 to Bitmap_temp.Width-1 do
              begin
                   k:=i*4+j*rw;
                   // passage en niveau de gris
                   l:=(76*p[k+2]+150*p[k+1]+30*p[k+0]) div 256;
                   //suivant le seuil choisi, c'est noir ou blanc
                   if l<seuil then l:=0 else l:=255;
                   // on met à jour le bitmap
                   p[k+2]:=l;
                   p[k+1]:=l;
                   p[k+0]:=l;
              end;
         end;
   // Destruction de l'image temporaire
     Bitmap_Temp.Free;
end;

Mais maintenant j'ai un autre problème, la binarisation ne s'effectue pas, j'obtiens un TBitmap vide???????

Quelqu'un peut il m'aider?

ender27
0
Rejoignez-nous