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

Traitement d'images Discussion :

Génération de bruit et filtre(s) d'interpolation


Sujet :

Traitement d'images

  1. #1
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 763
    Points : 4 067
    Points
    4 067
    Billets dans le blog
    2
    Par défaut Génération de bruit et filtre(s) d'interpolation
    Bonjour, il y a quelques semaines je suis tombé sur un article parlant de la génération de bruit (white, additive gaussian, value, perlin.... noise) pour la génération de texture ou de "heightmap". En pascal avec Lazarus j'ai codé un petit truc. Pour l'instant je n'ai fait que le White et le Value noise.

    J'ai trouvé un bibliothèque en c/c++ de code qui fait tout ça très bien FastNoise

    Là ou je pêche c'est sur l'interpolation des valeurs. Voici le code de la génération du bruit

    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
     
     
    function Lerp(Edge0,Edge1,x: Single): Single; Inline;
    begin
      // Fast method = Edge0 + x * (Edge1 - Edge0);
      result := Edge0 * (1 - x) + (Edge1 * x);  // S'assure que le resultat = Edge1 quand x = 1.
    end; 
     
    // Resultat compris entre [-1,1]
    Function TBZValueNoiseGenerator.Noise2D(x, y : Double) : Double;
    var
      fx, cx, fy, cy : Integer;
      vx,vy : Double;
      upperLeftCell,
      upperRightCell,
      lowerLeftCell,
      lowerRightCell,
      interpolatorX,
      interpolatorY,
      upperCells,
      lowerCells : Double;
      InterpolationFilterClass : TBZInterpolationFilterClass;
      InterpolationFilter : TBZCustomInterpolationFilter;
     
    begin
      vx := x * Frequency;
      vy := y * Frequency;
      fx := Math.Floor(vx);
      fy := Math.Floor(vy);
      cx := fx + 1;  // Math.Ceil(vx); 
      cy := fy + 1; //Math.Ceil(vy); 
     
      upperLeftCell  := inherited Noise2D(fx, cy);
      upperRightCell := inherited Noise2D(cx, cy);
      lowerLeftCell  := inherited Noise2D(fx, fy);
      lowerRightCell := inherited Noise2D(cx, fy);
     
      // Interpolation linéaire simple par défaut
      interpolatorX :=  frac(vx); //vx - fx;
      interpolatorY :=  frac(vy); //vy - fy;
      if FSmooth then
      begin
        InterpolationFilterClass := GetBZInterpolationFilter(InterpolationMode);
        InterpolationFilter := InterpolationFilterClass.Create;
        interpolatorX := InterpolationFilter.Filter(interpolatorX);
        interpolatorY := InterpolationFilter.Filter(interpolatorY);
        FreeAndNil(InterpolationFilter);
        //interpolatorX := InterpHermiteFunc(interpolatorX);
        //interpolatorY := InterpHermiteFunc(interpolatorY);
      end;
     
      upperCells := Lerp(upperLeftCell, upperRightCell, interpolatorX);
      lowerCells := Lerp(lowerLeftCell, lowerRightCell, interpolatorX);
     
      Result := Lerp(lowerCells, upperCells, interpolatorY);
    end;

    Avec le Value noise et une fonction d'interpolation de type hermite coder comme ceci, comme dans fastnoise. Commenter dans le code ci-dessus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        //interpolatorX := InterpHermiteFunc(interpolatorX);
        //interpolatorY := InterpHermiteFunc(interpolatorY);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function InterpHermiteFunc(t : Double) : Double;
    begin
      result := t * t * (3 - 2 * t); 
    end;
    Code original :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    private static FN_DECIMAL InterpHermiteFunc(FN_DECIMAL t) { return t * t * (3 - 2 * t); }
     
    private static FN_DECIMAL InterpQuinticFunc(FN_DECIMAL t) { return t * t * t * (t * (t * 6 - 15) + 10); }
    pas de problème l'image générée est correcte

    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
     
      ng := TBZValueNoiseGenerator.Create;
      ng.Seed := StrToInt(edtSeed.Text); //1337
      ng.Frequency := fseFrequency.Value; //0.02
      ng.InterpolationMode := ifmHermit;
      bmp.Clear(clrBlack); 
      for y:=1 to 512 do
      begin
        For x := 1 to 512 do
        begin
          n := 1 + ng.Noise2D(x,y);   //0.5 + n*0.5  
          v := ClampByte(Round((n*255)/2));
          bmp.setPixel(x-1,y-1, BZColor(v,v,v));
        end;
      end;
    Nom : 2019-11-17_124601.png
Affichages : 143
Taille : 128,4 Ko

    Maintenant je dispose de plusieurs fonctions d'interpolation dont je me sert pour le ré-échantillonnage d'images (Hermite, Cosine, Cubic, Mitchell, Blackman, Lagrange, Lanczos3 etc.....)

    Voici le code de quelques filtres, dont le type Hermite

    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
     
     
    function TBZBoxInterpolationFilter.Filter(x: double): double;// Aka nearest neighbour
    begin
      if (x > -0.5) and (x <= 0.5) then
        Result := 1
      else
        Result := 0;
    end;
     
    function TBZCosineInterpolationFilter.Filter(x: Double): Double;
    begin
      Result := 0;
      if Abs(x) < 1 then
        Result := (System.Cos(x * cPI) + 1) * 0.5;
    end;   
     
     // Source : Graphic32, http://paulbourke.net/miscellaneous/interpolation/ 
    function TBZHermitInterpolationFilter.Filter(x: double): double;
    var  
      Z: Integer;
      t, t2, t3, m0, m1, a0, a1, a2, a3, FBias, FTension: Single;
    begin
      FBias:=0;
      FTension :=0;
      t := (1 - FTension) * 0.5;
      m0 := (1 + FBias) * t;
      m1 := (1 - FBias) * t;
     
      Z := Floor(x);
      t := Abs(Z - x);
      t2 := t * t;
      t3 := t2 * t;
     
      a1 := t3 - 2 * t2 + t;
      a2 := t3 - t2;
      a3 := -2 * t3 + 3 * t2;
      a0 := -a3 + 1;
     
      case Z of
        -2: Result := a2 * m1;
        -1: Result := a3 + a1 * m1 + a2 * (m0 - m1);
         0: Result := a0 + a1 * (m0 - m1) - a2 * m0;
         1: Result := -a1 * m0;
      else
        Result := 0;
      end;
    //begin
    //  Result := x * x * (3 - 2 * x);
    end;
    Seulement voila toutes mes fonctions d'interpolation pour le ré-échantillonnage me génère des images découpées, comme celle ci-dessous :

    Nom : 2019-11-17_125409.png
Affichages : 163
Taille : 137,8 Ko

    Je pense que cela est du au fait que le résultat renvoyé n'est pas compris entre entre 0 et 1 (je n'ai pas vérifié, encore)

    Pour finir, je souhaiterai disposer de plus de fonction que Hermite et Quintic.
    Donc :
    - Est-ce que quelqu'un pourrait m'expliquer simplement pourquoi ma fonction function TBZHermitInterpolationFilter.Filter(x: double): double; (et les autres ne fonctionnent pas dans ce cas)
    - Comment puis-je transformer mes fonctions pour quelles deviennent fonctionnelles (pas forcément compatibles, je peux réécrire une nouvelle unité),
    - Sinon connaissez vous un ou plusieurs site référençant ce genre de formules (je n'ai pas trouvé de site pertinent avec Google dans ce sens)

    Merci d'avance de votre aide

    Bon dimanche

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  2. #2
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    décembre 2010
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2010
    Messages : 1 176
    Points : 2 280
    Points
    2 280
    Billets dans le blog
    9
    Par défaut Génération de bruit et filtre(s) d'interpolation
    Bonjour,

    Il n'est pas facile de débrouiller l'écheveau de fonctions discontinues que contient le programme. Apparemment, le niveau de gris local dépend d'une variable réelle (x) dont le lien avec les coordonnées (i, j) du pixel n'a pas été donné - mais cela m'a peut-être échappé. On ne trouve pas trace non plus de grandeurs pseudo-aléatoires auxquelles on devrait s'attendre pour la définition d'un bruit de fond, et sur lesquelles portent l'interpolation.

    Les formules d'interpolation proposées sont définies sur l'intervalle [0 ; 1[ ; or on trouve formulées des conditions qui paraissent inadaptées au domaine précédent, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function TBZBoxInterpolationFilter.Filter(x: double): double;// Aka nearest neighbour
    begin
      if (x > -0.5) and (x <= 0.5) then
        Result := 1
      else
        Result := 0;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function TBZCosineInterpolationFilter.Filter(x: Double): Double;
    begin
      Result := 0;
      if Abs(x) < 1 then
        Result := (System.Cos(x * cPI) + 1) * 0.5;
    end;
    Dans la troisième fonction sont initialisées deux variables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      FBias:=0;
      FTension :=0;
    dont la valeur n'est pas modifiée par la suite.
    Il y a sûrement un oubli: elles auraient dû logiquement être réactualisées.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  3. #3
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 763
    Points : 4 067
    Points
    4 067
    Billets dans le blog
    2
    Par défaut
    Bonjour
    Citation Envoyé par wiwaxia Voir le message
    Bonjour,

    Il n'est pas facile de débrouiller l'écheveau de fonctions discontinues que contient le programme. Apparemment, le niveau de gris local dépend d'une variable réelle (x) dont le lien avec les coordonnées (i, j) du pixel n'a pas été donné - mais cela m'a peut-être échappé.
    Je ne comprend pas ce que tu veux dire par là ?
    C'est ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for y:=1 to 512 do
      begin
        For x := 1 to 512 do
        begin 
          n := 1 + ng.Noise2D(x,y);    // Normalisation pour obtenir une valeur entre [0;2] // --> valeur de n entre[0;1] = 0.5 + n*0.5 
          v := ClampByte(Round((n*255)/2));
          bmp.setPixel(x-1,y-1, BZColor(v,v,v));
        end;
      end;
    Les facteurs d'interpolations sont les "distances" entre chaque points et doivent donc être comprises entre [0;1], mais dans mon code je prend la partie fractionnelle des coordonnées x,y

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      vx := x * Frequency;
      vy := y * Frequency;
      fx := Math.Floor(vx);
      fy := Math.Floor(vy);
      cx := fx + 1;  // Math.Ceil(vx);
      cy := fy + 1; //Math.Ceil(vy);
     
    interpolatorX :=  frac(vx); //vx - fx;
    interpolatorY :=  frac(vy); //vy - fy;
    j'obtiens les mêmes résultat en calculant la différence

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    interpolatorX :=  vx - fx;
    interpolatorY :=  vy - fy;
    Citation Envoyé par wiwaxia Voir le message
    On ne trouve pas trace non plus de grandeurs pseudo-aléatoires auxquelles on devrait s'attendre pour la définition d'un bruit de fond, et sur lesquelles portent l'interpolation.
    Voila le code que j'utilise pour générer le bruit

    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
     
    // Nombres premier
    Const
      cX_PRIME : Integer = 1619;
      cY_PRIME : Integer  = 31337;
      cZ_PRIME : Integer  = 6971; 
      cW_PRIME : Integer  = 1013;
      cNOISE_SEED = 4679;  
     
    Function TBZCustomNoiseGenerator.RandUniform1D(x : Double) : Double;
    Var
      n : Integer;
    begin
      n := Round(cX_PRIME * x + cNOISE_SEED * Seed) and $7fffffff;
      n := (n shr 13) xor n;
      Result := 1.0 - (((n * (n * n * 60493 + 19990303) + 1376312589) and $7fffffff) / 1073741824.0);
    end;
     
    Function TBZCustomNoiseGenerator.RandUniform2D(x,y:Double):Double;
    Var
      n : Integer;
    begin
      n := Round(cX_PRIME * x + cY_PRIME * y + cNOISE_SEED * Seed) and $7fffffff;
      n := (n shr 13) xor n;
      Result := 1.0 - (((n * (n * n * 60493 + 19990303) + 1376312589) and $7fffffff) / 1073741824.0);
    end;
     
    Function TBZCustomNoiseGenerator.RandUniform3D(x,y,z : Double): Double;
    Var
      n : Integer;
    begin
      n := Round(cX_PRIME * x + cY_PRIME * y + cZ_PRIME * z + cNOISE_SEED * Seed) and $7fffffff;
      n := (n shr 13) xor n;
      Result := 1.0 - (((n * (n * n * 60493 + 19990303) + 1376312589) and $7fffffff) / 1073741824.0);
    end;
     
    Function TBZCustomNoiseGenerator.RandUniform4D(x, y, z, w : Double) : Double;
    Var
      n : Integer;
    begin
      n := Round(cX_PRIME * x + cY_PRIME * y + cZ_PRIME * z + cW_PRIME * w + cNOISE_SEED * Seed) and $7fffffff;
      n := (n shr 13) xor n;
      Result := 1.0 - (((n * (n * n * 60493 + 19990303) + 1376312589) and $7fffffff) / 1073741824.0);
    end; 
     
    Function TBZWhiteNoiseGenerator.Noise1D(x : Double) : Double;
    begin
      //Result := Frac(Sin(x * ((Random * 2.0) - 1.0)) * 143758.5453);
      //Result := Frequency + ( 1 * (Result + Frequency)); // Pink noise ?????
      Result := RandUniform1D(x);
    end;
     
    Function TBZWhiteNoiseGenerator.Noise2D(x,y:Double):Double;
    begin
    // Result := 0.5 * (Noise1D(x) + Noise1D(y));
      Result := RandUniform2D(x,y);
    end;
     
    Function TBZWhiteNoiseGenerator.Noise3D(x,y,z : Double): Double;
    begin
    //  Result := (Noise1D(x) + Noise1D(y) + Noise1D(z)) / 3;
      Result := RandUniform3D(x,y,z);
    end;
     
    Function TBZWhiteNoiseGenerator.Noise4D(x, y, z, w : Double) : Double;
    begin
      //Result := 0.25 * (Noise1D(x) + Noise1D(y) + Noise1D(z) + Noise1D(w));
      Result := RandUniform4D(x,y,z,w);
    end;
    Les valeurs générées ici sont comprises entre [-1,1]

    Citation Envoyé par wiwaxia Voir le message
    Les formules d'interpolation proposées sont définies sur l'intervalle [0 ; 1[ ; or on trouve formulées des conditions qui paraissent inadaptées au domaine précédent, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function TBZBoxInterpolationFilter.Filter(x: double): double;// Aka nearest neighbour
    begin
      if (x > -0.5) and (x <= 0.5) then
        Result := 1
      else
        Result := 0;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function TBZCosineInterpolationFilter.Filter(x: Double): Double;
    begin
      Result := 0;
      if Abs(x) < 1 then
        Result := (System.Cos(x * cPI) + 1) * 0.5;
    end;
    C'est bien ce qui me semblais, elles sont adaptées pour ré-échantillonner des images, mais pas pour interpoler des valeurs pour la génération de bruits dans l'intervalle [-1;1]
    D'ou ma 2ème et 3ème question :
    - Comment puis-je transformer mes fonctions d'interpolation pour quelles deviennent fonctionnelles pour la génération de bruit
    - connaissez vous un ou plusieurs site référençant ce genre de formules (je n'ai pas trouvé de site pertinent avec Google dans ce sens) ?

    J'ai vérifié les fonctions retournent bien des valeurs entre [0;1]

    Citation Envoyé par wiwaxia Voir le message
    Dans la troisième fonction sont initialisées deux variables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      FBias:=0;
      FTension :=0;
    dont la valeur n'est pas modifiée par la suite.
    Il y a sûrement un oubli: elles auraient dû logiquement être réactualisées.
    Non ces paramètres sont là pour contrôler l'interpolation d'après http://paulbourke.net/miscellaneous/interpolation/

    Tension can be used to tighten up the curvature at the known points. The bias is used to twist the curve about the known points.

    Tension: 1 is high, 0 normal, -1 is low
    Bias: 0 is even,
    positive is towards first segment,
    negative towards the other

    Bon ben du coup en écrivant ces lignes une idée "saugrenue" m'ai apparue

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if FSmooth then
      begin
        InterpolationFilterClass := GetBZInterpolationFilter(InterpolationMode);
        InterpolationFilter := InterpolationFilterClass.Create;
           interpolatorX := 1 - InterpolationFilter.Filter(interpolatorX); // juste en partant de 1
           interpolatorY := 1 - InterpolationFilter.Filter(interpolatorY);
        FreeAndNil(InterpolationFilter);
      end;
    Et voila cela fonctionne :

    Avec le filtre Hermit
    Nom : 2019-11-17_191357.png
Affichages : 73
Taille : 125,2 Ko
    Avec le filtre Cubic
    Nom : 2019-11-17_192511.png
Affichages : 70
Taille : 125,8 Ko
    Avec le filtre Kaiser
    Nom : 2019-11-17_192555.png
Affichages : 95
Taille : 125,9 Ko

    Mais je ne comprend pas pourquoi faire "1-Facteur"

    Merci

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  4. #4
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    décembre 2010
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2010
    Messages : 1 176
    Points : 2 280
    Points
    2 280
    Billets dans le blog
    9
    Par défaut Génération de bruit et filtres d'interpolation
    L'observation de la seconde image postée dans le message initial conduit à penser
    - que l'interpolation est effectuée sur les sous-domaines carrés qui apparaissent nettement, et dont le niveau local de gris varie d'une façon continue; et
    - qu'en un sommet commun à 2 ou 4 carrés, on ne retrouve pas la même valeur pseudo-aléatoire issue du générateur de bruit, selon qu'on se rapproche du point considéré en se situant strictement dans l'un ou l'autre des domaines adjacents.
    Nom : Image_# 01.png
Affichages : 65
Taille : 89,6 Ko
    Ce défaut a peut-être été supprimé par la rectification que tu as introduite.

    J'ai regardé ce à quoi pouvait conduire la partition d'une image de dimensions (La×Ha) en sous domaines carrés d'arête (Dcarre), après avoir mémorisé dans un tableau suffisamment large (N1N2) entiers au format Byte délivrés par un générateur de nombres pseudo-aléatoires:
    N1 = 1 + (La - 1) DIV Dcarre ; N2 = 1 + (Ha - 1) DIV Dcarre .
    Le calcul fait intervenir le procédé d'interpolation le plus simple, par le recours à la fonction bilinéaire
    z = K00 + K10.x + K01.y + K11.xy
    qui utilise les coordonnées relatives (x, y) sur le domaine [0 ; 1[×[0 ; 1[ , et dont les coefficients se déduisent très simplement des valeurs imposées aux quatre sommets; on a en effet:
    Z00 = K00 ; Z10 = K00 + K10 ; Z01 = K00 + K01 ; Z11 = K00 + K10 + K01 + K11 ,
    d'où l'on déduit très simplement:
    K10 = Z11 - K00 ; K01 = Z01 - K00 ; K11 = Z11 - K00 - K10 - K01 .

    Ces précisions facilitent la lecture de l'algorithme:
    Code Pascal : 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
     CONST K_Entete = 54;           Dim_Max = 1500;
           Chemin = 'D:\ZZZZZZ\#\'; NmaxC = 150; Dcarre = 35;
     
     TYPE Pixel = ARRAY[1..3] OF Byte;
          Tab_Pix = ARRAY[0..Dim_Max, 0..Dim_Max] OF Pixel;
          Tab_B = ARRAY[0..NmaxC, 0..NmaxC] OF Byte;
          Tab_E = ARRAY[0..NmaxC, 0..NmaxC] OF Z_32;
          Lst3E = ARRAY[1..3] OF Z_32;
     
     VAR Larg_Image, Haut_Image, T_Fichier, T_Image: Z_32;
         V_Fich_1, V_Fich_2: File OF Byte;
         Matrice_1, Matrice_2: Tab_Pix;
         Nom_F2: String;
         Mat_B: Tab_B; Mat_E: Tab_E;
     
    // ... / ...
     
     PROCEDURE ZeroM(VAR Ma: Tab_Pix);
       CONST Pzero: Pixel = (0, 0, 0);
       VAR i, j: Z_32;
       BEGIN
         FOR i:= 0 TO Dim_Max DO
           FOR j:= 0 TO Dim_Max DO Ma[i, j]:= Pzero
       END;
     
    (*HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
     
     Palette monochrome
     
    HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH*)
     
     PROCEDURE AffNc_00;          // Affichages des entiers al‚atoires
       CONST h = 0;
       VAR i, j, x, y: Byte;
       BEGIN
         E(0111);
         FOR i:= h TO (h + 15) DO
           FOR j:= h TO (h + 15) DO BEGIN
                                      x:= 5 * (j - h); Inc(x, 2);
                                      y:= 2 * (i - h); Inc(y, 37);
                                      We(x, y, Mat_B[j, i], 3)          // écriture d'un entier
                                    END
       END;
     
     PROCEDURE InitC_00(VAR M_b: Tab_B);
       VAR i, j: Byte;
       BEGIN
         RandSeed:= 111152222;
         FOR i:= 0 TO NmaxC DO
           FOR j:= 0 TO NmaxC DO M_b[i, j]:= Random(256)
       END;
     
    // Calcul des éléments de la matrice du corps de l'image
     
     PROCEDURE Calc_Mat_Im2_02b(La, Ha: Z_32; VAR M_b: Tab_E; VAR Ma2: Tab_Pix); 
       VAR h, i: Byte;
           Dx, Dy, K00, K01, K10, K11, X1, X1m, Xm, Y1, Y1m, Ym: Z_32;
           Rx, Ry, u, v: Reel; Px: Pixel;
       BEGIN
         ZeroM(Matrice_2);          InitC_00(Mat_B); AffNc_00;
         X1m:= (La - 1) DIV Dcarre; Y1m:= (Ha - 1) DIV Dcarre;
         FOR X1:= 0 TO X1m DO
           FOR Y1:= 0 TO Y1m DO
             BEGIN
               K00:= M_b[X1, Y1];           K10:= M_b[X1 + 1, Y1] - K00;
               K01:= M_b[X1, Y1 + 1] - K00; K11:= M_b[X1 + 1, Y1 + 1] - K00;
               Dec(K11, K10 + K01);
               FOR Dx:= 0 TO (Dcarre - 1) DO
                 BEGIN
                   Xm:= Dcarre * X1; Inc(Xm, Dx); Rx:= Dx / Dcarre;
                   FOR Dy:= 0 TO (Dcarre - 1) DO
                     BEGIN
                       Ym:= Dcarre * Y1; Inc(Ym, Dy); Ry:= Dy / Dcarre;
                       v:= Rx * Ry;      u:= K00 + (K11 * v);
                       v:= (K10 * Rx) + (K01 * Ry); h:= Round(u + v);
                       FOR i:= 1 TO 3 DO Px[i]:= h;
                       IF ((Xm<La) AND (Ym<Ha)) THEN Ma2[Xm, Ym]:= Px
                     END
                 END
             END
       END;                    
     
    // ... / ...

    Voici l'image résultant de l'exécution du programme:

    Nom : Fich_2_Dc=35_1C.png
Affichages : 70
Taille : 152,5 Ko

    L'image aléatoire en couleur s'obtient en faisant trois fois le même travail, pour chacune des composantes; c'est évidemment plus lourd (il faut désormais calculer 12 coefficients pour chaque domaine), mais il suffit cependant:
    - de consigner dans un tableau (N1N2) entiers au format LongInt (ici noté Z_32), variant de zéro à (2563 - 1) = 16777215 ;
    - de prendre pour les coefficients (Kij) des tableaux de 3 entiers.
    Code Pascal : 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
    (*HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
     
     Palette trichrome
     
    HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH*)
     CONST B08 = 256; B16 = B08 * B08; B24 = B08 * B16; // B24 = 16777216
     
     PROCEDURE AffNc_01;          // Affichages des entiers al‚atoires
       CONST h = 0;
       VAR i, j, x, y: Byte; k: Z_32;
       BEGIN
         E(0111);
         FOR i:= h TO (h + 15) DO
           FOR j:= h TO (h + 15) DO BEGIN
                                      x:= 5 * (j - h); Inc(x, 2);
                                      y:= 2 * (i - h); Inc(y, 37);
                                      k:= Mat_B[j, i] MOD B16;
                                      We(x, y, (k DIV B08), 3)
                                    END
       END;
     
     PROCEDURE InitC_01(VAR M_e: Tab_E);
       VAR i, j: Byte;
       BEGIN
         RandSeed:= 111152222;
         FOR i:= 0 TO NmaxC DO
           FOR j:= 0 TO NmaxC DO M_e[i, j]:= Random(B24)
       END;
    (*HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
     
     Palette trichrome / Interpolation lin‚aire
     
    HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH*)
     PROCEDURE CalcKij(x, y: Z_32; VAR M_e: Tab_E;
                       VAR C00, C01, C10, C11: Lst3E);
       VAR j: Byte; m, X1, Y1: Z_32;
           K00, K01, K10, K11, P00, P01, P10, P11: Lst3E;
       BEGIN
         X1:= x + 1; Y1:= y + 1;
         FOR j:= 1 TO 3 DO
           BEGIN
             CASE j OF  1: BEGIN
                             P00[1]:= M_e[x,  y ] DIV B16;
                             P01[1]:= M_e[x,  Y1] DIV B16;
                             P10[1]:= M_e[X1, y ] DIV B16;
                             P11[1]:= M_e[X1, Y1] DIV B16
                           END;
                        3: BEGIN
                             P00[3]:= M_e[x,  y ] MOD B08;
                             P01[3]:= M_e[x,  Y1] MOD B08;
                             P10[3]:= M_e[X1, y ] MOD B08;
                             P11[3]:= M_e[X1, Y1] MOD B08
                           END
                      ELSE BEGIN
                             m:= M_e[x,  y ] MOD B16; P00[2]:= m DIV B08;
                             m:= M_e[x,  Y1] MOD B16; P01[2]:= m DIV B08;
                             m:= M_e[X1, y ] MOD B16; P10[2]:= m DIV B08;
                             m:= M_e[X1, Y1] MOD B16; P11[2]:= m DIV B08
                           END  END;
             K00[j]:= P00[j];          K10[j]:= P10[j] - K00[j];
             K01[j]:= P01[j] - K00[j]; K11[j]:= P11[j] - K00[j];
             Dec(K11[j], K10[j] + K01[j])
           END;
         C00:= K00; C01:= K01; C10:= K10; C11:= K11
       END;
     
     PROCEDURE Calc_Mat_Im2_03(La, Ha: Z_32; VAR M_e: Tab_E; VAR Ma2: Tab_Pix);
       CONST P000: Pixel = (0, 0, 0);
       VAR j: Byte; Dx, Dy, X1, X1m, Xm, Y1, Y1m, Ym: Z_32;
           Rx, Rxy, Ry, u, v: Reel; K00, K01, K10, K11: Lst3E; Px: Pixel;
       BEGIN
         ZeroM(Matrice_2); InitC_01(Mat_E); AffNc_01;
         X1m:= (La - 1) DIV Dcarre;
         Y1m:= (Ha - 1) DIV Dcarre;
         FOR X1:= 0 TO X1m DO
           FOR Y1:= 0 TO Y1m DO
             BEGIN
               CalcKij(X1, Y1, Mat_E, K00, K01, K10, K11);
               FOR Dx:= 0 TO (Dcarre - 1) DO
                 BEGIN
                   Xm:= Dcarre * X1; Inc(Xm, Dx); Rx:= Dx / Dcarre;
                   FOR Dy:= 0 TO (Dcarre - 1) DO
                     BEGIN
                       Ym:= Dcarre * Y1; Inc(Ym, Dy);
                       Ry:= Dy / Dcarre; Rxy:= Rx * Ry; Px:= P000;
                       IF ((Xm<La) AND (Ym<Ha)) THEN
                         BEGIN
                           FOR j:= 1 TO 3 DO
                             BEGIN
                               u:= K00[j] + (K11[j] * Rxy);
                               v:= (K10[j] * Rx) + (K01[j] * Ry);
                               Px[j]:= Round(u + v)
                             END;
                           Ma2[Xm, Ym]:= Px
                         END
                     END
                 END
             END
       END;
    Voici l'image obtenue, précédée des trois versions monochromes (résultant d'un petit bricolage du code):
    Nom : Fich_2_Dc=35_1Rouge_300xx.png
Affichages : 60
Taille : 326,3 Ko
    Noter la parenté de l'image rouge avec la grise: le générateur a été initialisé avec la même graine.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  5. #5
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    juillet 2006
    Messages
    9 305
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : juillet 2006
    Messages : 9 305
    Points : 13 233
    Points
    13 233
    Par défaut
    Bonsoir,

    j'ai vu que la porte n'était pas fermée, alors je l'ai poussée. Je peux poser une question de total béotien ?
    Citation Envoyé par wiwaxia Voir le message
    Voici l'image obtenue, précédée des trois versions monochromes (résultant d'un petit bricolage du code)
    À quoi ça sert, tout ça ?
    La réponse avec des phrases simples, compréhensibles par un gamin de 12 ans, merci,
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  6. #6
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    décembre 2010
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2010
    Messages : 1 176
    Points : 2 280
    Points
    2 280
    Billets dans le blog
    9
    Par défaut Génération de bruit et filtres d'interpolation
    Citation Envoyé par Jipété Voir le message
    À quoi ça sert, tout ça ?
    À produire, par un processus pseudo-aléatoire, une image représentant d'une manière réaliste des éléments naturels tels que le bois, le marbre, le métal ou la pierre.

    L'exemple décrit est élémentaire (et même beaucoup trop simple), et je reconnais que cela s'apparente plus à du coloriage pour fond d'écran - mais c'est un point de départ et le sujet n'en est pas moins fascinant.
    On trouve sur ce site une très bonne introduction concernant le bruit de Perlin.

    Voir aussi https://fr.wikipedia.org/wiki/Bruit_de_Perlin.
    https://gametorrahod.com/various-noise-functions/
    Je n'en sais guère plus que toi, bien que je me sois déjà intéressé aux teintes pseudo-aléatoires. Je vais devoir déchiffrer des instructions en C++


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  7. #7
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    juillet 2006
    Messages
    9 305
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : juillet 2006
    Messages : 9 305
    Points : 13 233
    Points
    13 233
    Par défaut
    Bonjour,

    merci beaucoup pour les liens, bon courage pour étudier tout ça, et bonne chance pour le déchiffrage du C++ (suivi d'une réécriture en Free Pascal ou similaire, je suppose ? )
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  8. #8
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    décembre 2010
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2010
    Messages : 1 176
    Points : 2 280
    Points
    2 280
    Billets dans le blog
    9
    Par défaut Génération de bruit et filtres d'interpolation
    Citation Envoyé par Jipété Voir le message
    ... bon courage pour étudier tout ça, et bonne chance pour le déchiffrage du C++ (suivi d'une réécriture en Free Pascal ou similaire, je suppose ? )
    Hors du Pascal, point de salut !

    PS: Trouvaille survenue à l'instant, et en français: The Book of Shaders.


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

  9. #9
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 763
    Points : 4 067
    Points
    4 067
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    À produire, par un processus pseudo-aléatoire, une image représentant d'une manière réaliste des éléments naturels tels que le bois, le marbre, le métal ou la pierre.

    L'exemple décrit est élémentaire (et même beaucoup trop simple), et je reconnais que cela s'apparente plus à du coloriage pour fond d'écran - mais c'est un point de départ et le sujet n'en est pas moins fascinant.
    On trouve sur ce site une très bonne introduction concernant le bruit de Perlin.

    Voir aussi https://fr.wikipedia.org/wiki/Bruit_de_Perlin.
    https://gametorrahod.com/various-noise-functions/
    Je n'en sais guère plus que toi, bien que je me sois déjà intéressé aux teintes pseudo-aléatoires. Je vais devoir déchiffrer des instructions en C++
    Bonjour wiwaxia merci de ta réponse et de tes explication pour ce "1-Facteur" que j'avais partiellement compris, mais que j'ai pigée en lisant l'article de Jeremy (je l'avais pas vu celui la )

    Citation Envoyé par wiwaxia Voir le message
    Hors du Pascal, point de salut !

    PS: Trouvaille survenue à l'instant, et en français: The Book of Shaders.
    Je ne le connaissait pas celui la aussi

    Et je te rejoins c'est super intéressant et on peut ajouter plein de variations et d'algorithme de génération de nombre aléatoire comme l'"Additive white Gaussian noise" ou le FBM

    il y aussi les "Bruit dégradé" comme le Perlin, le SimpleX et l'OpenSimpleX
    ou encore les bruits cellulaire comme l'aglorithme de Worley

    Et la génération de bruit est aussi applicable dans d'autre domaine tel que le signal audio

    Apres tout cela on peut rajouter les algorithmes de génération fractal comme le "Diamon Square"

    Bref niveau génération de texture il y'a de quoi s'amuser un peu

    Merci encore

    A bientôt

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  10. #10
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    décembre 2010
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2010
    Messages : 1 176
    Points : 2 280
    Points
    2 280
    Billets dans le blog
    9
    Par défaut Génération de bruit et filtres d'interpolation
    Citation Envoyé par BeanzMaster Voir le message
    ... Et je te rejoins c'est super intéressant et on peut ajouter plein de variations et d'algorithmes de génération de nombres aléatoires ... / ...
    Bref niveau génération de texture il y a de quoi s'amuser un peu ...
    Merci pour tous les liens fournis, qui conduisent en effet à des domaines très vastes, avec des résultats parfois étonnants.
    Je retrouve à cette occasion l'arithmétique booléenne, que Jipété m'avait fait découvrir dans une autre discussion.

    J'avais il y a deux ans rédigé deux billets sur un sujet voisin, précédés de 3 autres plus techniques. La série partait d'une question très banale, régulièrement posée sur les forums.
    L'algorithme pourrait être repris pour éviter la formation du massif montagneux central, qui apparaît spontanément en l'absence de toute contrainte.

    Nom : Im_3000_L=016.png
Affichages : 100
Taille : 29,3 KoNom : Im_5000_L=004.png
Affichages : 78
Taille : 30,2 Ko


    Le français, notre affaire à tous
    Grand Dictionnaire Terminologique

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

Discussions similaires

  1. [1.x] Génération des formulaire et filtre
    Par mino26tz dans le forum Débuter
    Réponses: 2
    Dernier message: 08/04/2011, 10h13
  2. génération du bruit blanc
    Par zizo08 dans le forum MATLAB
    Réponses: 6
    Dernier message: 14/01/2009, 21h21
  3. corriger l'image bruitée par filtre median
    Par Invité dans le forum Traitement d'images
    Réponses: 10
    Dernier message: 02/06/2008, 00h04
  4. Réponses: 0
    Dernier message: 08/04/2008, 19h19
  5. algo d'un filtre d'interpolation
    Par sandball22 dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 11/04/2007, 10h53

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