Maison  >  Article  >  interface Web  >  Série d'analyses des principes de l'algorithme PhotoShop - pixellisation - fragmentation

Série d'analyses des principes de l'algorithme PhotoShop - pixellisation - fragmentation

高洛峰
高洛峰original
2017-02-21 09:18:171698parcourir

Continuant avec la popularité de l’article précédent, continuons à parler de quelques algorithmes légèrement plus simples.

Cet article parlera de l'algorithme de fragmentation. Postons d'abord quelques rendus :

PhotoShop算法原理解析系列 - 像素化-碎片 PhotoShop算法原理解析系列 - 像素化-碎片 PhotoShop算法原理解析系列 - 像素化-碎片 PhotoShop算法原理解析系列 - 像素化-碎片

C'est un filtre destructeur. La raison pour laquelle on utilise de belles femmes est que 90% des personnes qui créent des images sont des hommes, des hommes pervers.

Concernant le principe du filtre de fragments, les informations disponibles sur Internet sont les suivantes : Créer quatre copies de l'image décalées les unes par rapport aux autres, produisant un effet similaire à du ghosting.

Avec juste la phrase ci-dessus, nous pouvons commencer.

Analyse : En comparant les images ci-dessus, en particulier les yeux, on peut voir que l'image traitée devrait ressembler à un seul œil est devenue 4 yeux. Par conséquent, le réseau La déclaration ci-dessus. est fiable.

Alors où est le centre du décalage et quel est le nombre de décalages ? Dans quelles directions les 4 décalages sont-ils également très simples ? vérifier :

Les étapes spécifiques sont les suivantes : Ouvrez une image et remplissez une zone rouge de 2*2 pixels à un endroit où la couleur de l'image est relativement monotone (comme le bras de la beauté mentionnée ci-dessus), puis copiez le calque, appliquez un filtre de fragment au calque copié et ajustez la transparence du calque à 50 %. Vous pouvez obtenir l'image suivante en zoomant partiellement :

🎜> PhotoShop算法原理解析系列 - 像素化-碎片 Avec cet effet, vous pouvez facilement tirer la conclusion :

Le centre du décalage est centré sur chaque pixel, et les quatre décalages sont symétriques par rapport au centre , avec une pente de 45 degrés sont uniformément disposés en cercle, avec des décalages horizontaux et verticaux de 45 degrés chacun et un décalage de 4 pixels.

Alors la question de savoir comment superposer se devine, il s'agit de faire la moyenne des valeurs accumulées après quatre décalages.

Sur la base de cette idée, j'ai écrit l'algorithme suivant :

private void CmdFragment_Click(object sender, EventArgs e)
{    int X, Y, Z, XX, YY;    int Width, Height, Stride;    int Speed, Index;    int SumR, SumG, SumB;
    Bitmap Bmp = (Bitmap)Pic.Image;    if (Bmp.PixelFormat != PixelFormat.Format24bppRgb) throw new Exception("不支持的图像格式.");

    Width = Bmp.Width; Height = Bmp.Height; Stride = (int)((Bmp.Width * 3 + 3) & 0XFFFFFFFC);    byte[] ImageData = new byte[Stride * Height];                                    // 用于保存图像数据,(处理前后的都为他)
    byte[] ImageDataC = new byte[Stride * Height];                                   // 用于保存克隆的图像数据
    int[] OffsetX = new int[] { 4, -4, -4, 4 };                                      // 每个点的偏移量
    int[] OffsetY = new int[] { -4, -4, 4, 4 };    fixed (byte* P = &ImageData[0], CP = &ImageDataC[0])
    {        byte* DataP = P, DataCP = CP;
        BitmapData BmpData = new BitmapData();
        BmpData.Scan0 = (IntPtr)DataP;                                              //  设置为字节数组的的第一个元素在内存中的地址
        BmpData.Stride = Stride;
        Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite | ImageLockMode.UserInputBuffer, PixelFormat.Format24bppRgb, BmpData);

        Stopwatch Sw = new Stopwatch();                                             //  只获取计算用时        Sw.Start();
        System.Buffer.BlockCopy(ImageData, 0, ImageDataC, 0, Stride * Height);     //  填充克隆数据        

        for (Y = 0; Y < Height; Y++)
        {
            Speed = Y * Stride;            for (X = 0; X < Width; X++)
            {
                SumB = 0; SumG = 0; SumR = 0;                for (Z = 0; Z < 4; Z++)                                           //  累积取样点的取样和                {
                    XX = X + OffsetX[Z];
                    YY = Y + OffsetY[Z];                    if (XX < 0)                                                    //   注意越界
                        XX = 0;                    else if (XX >= Width)
                        XX = Width - 1;                    if (YY < 0)
                        YY = 0;                    else if (YY >= Height)
                        YY = Height - 1;
                    Index = YY * Stride + XX * 3;
                    SumB += DataCP[Index];
                    SumG += DataCP[Index + 1];
                    SumR += DataCP[Index + 2];
                }

                DataP[Speed] = (byte)((SumB+2) >> 2);    //  求平均值(Sum+2)/4,为什么要+2,就为了四舍五入。比如如果计算结果为108.6,则取像素109更为合理     
                DataP[Speed + 1] = (byte)((SumG + 2) >> 2);
                DataP[Speed + 2] = (byte)((SumR + 2) >> 2);
                Speed += 3;                                                     //  跳往下一个像素            }
        }
        Sw.Stop();        this.Text = "计算用时: " + Sw.ElapsedMilliseconds.ToString() + " ms";
        Bmp.UnlockBits(BmpData);                         //  必须先解锁,否则Invalidate失败     }
    Pic.Invalidate();}

Algorithme, OffsetX et OffsetY sont respectivement les décalages des pixels du point d'échantillonnage. De même, puisque ce filtre implique des opérations sur le terrain, une sauvegarde des pixels est requise avant le traitement, mais les données de sauvegarde ne sont pas développées ici. Par conséquent, les coordonnées du point d'échantillonnage doivent être vérifiées dans le code interne pour voir s'il dépasse sa plage, s'il dépasse la plage, il est généralement dans la plage de l'algorithme de filtre d'image. Il existe trois méthodes de traitement :

(1) S'il dépasse, il est considéré comme sa valeur limite la plus proche, c'est-à-dire les pixels de bord répétés. Cette partie du code est la partie if...sinon if publiée ci-dessus. .

(2) Le rembobinage peut être décrit par le code suivant :

while (XX >= Width)
    XX = XX - Width;while (XX < 0)
    XX = XX + Width;while (YY >= Height)
    YY = YY - Height;while (YY < 0)
    YY = YY + Height;
(3) Ne comptez que les pixels dans la plage de l'image :

 if (XX >= 0 && XX < Width && YY >= 0 && YY < Height)
 {
       // 累加计算
 }
Bien sûr, pour ce faire, vous devez utiliser un variable pour l'enregistrer. Combien de calculs admissibles ont été effectués.

Les amis intéressés peuvent modifier le code et essayer.

Dans l'extrait de code ci-dessus, DataP[Speed] = (byte)((SumB 2) >> 2); La raison de l'ajout de 2 à SumB est d'arrondir le résultat, ce qui est plus raisonnable. .

Après test, le code ci-dessus est cohérent à 100 % avec l'effet du traitement PS. Cela montre que notre hypothèse est tout à fait correcte.

Vous pouvez également étendre davantage l'algorithme : Réfléchissez davantage, pourquoi doit-il s'agir de 4 images fantômes ? Il doit s'agir d'un angle de 45 degrés. doit être 4 Le décalage horizontal et vertical des pixels. Je donne l'image ci-dessous pour que les lecteurs intéressés puissent se développer par eux-mêmes.

PhotoShop算法原理解析系列 - 像素化-碎片

Sur la photo, l'angle est de 32 degrés, le rayon est de 10 et le nombre de fragments est de 7, qui peut produire un effet similaire au suivant (vous pouvez utiliser mon Imageshop pour vérifier) :

PhotoShop算法原理解析系列 - 像素化-碎片 Veuillez faire attention au site Web chinois PHP ! PhotoShop算法原理解析系列 - 像素化-碎片

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn