IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Recherche d’un algo performant pour combler des trous


Sujet :

Delphi

  1. #1
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    765
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 765
    Points : 960
    Points
    960
    Par défaut Recherche d’un algo performant pour combler des trous
    Bonjour,

    Je cherche un algo performant pour combler des trous dans un bitmap ou dans un tableau à 2 dimension, c’est égale.

    Le but, c’est pas de prendre les valeurs attenantes et d’attribuer la valeur moyenne, mais de prendre la valeur la plus présente autours.

    Jj’avoue n’avoir pas trouvé d’algo (ou de fonction) performante pour les boucher.

    Auriez-vous des idées / suggestions ?

    Merci d’avance de vos retours…

  2. #2
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par der§en Voir le message
    Jj’avoue n’avoir pas trouvé d’algo (ou de fonction) performante pour les boucher.
    bonjour cher chambourdin, intéressez-vous au principe d'interpolation linéaire..
    sinon oui si vous faites la moyenne vous obtenez un flou gaussien sauf erreur de ma part

  3. #3
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 346
    Points : 3 124
    Points
    3 124
    Par défaut
    Bonjour,
    oui ça s’apparente aux calculs de filtres sur des images. Mais que faire quand toutes les valeurs autour sont toutes différentes ?

    A+
    Charly

  4. #4
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    765
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 765
    Points : 960
    Points
    960
    Par défaut
    Dans mon contexte, je suis sur d’avoir au moins 2 valeurs identiques sur les 8 attenante, et ce n’est pas un flou gaussien que je veux mais juste la valeur la plus présente autour.

    Une idée / suggestion ?

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 045
    Points : 40 963
    Points
    40 963
    Billets dans le blog
    62
    Par défaut
    FMX ou VCL ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  6. #6
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 346
    Points : 3 124
    Points
    3 124
    Par défaut
    Bonjour,
    dans un bitmap, il faut déjà utiliser Scanline, puis tester les 8 valeurs des pixels voisins. Mais il y aura au moins 3 valeurs par pixels ?

    A+
    Charly

  7. #7
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 300
    Points
    11 300
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Je peux concevoir que si on construit un tableau 2D avec des valeurs mesurées, il puisse y avoir des cellules non affectées s'il existe des mesures manquantes.
    Si le but est de ne remplir ces absences qu'avec des valeurs déjà mesurées, comment la méthode devra-t-elle gérer le cas de figure suivant ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    1 1 2 2 
    1 A B 1
    2 2 1 2
    Si on affecte le voisin le plus représenté, résultat potentiellement différent suivant qu'on part de TopLeft (A -> 1 et B 1 ou 2) ou DownRight (B -> 2 et A 1 ou 2)
    Pour un BitMap, faut-il retenir la couleur ou la luminosité la plus représentée ?
    En savoir plus sur le besoin permettrait pê de mieux y répondre.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  8. #8
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    765
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 765
    Points : 960
    Points
    960
    Par défaut
    De préférence en FMX, mais ce n’est pas essentiel.

    Pour A et B, peux importe comme on cherche, l’essentiel ici aussi c’est de bouché le trou de manière performante avec la valeur la plus présente (la valeur importe peux que cela soit bouché avec 1 ou 2 dans l’exemple proposé) le point important c’est d’avoir un algo rapide…

    Si cela vous semble plus simple, je suis preneur d’un algo pour un array en 2D !

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 045
    Points : 40 963
    Points
    40 963
    Billets dans le blog
    62
    Par défaut
    S'il s'agit de FMX as-tu fait un tour du côté des effets ?
    TPixelateEffect ?
    je n'ai utilisé les effets sur une image qu'avec une mise en niveau de gris TMonochromeEffect voir ici mais ça pourrait te donner des pistes
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  10. #10
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 421
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 421
    Points : 5 820
    Points
    5 820
    Par défaut
    Salut

    si je comprend bien tu veux prendre la valeur la plus présente dans les 8 directions confondu
    au départ je pensais a une matrice de convolution mais a priori ce que tu demande est un chouilla diffèrent
    donc le plus simple est de prendre un tableau dynamique de six Valeur maximal
    a chaque valeur identique que tu trouve tu incrémente le nombre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    TValeur = Record 
       Coul : TColor ;
       Nb   : Integer;
    End;
    TabColor : Array of TValeur;
    Function GetColor(x,y : Integer) : TColor;
    Function SetColor(x,y : Integer;Col : TColor);
    [42,42,55]
    [42,-1,55]
    [42,55,55]
    si J'ai bien compris c'est le 55 que tu veux
    il te suffit de parcourir ce tableau et de choisir le plus grand nombre ayant le même éléments
    dans notre cas quand il y a égalité et ce sera le premier trouvé (42)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    Function DefMatrice(ox,0y : Integer) : TabColor;
    Const 
      DEPLX : Array[0..8] of integer = (-1,-1,-1, 0, 0, 0, 1, 1, 1);
      DEPLY : Array[0..8] of integer = (-1, 0,  1,-1, 0, 1,-1, 0, 1);
    Var 
      Tab : TabColor;
    Begin 
      Tab = nil;
     
      For i := 0 To 8 Do 
      begin
        if i  <> 4 Then // Pixel recherché 
        Begin 
           Col := GetColor(ox+DEPLX[i],DEPLY[i]+0y) ;
           Ipos  := ColorExist(Tab);
           If Ipos = -1 Then 
           Begin 
              Setlength(Tab,length(Tab)+1); 
              Tab[High(Tab)].Coul :=  Col;
              Tab[High(Tab)].Nb  := 1;
           end
           else 
              Tab[Ipos].NbVal:= Tab[Ipos].NbVal+1;
        End;
       Result := Tab;
    End; 
     
    Function MaxValue(Tab : TabColor) : TColor;
    Begin 
       Ipos := -1;
       nb := -1;  
       For i:= Low(Tab) to High(Tab) Do 
         if   Tab[i].Nb > nb Then 
           Ipos :=  i
       Result := Tab[Ipos].Coul
    End;
    dans le corps du programme lorsque tu a besoin de modifier ta couleur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      ...
      Col := MaxValue(DefMatrice(Ximg,Yimg));
      SetColor(Ximg,Yimg,Col);
      ...
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 696
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 696
    Points : 13 135
    Points
    13 135
    Par défaut
    En supposant que les "trous" sont des zéros et qu'on a 255 valeurs possibles :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function GetMostOccurrence(const aValues :TArray<byte>) :byte; inline;
    var
      Counters :array[byte] of byte;
    begin
      Result := 0;
      ZeroMemory(@Counters, SizeOf(Counters));
     
      // Remplissage
      for var i := 0 to High(aValues) do
        inc(Counters[aValues[i]]);
     
      // Contrôle
      for var i := 0 to High(aValues) do
        case Counters[aValues[i]] of
          1    : ;                                         // On ne perd pas de temps à assigner une valeur
          2    : if Result = 0 then Result := aValues[i];  // Gardée si rien trouvé de mieux avant
          3    : Result := aValues[i];                     // Mieux que 2 (sic)
          else   Exit(aValues[i]);                         // Dès 4 c'est sûr qu'il n'y a pas mieux
        end;
     
      // Si 8 valeurs différentes
      if Result = 0 then
        Result := aValues[0];
    end;

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par der§en Voir le message
    Jj’avoue n’avoir pas trouvé d’algo (ou de fonction) performante pour les boucher.
    Pourquoi ne pas proposer un code existant sur lequel on pourrait travailler à l'améliorer ?

    L'analyse des 8 cases adjacentes, je me demande si l'on pourrait aussi prendre des bouts de code du Solver du Sudoku, pas la résolution mais au moins la partie parcours de la matrice,

    De mémoire, j'avais tenté de créer des sortes de liste chainée des cellules adjacentes pour éviter de faire plusieurs la même itération sur le offset X et offset Y, c'est valable uniquement pour un grand nombre de relecture mais si c'est un algo en une seule passe, il n'y a pas grand chose à améliorer pour les boucles sur le tableau

    Pour la version Image, il te faut 3 buffer de ScanLine que tu peux assimiler à une matrice temporaire de 3 lignes, quand tu passes à la ligne suivante, il te suffit de "déplacer" cette matrice (retirer la première, décalage, ajout de la dernière, uniquement au niveau des pointeurs, surtout pas de copie d'array)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 421
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 421
    Points : 5 820
    Points
    5 820
    Par défaut
    Salut

    le postula de 255 couleurs est hasardeux non
    j'imagine qu'il doit être plus proche des 32000 couleurs


    j'avais pensais au compteur par dénombrement mais je n'ai pas trouvé de solution adéquate me convenant

    j'ai choisi des matrice de 3*3 justement pour la rapidité de parcourt je pense qu'il y a surement des optimisations a faire mais
    parcourir 9 case maxi me semble plutôt rapide a faire

    cordialement
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  14. #14
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par anapurna Voir le message
    le postula de 255 couleurs est hasardeux non
    j'imagine qu'il doit être plus proche des 32000 couleurs
    cordialement
    Pour 255 ou 65535 couleurs (8bit et 16bit), un algo utilisant une sorte de table de hash comme la fonction GetMostOccurrence de AndNotor est rapide, pas trop couteux en mémoire, mais on a beaucoup d'itération sur la plage de valeurs.
    Pour un 24Bits 16 millions de couleurs faut abandonner cette pratique, ci-dessus codé en 8Bit mais cela se converti en 24 bit facilement

    Je te laisse jouer sur le Move ou pas,
    Activer - Move MatrixSource : modifie l'original
    Désactiver - Move MatrixSource[1]^ : cela permet soit d'avoir juste les bouche-trous

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    unit FileHole_MainForm;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ComCtrls;
     
    type
      TForm1 = class(TForm)
        btnBuild: TButton;
        edWidth: TLabeledEdit;
        edHeight: TLabeledEdit;
        Image1: TImage;
        pcImages: TPageControl;
        tsImageOriginale: TTabSheet;
        tsImageFilled: TTabSheet;
        pnlActionTop: TPanel;
        Image2: TImage;
        btnFill: TButton;
        procedure btnBuildClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure btnFillClick(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.btnBuildClick(Sender: TObject);
    var
      X: Integer;
      Y: Integer;
      Line: PByteArray;
    begin
      Image1.AutoSize := False;
      try
        Image1.Picture.Assign(nil);
     
        Image1.Picture.Bitmap.Width := StrToInt(edWidth.Text);
        Image1.Picture.Bitmap.Height := StrToInt(edHeight.Text);
        Image1.Picture.Bitmap.PixelFormat := pf8bit; // Comme Andnotor pour du 0 à 255
     
        Image1.Picture.Bitmap.Canvas.Lock(); // Delphi n'a pas de BeginUpdate pour le Canvas ???
        try
          for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
          begin
            Line := Image1.Picture.Bitmap.ScanLine[Y];
     
            for X := 0 to Image1.Picture.Bitmap.Width - 1 do
            begin
             if LongBool(Random(4)) then
                Line[X] := 254 - Random(6) //Random(High(Byte) - 1) + 1
              else
                Line[X] := 0;
            end;
          end;
        finally
          Image1.Picture.Bitmap.Canvas.Unlock();
        end;
      finally
        Image1.AutoSize := True;
      end;
    end;
     
    procedure TForm1.btnFillClick(Sender: TObject);
    type
      TOccurrence = record
        Value: Byte;
        Counter: Integer;
      end;
    var
      Occurrences: array[1..8] of TOccurrence;
      OccurrenceHigh: Integer;
      Occurrence: TOccurrence;
     
      function IndexOfOccurrence(B: Byte): Integer;
      begin
        for Result := Low(Occurrences) to OccurrenceHigh do
          if Occurrences[Result].Value = B then
            Exit;
     
        Result := -1;
      end;
     
      procedure UpdateOccurrence(B: Byte);
      var
        OccurrenceFound: Integer;
      begin
        if B > 0 then
        begin
          OccurrenceFound := IndexOfOccurrence(B);
          if OccurrenceFound <= 0 then
          begin
            Inc(OccurrenceHigh);
            Occurrences[OccurrenceHigh].Value := B;
            OccurrenceFound := OccurrenceHigh;
          end;
     
          Inc(Occurrences[OccurrenceFound].Counter);
     
          if Occurrence.Counter < Occurrences[OccurrenceFound].Counter then
            Occurrence := Occurrences[OccurrenceFound];
        end;
      end;
     
     
    var
      X: Integer;
      Y: Integer;
      MatrixSource: array[0..2] of PByteArray;
      MatrixDestination: array[0..2] of PByteArray;
      I: Integer;
     
    begin
      Image2.AutoSize := False;
      try
        Image2.Picture.Assign(nil);
     
        Image2.Picture.Bitmap.Width := Image1.Picture.Bitmap.Width;
        Image2.Picture.Bitmap.Height := Image1.Picture.Bitmap.Height;
        Image2.Picture.Bitmap.PixelFormat := pf8bit; // Comme Andnotor pour du 0 à 255
     
        Image2.Picture.Bitmap.Canvas.Lock();
        try
          ZeroMemory(@MatrixSource, SizeOf(MatrixSource));
          ZeroMemory(@MatrixDestination, SizeOf(MatrixDestination));
     
          if Image1.Picture.Bitmap.Height >= 2 then
          begin
            MatrixSource[2] := Image1.Picture.Bitmap.ScanLine[1];
            MatrixDestination[2] := Image2.Picture.Bitmap.ScanLine[1];
          end;
     
          for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
          begin
            MatrixSource[1] := Image1.Picture.Bitmap.ScanLine[Y];
            // Destination différente de la source, le calcul ne s'influence pas lui-même, cela peut créer des zones incalculables mais c'est d'autant plus intéressant
            MatrixDestination[1] := Image2.Picture.Bitmap.ScanLine[Y];
            // Altération de l'image d'origine, impact les couleurs calculées seront utilisées pour les calculs suivants
            // Move(MatrixSource, MatrixDestination, SizeOf(MatrixDestination));
            // Intéressant de générer une matrice séparée, on voit uniquement les zones bouchées
            //Move(MatrixSource[1]^, MatrixDestination[1]^, Image1.Picture.Bitmap.Width * SizeOf(Byte));
     
            for X := 0 to Image1.Picture.Bitmap.Width - 1 do
            begin
              if MatrixSource[1, X] = 0 then
              begin
                OccurrenceHigh := 0;
                ZeroMemory(@Occurrences, SizeOf(Occurrences));
                ZeroMemory(@Occurrence, SizeOf(Occurrence));
     
                if Assigned(MatrixSource[0]) then
                  for I := 0 to 2 do
                    UpdateOccurrence(MatrixSource[0, I]);
     
                UpdateOccurrence(MatrixSource[1, 0]);
                UpdateOccurrence(MatrixSource[1, 2]);
     
                if Assigned(MatrixSource[2]) and (Occurrence.Counter < 4) then
                  for I := 0 to 2 do
                    UpdateOccurrence(MatrixSource[2, I]);
     
                if Occurrence.Counter > 1 then
                  MatrixDestination[1, X] := Occurrence.Value
                else
                  MatrixDestination[1, X] := 255; // Qui favoriser en cas d'égalité ?
              end;
            end;
     
            for I := 1 to 2 do
            begin
              MatrixSource[I - 1] := MatrixSource[I];
              MatrixDestination[I - 1] := MatrixDestination[I];
            end;
            if Image1.Picture.Bitmap.Height - 1 = Y then
            begin
              MatrixSource[2] := nil;
              MatrixDestination[2] := nil;
            end;
          end;
        finally
          Image2.Picture.Bitmap.Canvas.Unlock();
          Image1.Invalidate; 
        end;
      finally
        Image2.AutoSize := True;
      end;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Randomize();
    end;
     
    end.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    object Form1: TForm1
      Left = 0
      Top = 0
      Caption = 'Form1'
      ClientHeight = 515
      ClientWidth = 705
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object pcImages: TPageControl
        Left = 0
        Top = 41
        Width = 705
        Height = 474
        ActivePage = tsImageOriginale
        Align = alClient
        TabOrder = 0
        ExplicitLeft = 176
        ExplicitTop = 224
        ExplicitWidth = 289
        ExplicitHeight = 193
        object tsImageOriginale: TTabSheet
          Caption = 'Originale'
          ExplicitWidth = 281
          ExplicitHeight = 165
          object Image1: TImage
            Left = 3
            Top = 3
            Width = 105
            Height = 105
          end
        end
        object tsImageFilled: TTabSheet
          Caption = 'Filled'
          ImageIndex = 1
          ExplicitWidth = 281
          ExplicitHeight = 165
          object Image2: TImage
            Left = 3
            Top = 3
            Width = 105
            Height = 105
          end
        end
      end
      object pnlActionTop: TPanel
        Left = 0
        Top = 0
        Width = 705
        Height = 41
        Align = alTop
        Locked = True
        ShowCaption = False
        TabOrder = 1
        ExplicitLeft = 72
        ExplicitTop = 56
        ExplicitWidth = 185
        object btnBuild: TButton
          Left = 118
          Top = 16
          Width = 75
          Height = 25
          Caption = 'Build'
          TabOrder = 0
          OnClick = btnBuildClick
        end
        object edHeight: TLabeledEdit
          Left = 63
          Top = 18
          Width = 49
          Height = 21
          EditLabel.Width = 31
          EditLabel.Height = 13
          EditLabel.Caption = 'Height'
          NumbersOnly = True
          TabOrder = 1
          Text = '512'
        end
        object edWidth: TLabeledEdit
          Left = 8
          Top = 18
          Width = 49
          Height = 21
          EditLabel.Width = 28
          EditLabel.Height = 13
          EditLabel.Caption = 'Width'
          NumbersOnly = True
          TabOrder = 2
          Text = '512'
        end
        object btnFill: TButton
          Left = 199
          Top = 16
          Width = 75
          Height = 25
          Caption = 'Fill'
          TabOrder = 3
          OnClick = btnFillClick
        end
      end
    end

    EDIT : la version 24bit, même code, c'est juste le typage du Byte au TRGBTriple qui change

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
     
    type
      PRGBTripleArray = ^TRGBTripleArray;
      TRGBTripleArray = array[Word] of TRGBTriple;
     
    function ColorToTriple(C: TColor): TRGBTriple;
    begin
      with Result do
      begin
        rgbtRed := GetRValue(C);
        rgbtGreen := GetGValue(C);
        rgbtBlue := GetBValue(C);
      end;
    end;
     
    procedure TForm1.btnBuildClick(Sender: TObject);
    const
      COLORS: array [0..3] of TColor = (clRed, clGreen, clBlue, clYellow);
    var
      X: Integer;
      Y: Integer;
      Line: PRGBTripleArray;
    begin
      Image1.AutoSize := False;
      try
        Image1.Picture.Assign(nil);
     
        Image1.Picture.Bitmap.Width := StrToInt(edWidth.Text);
        Image1.Picture.Bitmap.Height := StrToInt(edHeight.Text);
        Image1.Picture.Bitmap.PixelFormat := pf24bit;
     
        Image1.Picture.Bitmap.Canvas.Lock(); // Delphi n'a pas de BeginUpdate pour le Canvas ???
        try
          for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
          begin
            Line := Image1.Picture.Bitmap.ScanLine[Y];
     
            for X := 0 to Image1.Picture.Bitmap.Width - 1 do
            begin
              if LongBool(Random(8)) then
                Line[X] := ColorToTriple(COLORS[Random(4)])
              else
                Line[X] := ColorToTriple(clBlack);
            end;
          end;
        finally
          Image1.Picture.Bitmap.Canvas.Unlock();
        end;
      finally
        Image1.AutoSize := True;
      end;
    end;
     
    procedure TForm1.btnFillClick(Sender: TObject);
    type
      TOccurrence = record
        Value: TRGBTriple;
        Counter: Integer;
      end;
    var
      Occurrences: array[1..8] of TOccurrence;
      OccurrenceHigh: Integer;
      Occurrence: TOccurrence;
     
      function IndexOfOccurrence(RGB: TRGBTriple): Integer;
      begin
        for Result := Low(Occurrences) to OccurrenceHigh do
          with Occurrences[Result] do
            if (Value.rgbtRed = RGB.rgbtRed) and (Value.rgbtGreen = RGB.rgbtGreen) and (Value.rgbtBlue = RGB.rgbtBlue) then
              Exit;
     
        Result := -1;
      end;
     
      procedure UpdateOccurrence(RGB: TRGBTriple);
      var
        OccurrenceFound: Integer;
      begin
        if RGB.rgbtRed + RGB.rgbtGreen + RGB.rgbtBlue > 0 then
        begin
          OccurrenceFound := IndexOfOccurrence(RGB);
          if OccurrenceFound <= 0 then
          begin
            Inc(OccurrenceHigh);
            Occurrences[OccurrenceHigh].Value := RGB;
            OccurrenceFound := OccurrenceHigh;
          end;
     
          Inc(Occurrences[OccurrenceFound].Counter);
     
          if Occurrence.Counter < Occurrences[OccurrenceFound].Counter then
            Occurrence := Occurrences[OccurrenceFound];
        end;
      end;
     
     
    var
      X: Integer;
      Y: Integer;
      MatrixSource: array[0..2] of PRGBTripleArray;
      MatrixDestination: array[0..2] of PRGBTripleArray;
      I: Integer;
      RGB: TRGBTriple;
    begin
      Image2.AutoSize := False;
      try
        Image2.Picture.Assign(nil);
     
        Image2.Picture.Bitmap.Width := Image1.Picture.Bitmap.Width;
        Image2.Picture.Bitmap.Height := Image1.Picture.Bitmap.Height;
        Image2.Picture.Bitmap.PixelFormat := pf24bit;
     
        Image2.Picture.Bitmap.Canvas.Lock();
        try
          ZeroMemory(@MatrixSource, SizeOf(MatrixSource));
          ZeroMemory(@MatrixDestination, SizeOf(MatrixDestination));
     
          if Image1.Picture.Bitmap.Height >= 2 then
          begin
            MatrixSource[2] := Image1.Picture.Bitmap.ScanLine[1];
            MatrixDestination[2] := Image2.Picture.Bitmap.ScanLine[1];
          end;
     
          for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
          begin
            MatrixSource[1] := Image1.Picture.Bitmap.ScanLine[Y];
            // Destination différente de la source, le calcul ne s'influence pas lui-même, cela peut créer des zones incalculables mais c'est d'autant plus intéressant
            MatrixDestination[1] := Image2.Picture.Bitmap.ScanLine[Y];
            // Altération de l'image d'origine, impact les couleurs calculées seront utilisées pour les calculs suivants
            // Move(MatrixSource, MatrixDestination, SizeOf(MatrixDestination));
            // Intéressant de générer une matrice séparée, on voit uniquement les zones bouchées
            //Move(MatrixSource[1]^, MatrixDestination[1]^, Image1.Picture.Bitmap.Width * SizeOf(TRGBTriple));
     
            for X := 0 to Image1.Picture.Bitmap.Width - 1 do
            begin
              RGB :=  MatrixSource[1, X];
              if RGB.rgbtRed + RGB.rgbtGreen + RGB.rgbtBlue = 0 then
              begin
                OccurrenceHigh := 0;
                ZeroMemory(@Occurrences, SizeOf(Occurrences));
                ZeroMemory(@Occurrence, SizeOf(Occurrence));
     
                if Assigned(MatrixSource[0]) then
                  for I := 0 to 2 do
                    UpdateOccurrence(MatrixSource[0, I]);
     
                UpdateOccurrence(MatrixSource[1, 0]);
                UpdateOccurrence(MatrixSource[1, 2]);
     
                if Assigned(MatrixSource[2]) and (Occurrence.Counter < 4) then
                  for I := 0 to 2 do
                    UpdateOccurrence(MatrixSource[2, I]);
     
                if Occurrence.Counter > 1 then
                  MatrixDestination[1, X] := Occurrence.Value
                else
                  MatrixDestination[1, X] := ColorToTriple(clWhite); // Qui favoriser en cas d'égalité ?
              end;
            end;
     
            for I := 1 to 2 do
            begin
              MatrixSource[I - 1] := MatrixSource[I];
              MatrixDestination[I - 1] := MatrixDestination[I];
            end;
            if Image1.Picture.Bitmap.Height - 1 = Y then
            begin
              MatrixSource[2] := nil;
              MatrixDestination[2] := nil;
            end;
          end;
        finally
          Image2.Picture.Bitmap.Canvas.Unlock();
          Image1.Invalidate;
        end;
      finally
        Image2.AutoSize := True;
      end;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Randomize();
    end;
     
    end.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  15. #15
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    765
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 765
    Points : 960
    Points
    960
    Par défaut
    Merci pour vos propositions

    Je pense m’orienter vers la suggestion d’Anapurna

  16. #16
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    S'il y a un besoin de haute performance le mieux est de paralléliser le code. Si la machine sur laquelle tu travailles dispose d'une carte NVDIA tu peux utiliser les GPU et CUDA.
    Je te suggère de regarder ce que j'ai écrit sur le sujet (https://www.developpez.net/forums/bl...a-sous-delphi/)
    Et pour ce qui est de l'algorithme il peut être très simple comme faire un histogramme avec les valeurs valides des huit pixel entourant le pixel manquant et prendre celle qui a la plus haute fréquence.
    Avec CUDA cette opération peut se faire (en fonction de ta carte) pour plusieurs centaine de pixels en même temps.
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. update pour combler des trous
    Par nine dans le forum Requêtes
    Réponses: 11
    Dernier message: 27/10/2018, 18h43
  2. [griddata] Combler des trous d'interpolation
    Par raceng dans le forum MATLAB
    Réponses: 4
    Dernier message: 09/06/2009, 11h05
  3. [C# .Net] Recherche d'une API pour réaliser des diagrammes
    Par arnaudperfect dans le forum ASP.NET
    Réponses: 1
    Dernier message: 12/01/2007, 19h29
  4. recherche d'un logiciel pour créer des interface d'autorun
    Par reeda dans le forum Autres Logiciels
    Réponses: 3
    Dernier message: 13/09/2006, 20h03
  5. Recherche d'un logiciel pour créer des algorithmes
    Par Seb003 dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 02/10/2005, 17h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo