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 :

Flou circulaire/radial : conversion polaire vers cartésien et inversement


Sujet :

Traitement d'images

  1. #1
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    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 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut Flou circulaire/radial : conversion polaire vers cartésien et inversement
    Bonjour, je suis confronté à un petit problème je n'arrive pas à voir et à saisir ou est mon erreur dans mes fonctions

    Le but est d'appliquer à une image un flou circulaire ou radial

    L'idée est simple pour le flou circulaire on transforme l'image en coordonnée polaire, on applique un flou de mouvement horizontal et on repasse l'image en coordonnée cartésienne
    Pour le flou radial c'est la même chose sauf que l'on effectue un flou de mouvement vertical

    Voila 2 captures d'écran

    Le flou radial, celui-ci me semble correcte

    Nom : 2019-12-29_113908.png
Affichages : 450
Taille : 460,6 Ko

    Le flou circulaire, il y a une cassure au milieu de l'image et cette effet de rotation que je ne veux pas naturellement

    Nom : 2019-12-29_114229.png
Affichages : 435
Taille : 469,7 Ko

    Nom : 2019-12-29_113944.png
Affichages : 424
Taille : 21,8 Ko

    Voici mes fonctions en pascal de transformation polaire<-->cartesien

    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
    procedure TBZBitmapTransformations.CartesianToPolar;
    var
      x,y,dx,dy : Integer;
      dr, dt, r, theta, dtheta, SinAngle, CosAngle: Single;
      InColor : TBZColor;
      TmpBmp : TBZBitmap;
    begin
      dr := Sqrt(OwnerBitmap.CenterX * OwnerBitmap.CenterX + OwnerBitmap.CenterY * OwnerBitmap.CenterY) / OwnerBitmap.Height;
      dTheta  := 360 / OwnerBitmap.Width;
      dt := DegToRadian(dTheta);
      r := dr;
      TmpBmp := TBZBitmap.Create(OwnerBitmap.Width, OwnerBitmap.Height);
     
     
      InColor := OwnerBitmap.GetPixel(OwnerBitmap.CenterX,OwnerBitmap.CenterY);
      for x := 0 to OwnerBitmap.MaxWidth do TmpBmp.setPixel(x,0, InColor);
     
      for y := 0 to OwnerBitmap.MaxHeight do
      begin
        theta := 0.0;
        for x := 0 to OwnerBitmap.MaxWidth do
        begin
          CosAngle := System.Cos(Theta);
          SinAngle := System.Sin(Theta);
     
          dx := round(OwnerBitmap.CenterX + r * CosAngle);
          dy := round(OwnerBitmap.CenterY + r * SinAngle);
     
          if OwnerBitmap.CheckPixelBound(dx, dy) then
          begin
            InColor := OwnerBitmap.getPixel(dx,dy)
          end
          else InColor := clrTransparent;
     
          TmpBmp.setPixel(x,y,InColor);
     
          Theta := Theta + dt;
        end;
        r := r + dr;
      end;
      OwnerBitmap.FastCopy(TmpBmp);
      FreeAndNil(TmpBmp);
    end;
     
    procedure TBZBitmapTransformations.PolarToCartesian;
    var
      ii,jj,Ind1, Ind2, m,n,x,y,px,py : Integer;
      weight, dr, dt, r, theta, dtheta, SinAngle, CosAngle, dx, dy  : Single;
      AColor: TBZColor;
      xs,ys,ddx,ddy,cx,cy : Integer;
      TmpBmp : TBZBitmap;
    Const
      BiCubicRPrecal: Array[1..16] Of Single = (0.00260416666666667, 0.0208333333333333, 0.0703125, 0.166666666666667,
        0.315104166666667, 0.479166666666667, 0.611979166666667, 0.666666666666667,
        0.611979166666667, 0.479166666666667, 0.315104166666667, 0.166666666666667,
        0.0703125, 0.0208333333333333, 0.00260416666666667, 0.0);
     
    begin
      dr := System.Sqrt(OwnerBitmap.CenterX * OwnerBitmap.CenterX + OwnerBitmap.CenterY * OwnerBitmap.CenterY) / OwnerBitmap.Height;
      dTheta  := 360 / OwnerBitmap.Width;
      dt := DegToRadian(dTheta);
      r := dr;
      TmpBmp := TBZBitmap.Create(OwnerBitmap.Width, OwnerBitmap.Height);
      for y := 0 to OwnerBitmap.MaxHeight do
      begin
        theta := 0.0;
        for x := 0 to OwnerBitmap.MaxWidth do
        begin
     
          CosAngle := System.Cos(Theta);
          SinAngle := System.Sin(Theta);
     
          dx := (OwnerBitmap.CenterX + r * CosAngle);
          dy := (OwnerBitmap.CenterY + r * SinAngle);
          px := Round(dx);
          py := round(dy);
     
          if TmpBmp.CheckPixelBound(px, py) then
          begin
            AColor := OwnerBitmap.getPixel(x, y);
     
            xs := Ceil(dx - dt);
            ys := Ceil(dy - dr);
     
            cx := Floor(dx + dt);
            cy := Floor(dy + dr);
     
            ddx := cx - xs;
            ddy := cy - ys;
     
            For m := -1 To 2 Do
            Begin
              For n := -1 To 2 Do
              Begin
                Ind1 := round(4 * (m - ddx)) + 8; // Indice de correspondance avec la table précalculée
                Ind2 := round(4 * (n - ddy)) + 8; // Idem
                // Evite un bug d'indice hors limites
                Ind1 := Max(Min(Ind1, 16), 1);
                Ind2 := Max(Min(Ind2, 16), 1);
     
                weight := BiCubicRPrecal[ind1]*BiCubicRPrecal[ind2];
     
                ii := Clamp((xs + m), 0, OwnerBitmap.MaxWidth);
                jj := Clamp((ys + n), 0, OwnerBitmap.MaxHeight);
     
                TmpBmp.setPixel(Floor(ii+m*weight),Floor(jj+n*weight),AColor);
              End;
            End;
          end;
     
          Theta := Theta + dt;
        end;
        r := r + dr;
      end;
      OwnerBitmap.FastCopy(TmpBmp);
      FreeAndNil(TmpBmp);
    end;
    et de flou de mouvement :

    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
    Procedure TBZBitmapBlurFilters.MotionBlur(direction, amount : Integer);
    //Type
    //  TSumRec = packed record
    //    Red,Green, Blue, Alpha : Single;
    //  end;
    Var
      AColor, MColor:   TBZColor;
      Dir:      Single;
      x, y, xa, ya, maxh, maxw, m, s: Integer;
      incr:     Integer;
      SinDir,CosDir,delta, DeltaC:single;
      mustdraw: Boolean;
      SumRec, FColor :   TBZColorVector; //TSumRec;
    Begin
      s := Amount - 1;
      x:=0;
      y:=0;
      AColor := clrTransparent;
      MaxH := OwnerBitmap.MaxHeight + s;
      MaxW := OwnerBitmap.MaxWidth + s;
      Dir := DegToRad(direction);
     
      InitProgress(OwnerBitmap.Width,OwnerBitmap.Height);
      StartProgressSection(0,'');
      StartProgressSection(100,'Flou Motion');
      Delta := 100 / MaxH + s;
     
      SinDir :=System.sin(dir);
      CosDir:=System.cos(dir);
      For Ya := -s To MaxH Do
      Begin
        For Xa := -s To MaxW Do
        Begin
          SumRec.Create(0,0);
          //With SumRec Do
          //Begin
          //  Red := 0;
          //  Green := 0;
          //  Blue := 0;
          //  Alpha := 0;
          //End;
          Incr := 0;
          mustdraw := False;
          For m := 1 To Amount Do
          Begin
            X := Xa + round(CosDir * m);
            Y := Ya + round(SinDir * m);
            If (X >= 0) And (X <= OwnerBitmap.MaxWidth) And (Y >= 0) And (Y <= OwnerBitmap.MaxHeight) Then
            Begin
              if (TBZBitmap(OwnerBitmap).UseMask) and (TBZBitmap(OwnerBitmap).Mask.Apply) then
              begin
                MColor := TBZBitmap(OwnerBitmap).Mask.GetPixel(X,Y);
                if MColor.Red>0 then
                begin
                  FColor := OwnerBitmap.GetPixel(X, Y).AsColorVector;
                  SumRec := SumRec + FColor;
                  //With SumRec Do
                  //Begin
                  //  Red := Red + AColor.Red;
                  //  Green := Green + AColor.Green;
                  //  Blue := Blue + AColor.Blue;
                  //  Alpha := Alpha + AColor.Alpha;
                  //End;
                  Inc(Incr);
                  mustdraw := True;
                End;
              End
              else
              begin
                FColor := OwnerBitmap.GetPixel(X, Y).AsColorVector;
                SumRec := SumRec + FColor;
                //With SumRec  Do
                //Begin
                //  Red := Red + AColor.Red;
                //  Green := Green + AColor.Green;
                //  Blue := Blue + AColor.Blue;
                //  Alpha := Alpha + AColor.Alpha;
                //End;
                Inc(Incr);
                mustdraw := True;
              End;
            End;
          End;
          If mustdraw Then
          Begin
            DeltaC := Incr.Reciprocal;
            SumRec := SumRec * DeltaC;
            //With  AColor Do
            //Begin
            //  Red := ClampByte(Round(SumRec.Red * deltaC));
            //  Green := ClampByte(Round(SumRec.Green * deltaC));
            //  Blue := ClampByte(Round(SumRec.Blue * deltaC));
            //  Alpha := ClampByte(Round(SumRec.Alpha * deltaC)); // /incr
            //End;
            AColor.Create(SumRec);
            OwnerBitmap.SetPixel(x, y, AColor); {%H-}
          End;
        End;
        AdvanceProgress(Delta, 0,1,True);
      End;
      FinishProgressSection(False);
      FinishProgressSection(True);
    End;
    Pourriez vous m'aider à les corriger, pour solutionner le problème du flou circulaire. Il y a forcément quelque chose que je ne fais pas correctement, mais quoi ???
    Merci d'avance

    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
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    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 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut

    est tu sur des formules de calcul
    r correspondant a l'hypothenus d'un triangle rectangle
    pour retrouver l'angle il suffit de chercher tan-1(r)ce qui en pascal se nome je crois atan2

    une petite page tres instructive ici

    si je comprend bien tu prend le centre de la page comme référence 0,0 et ensuite tu fais un décalage en x et en y



    la formule de calcul est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Function CartesianToPolar(x,y : Currency ) : TPointReal;
    Var  
      radius,angle : Currency ;
    Begin 
       radius := Sqrt((x*x) + (y*y));
       angle  := Atan2(y, x);
       Result :=  TPointReal(radius, angle);
    end;
    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

  3. #3
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    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 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par anapurna Voir le message
    salut

    est tu sur des formules de calcul
    r correspondant a l'hypothenus d'un triangle rectangle
    pour retrouver l'angle il suffit de chercher tan-1(r)ce qui en pascal se nome je crois atan2

    une petite page tres instructive ici

    si je comprend bien tu prend le centre de la page comme référence 0,0 et ensuite tu fais un décalage en x et en y



    la formule de calcul est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Function CartesianToPolar(x,y : Currency ) : TPointReal;
    Var  
      radius,angle : Currency ;
    Begin 
       radius := Sqrt((x*x) + (y*y));
       angle  := Atan2(y, x);
       Result :=  TPointReal(radius, angle);
    end;
    Salut, la fonction CartesianToPolar semble fonctionner correctement (mais j'ai l'impression que quelque chose ne joue pas quand même)

    Nom : 2019-12-30_115532.png
Affichages : 368
Taille : 543,4 Ko

    par contre ma fonction PolarToCartesian est surement fausse (en partie), les coordonnées sont transformées en coordonnées sphérique au lieu de cylindrique

    Nom : 2019-12-30_120558.png
Affichages : 381
Taille : 532,9 Ko

    J'ai lu un truc hier dans ce sens. Je vais voir en utilisant l'hypotenus plutôt que les angles je penses que le problème vient de cette projection

    Merci pour le lien et me mettre sur la bonne voie
    • "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
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    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 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut

    selons le cadran ou tu te trouve il faut ajouter des degrés pour avoir le bonne angle si je me trompe pas
    de plus si tu prend les valeur de x telquel j'ai peur que ton point centrale se retrouve en haut a gauche

    je pense qu'il faut que tu calcul

    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
     
      // Calcul Point origine 
      LC := (o+IWidth) / 2; 
      HC := (o+IHeigth) / 2;
     
      For X:= 0 To IWidth do
        For y := 0 To IHeigth do
        begin    
           // Calcul du point decale de la moitie de l'image
           XT := X - LC ;
           YT := Y - HC ;
           ....
          // SI XT < 0 ET YT >= 0 
          // 4 ieme Quadran 
          // SI XT >= 0 ET YT >=0 
          // 1 ier Quadran 
          // SI XT >= 0 ET YT < 0 
          // 2 ieme Quadran 
          // SI XT < 0 ET YT < 0 
          // 3 ieme Quadran 
     
       end;
    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

  5. #5
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    J'arrive un peu tard (peu tard du 31 décembre ?), mais j'aimerais que tu expliques cette phrase :
    L'idée est simple pour le flou circulaire on transforme l'image en coordonnée polaire, on applique un flou de mouvement horizontal et on repasse l'image en coordonnée cartésienne
    Pour le flou radial c'est la même chose sauf que l'on effectue un flou de mouvement vertical
    Pourquoi horizontal et vertical, je pense que je vois. En coordonnées polaires tu as (R,T) au lieu de (X,Y) . En jouant sur R, tu te déplaces sur un rayon, et en jouant sur T, tu te déplaces sur un arc de cercle.

    La question est sur 'on applique un flou de mouvement horizontal' par exemple.
    Quelle est la manipulation précise qui est faite dans ce cas.

    Dans le flou 'circulaire', tu as les 2 problèmes que tu signales : problème sur le demi-axe horizontal et sensation que l'image a tourné de quelque degrés.
    Dans le flou radial, tu as en fait aussi le 2ème problème. on a le sentiment que l'image fuit vers l'extérieur (particulièrement visible selon moi sur les lunettes) ; c'est le même bug.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  6. #6
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    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 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Bonjour
    Citation Envoyé par tbc92 Voir le message
    J'arrive un peu tard (peu tard du 31 décembre ?), mais j'aimerais que tu expliques cette phrase :

    L'idée est simple pour le flou circulaire on transforme l'image en coordonnée polaire, on applique un flou de mouvement horizontal et on repasse l'image en coordonnée cartésienne
    Pour le flou radial c'est la même chose sauf que l'on effectue un flou de mouvement vertical
    Bon en fait, a force de lecture sur le web (dont pas mal mélange les notions de conversions polaire<-->cartésien), je me suis mélanger les pinceaux. J'ai donc repris m'a copie depuis l'intervention d'Anapurna qui m'a mis sur la bonne voie.

    Pour ce qui est du flou radial/circulaire il est dit que cet effet peut-être réalisé qu' en effectuant sur l'image source (cartesienne) une transformation des coordonnées Polaire vers Cartesienne (c'est là que je suis planter en premier lieu, car on le voit dans le site cité précédemment on peux lire ce truc erroné : Cartesian-to-polar transform par rapport à l'image du dessous)
    On applique alors un flou de mouvement vertical pour la radial et horizontal pour le circulaire. Puis enfin on retransforme l'image en coordonées Cartésienne vers Polaire

    Bref en reppartant du wiki je me suis aperçu que de un je n'avais pris en compte le Tan-1 et le fait que ArcTan2 donne des résultats compris dans l'intervalle [-pi, pi] et que en plus mes données était en degré au lieu de Radian. Plus qu'il fallait inverser certaines valeurs pour obtenir le bon résultat.

    Alors voila les fonctions corrigées :

    Transformation Cartesienne vers polaire :

    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
    procedure TMainForm.Cart2Polar;
    Var
      sx,sy, Radius, theta, r, Angle, WidthFactor, SqrY : single;
      xx,yy,x,y, nx, ny : Integer;
      inColor : TBZColor;
    begin
      FDisplayBuffer.SetSize(FImageBuffer.Width, FImageBuffer.Height);
      radius := Min(FImageBuffer.Width div 2, FImageBuffer.Height Div 2);
      WidthFactor := (FImageBuffer.Width/360);
      for yy := 0 to FImageBuffer.MaxHeight do
      begin
        y := FImageBuffer.CenterY - yy;
        SqrY := (y*y);
        for xx := 0 to FImageBuffer.MaxWidth do
        begin
          x := FImageBuffer.CenterX - xx;
     
          r := System.sqrt((x*x) + SqrY);
          // 1) Faut inverser l'ordre des paramètres de la fonction ArcTan sinon tourner vers la gauche ou vers la droite si on enlève "- cPI"
          // 2) Avec l'ordre des paramètres changer si "-cPI" est absent l'image est retournée horizontalement
          // 3) Il faut inverser le paramètre "Y" si non retournement vertical
          Theta := Math.arcTan2(x, -y) - cPI;
          // Conversion de l'angle de radian vers degré
          Angle := RadianToDeg(Theta);
          // On ajuste pour que l'angle soit dans l'interval [0,360] et non pas dans l'interval [-180,180]
          if Angle<0 then Angle := Angle + 360;
     
          // Calcul des coordonées polaire
          sx := (Angle * WidthFactor);
          sy := (FImageBuffer.Height * (r /radius));
     
          nx := Clamp(floor(sx),0,FImageBuffer.MaxWidth);
          ny := Clamp(floor(sy),0, FImageBuffer.MaxHeight);
     
          if FImageBuffer.CheckPixelBound(nx,ny) then
          begin
            inColor := FImageBuffer.getPixel(nx,ny);
            FDisplayBuffer.setPixel(xx,yy,inColor);
          end;
     
        end;
      end;
     
      FImageBuffer.Assign(FDisplayBuffer);
    end;
    Resultat :

    Nom : 2019-12-31_113757.png
Affichages : 352
Taille : 441,8 Ko

    Transformation Polaire vers Cartésienne :

    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
    procedure TMainForm.Polar2Cart;
    Var
      sx,sy, Radius, theta, r, AngleRad : single;
      AngleFactor, CosAngle, SinAngle : Single;
      xx,yy,x, nx, ny : Integer;
      inColor : TBZColor;
    begin
      FDisplayBuffer.SetSize(FImageBuffer.Width, FImageBuffer.Height);
      radius := Min(FImageBuffer.Width div 2, FImageBuffer.Height Div 2);
      AngleFactor := (360 / FImageBuffer.Width);
      for yy := 0 to FImageBuffer.MaxHeight do
      begin
        r := Radius * (yy / FImageBuffer.Height);
        for xx := 0 to FImageBuffer.MaxWidth do
        begin
          x := xx - FImageBuffer.CenterX;
     
          Theta := (x * AngleFactor);
          AngleRad := DegToRadian(Theta);
     
          CosAngle := System.Cos(AngleRad);
          SinAngle := System.Sin(AngleRad);
     
          sx := FImageBuffer.CenterX + (-r * SinAngle);
          sy := FImageBuffer.CenterY + (r * CosAngle);
     
          nx := Clamp(floor(sx),0,FImageBuffer.MaxWidth);
          ny := Clamp(floor(sy),0, FImageBuffer.MaxHeight);
     
          if FImageBuffer.CheckPixelBound(nx,ny) then
          begin
            inColor := FImageBuffer.getPixel(nx,ny);
            FDisplayBuffer.setPixel(xx,yy,inColor);
          end;
        end;
      end;
     
      // FDisplayBuffer.BlurFilter.MotionBlur(180,25); --> Flou circulaire
     // FDisplayBuffer.BlurFilter.MotionBlur(90,25); --> Flou radial
      FImageBuffer.Assign(FDisplayBuffer);
     
    end;
    Resutat sur l'image précédente, retour à la normale :

    Nom : 2019-12-31_113855.png
Affichages : 403
Taille : 524,6 Ko

    Maintenant sur l'image source (identique à celle du dessus) application de la transformation Polaire vers Cartesienne

    Nom : 2019-12-31_113951.png
Affichages : 378
Taille : 626,5 Ko

    puis reconversion Cartesienne vers polaire

    note : les coordonnées sont rognées d'ou cet effet d'étirement

    Nom : 2019-12-31_114311.png
Affichages : 390
Taille : 487,3 Ko

    et maintenant le résultat pour le flou radial

    Nom : 2019-12-31_114700.png
Affichages : 346
Taille : 372,2 Ko

    Et enfin le flou circulaire

    Nom : 2019-12-31_114857.png
Affichages : 380
Taille : 517,3 Ko

    Sur ce dernier on vois un cassure au centre, je pense qu'elle peut-être supprimée (ainsi que l'effet d'étirement). La cause les dimensions de l'image transformée reste les même que l'image source alors que par rapport à ce que dit l'auteur de l'article cité précédemment les dimensions devraient être de :

    So the transformed image is a buffer of dimensions ceil(sqrt(W^2+H^2)/2) and 2·(W+H-2).
    Voila me reste plus qu'a rajouté mes fonctions d'interpolation pour améliorer la qualité des résultats obtenus et continuer mes tests sur ce petit filtre circulaire.

    Je considère le sujet comme résolu

    Merci de votre aide

    Bonne années à tous

    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

  7. #7
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    Sur la dernière image, on a toujours le même bug : la tête penche vers la gauche, et on a toujours une cassure nette sur un demi-axe. Ce n'est plus le demi-axe horizontal mais le demi-axe vertical.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  8. #8
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    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 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tbc92 Voir le message
    Sur la dernière image, on a toujours le même bug : la tête penche vers la gauche, et on a toujours une cassure nette sur un demi-axe. Ce n'est plus le demi-axe horizontal mais le demi-axe vertical.
    Oui la cassure ne se fait plus au même endroit, vu que j'ai rectifié les formules (en tout cas elles sont bonnes, j'ai comparé avec gimp)

    en modifiant un peu le code et en prenant en compte le changement de dimensions, on ne vois plus la cassure. Mais il y a toujours cette rotation vers la gauche (en plus flagrant aussi )

    Nom : 2019-12-31_131725.png
Affichages : 350
Taille : 398,4 Ko

    et je ne vois pas ou se situerai cette erreur. peut-être en augmentant la résolution des calculs en utilisant des double au lieu de single ? je testerai demain si je n'ai pas trop de cheveux qui poussent à l'intérieur de mon cerveau
    • "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

  9. #9
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 053
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 053
    Points : 9 392
    Points
    9 392
    Par défaut
    Dans le code de la fonction TBZBitmapBlurFilters.MotionBlur que tu as posté au début, tu avais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     mustdraw := False;
          For m := 1 To Amount Do
          Begin
            X := Xa + round(CosDir * m);
            Y := Ya + round(SinDir * m);
            If (X >= 0) And (X <= OwnerBitmap.MaxWidth) And (Y >= 0) And (Y <= OwnerBitmap.MaxHeight) The
    Tu prends une direction (CosDir et SinDir) , et tu prends les points qui sont après le point courant quand on suit cette direction.
    Essaie cette variante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     mustdraw := False;
          For m := 1 To Amount Do
          Begin
            X := Xa - round(CosDir * m);
            Y := Ya - round(SinDir * m);
            If (X >= 0) And (X <= OwnerBitmap.MaxWidth) And (Y >= 0) And (Y <= OwnerBitmap.MaxHeight) The
    Si j'ai bien suivi, tu devrais avoir le bug inverse (tête penchée dans l'autre sens).
    Et avec cette autre variante, ça devrait être bon ?????
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     mustdraw := False;
          For m := Amount/2 To Amount/2 Do
          Begin
            X := Xa - round(CosDir * m);
            Y := Ya - round(SinDir * m);
            If (X >= 0) And (X <= OwnerBitmap.MaxWidth) And (Y >= 0) And (Y <= OwnerBitmap.MaxHeight) The
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

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

Discussions similaires

  1. Conversion Unix vers DOS...
    Par nicosfly dans le forum Langage
    Réponses: 4
    Dernier message: 23/06/2008, 17h53
  2. [VBA-E] macro conversion excel vers csv
    Par baboune dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 15/07/2004, 09h23
  3. conversion Access vers SQL
    Par Bjuice2 dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 23/03/2004, 13h57
  4. [langage] conversion décimal vers hexa
    Par chipster dans le forum Langage
    Réponses: 2
    Dernier message: 23/02/2004, 16h05
  5. Conversion Timestamp vers varchar
    Par stejutt dans le forum SQL
    Réponses: 4
    Dernier message: 08/01/2004, 08h46

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