このページは失敗作フィルタを掲載しています。
絵によっては面白い結果が出るのですが、絵によってはでたらめな絵にしか見えなくなる使用可能範囲の狭いフィルタでした。

砂絵フィルタのテスト

最初の絵が左上、右上がフィルタ一回、左下がフィルタ2回、右下がフィルタ3回適用結果です。

このイラストはPixivイラストID 10471204を元に作成しました。


その他のフィルタ適用後イラスト

おまけ話
このフィルタ連続適用すると、爆発に巻き込まれたような絵を作れます。
元写真 http://jp.123rf.com/photo_2996333.html
元写真 http://www.kimikame.net/blog/2008/05/
をしよう。


  • 以下フィルタサンプルコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace WindowsFormsApplication2
{
   public partial class Form1 : Form
   {
       public Form1()
       {
           InitializeComponent();
       }

       private void Form1_Load(object sender, EventArgs e)
       {
       }

       private void button1_Click(object sender, EventArgs e)
       {
           Bitmap b1 = new Bitmap(pictureBox1.Image);    // 変数の宣言
           

           //pictureBox1.Image  =b1;
           PictToCircle PTC = new WindowsFormsApplication2.PictToCircle();

           //PTC.changeCircle(b1);
           b1=PTC.changePictToLine(b1);

           //b1 = (PTC.getPict());
           pictureBox1.Image = b1;
           //b1.Dispose();
       }

       private void pictureBox1_Click(object sender, EventArgs e)
       {
           pictureBox1.Image = Image.FromFile("D:/色々/中高生向け戦争小説 ギガンダム討伐/so_036.jpg");
       }
       
   }


   class PictToCircle
   {
       Random rnd = new Random();
       Bitmap b1 = null;
       Bitmap b2 = null;
       int h;//高さ
       int w;//横幅
       int max;//横と高さのうちで大きいほう
       
       public Bitmap  changePictToLine(Bitmap inBit)
       {
           Color C;
               //アルゴリズムを分かりやすくするために (行、列に直す)
               byte[,] bmpData = new byte[inBit.Height, (inBit.Width) * 3 ];
               
               // bitmapクラスの画像ピクセル値を配列に挿入
               for (int i = 0; i < inBit.Height; i++)
               {
                   for (int j = 0; j < inBit.Width; j++)
                   {
                       C=inBit.GetPixel(j,i );
                       bmpData[i,j*3+0] = C.R;
                       bmpData[i,j*3+1] = C.G;
                       bmpData[i,j*3+2] = C.B;
                   }
               }
               




           int w=inBit.Width;
           double[] a=new double [3];
           double[] b=new double [3];
           int lenMax = 12;
           double[] bBunbos=new double[lenMax];
           double[] xAves=new double[lenMax];
           double[] yVers=new double[lenMax];

           for (int i = 4; i < lenMax;i++ )
           {
               xAves[i]  =(i + 1.0) / 2.0;
               for (double k = 0; k < i; k++)
               {
                   bBunbos[i] +=(k - xAves[i] )*(k-xAves[i] ); 
               }
           }

           int colPoint;
           int loopUp;
           double  r2,g2,b2;
           int []minRGB = new int[lenMax];
           int selectRGB = 0;
           
           
           for (int i = 0; i < inBit.Height; i++)
           {
           
           
               colPoint = 0;
           do
           {
               if (w - colPoint < 4)
               {
                   //とりあえずの数式
                   colPoint = w;
               }
               else
               {
                   
                   
                   if (w - colPoint < lenMax)
                   {
                       loopUp = w - colPoint;
                   }
                   else
                   {
                       loopUp = lenMax;
                   }

                   for (int k = 4; k < loopUp; k++)
                   {
                       a[0]=a[1]=a[2]=0;
                       b[0]=b[1]=b[2]=0;
                       for (int u = 0; u < k; u++)
                       {
                           
                           a[0]+=bmpData[i,colPoint*3+u*3+0];
                           a[1]+=bmpData[i,colPoint*3+u*3+1];
                           a[2]+=bmpData[i,colPoint*3+u*3+2];
                           b[0] += bmpData[i, colPoint * 3 + u * 3 + 0] *1.0*(xAves[k]-u);
                           b[1] += bmpData[i, colPoint * 3 + u * 3 + 1] *1.0*(xAves[k]-u);
                           b[2] += bmpData[i, colPoint * 3 + u * 3 + 2] *1.0*(xAves[k]-u);
                       }
                       a[0] /= k;
                       a[1] /= k;
                       a[2] /= k;
                       b[0] /= bBunbos[k] ;
                       b[1] /= bBunbos[k] ;
                       b[2] /= bBunbos[k] ;
                       double [] verTemps=new double[3];
                       double[] verSum = new double[3];
                       for (int u = 0; u < k; u++)
                       {
                           r2=bmpData[i, colPoint * 3 + u * 3 + 0];
                           g2 = bmpData[i, colPoint * 3 + u * 3 + 1];
                           b2 = bmpData[i, colPoint * 3 + u * 3 + 2];
                           verTemps[0] = (r2 - b[0] * (xAves[k] - u) + a[0]);
                           verTemps[0] *= verTemps[0];
                           verTemps[1] = (g2 - b[1] * (xAves[k] - u) + a[1]);
                           verTemps[1] *= verTemps[1];
                           verTemps[2] = (b2 - b[2] * (xAves[k] - u) + a[2]);
                           verTemps[2] *= verTemps[2];
                           verSum[0] += verTemps[0];
                           verSum[1] += verTemps[1];
                           verSum[2] += verTemps[2];
                       
                       }
                       yVers[k] = 0; 
                       for (int s = 0; s < 3; s++)
                       {
                           verTemps[s] = Math.Sqrt(1.0 / (k - 1.0) * verSum[s] *1.0 );
                       }
                       yVers[k] = verTemps[0] * verTemps[1] * verTemps[2];
                       if (verTemps[0] > verTemps[1] && verTemps[0] > verTemps[2])
                       {
                           minRGB[k] = 0;
                       }
                       else if (verTemps[1] > verTemps[2] && verTemps[1] > verTemps[0])
                       {
                           minRGB[k] = 1;
                       }
                       else
                       {
                           minRGB[k] = 2; 
                       }
                   }
                   double  minVer=yVers[4] ;
                   int minLen=4;
                   for (int k = 4; k < loopUp; k++)
                   {
                       if (rnd.Next(1000) < 20)
                       {
                           if (minVer < yVers[k])
                           {
                               minVer = yVers[k];
                               minLen = k;
                               selectRGB = minRGB[k];
                           }
                       }
                       else
                       {
                           if (minVer < yVers[k])
                           {
                               minVer = yVers[k];
                               minLen = k;
                               selectRGB=minRGB[k];
                           }
                       }

                   }
                   double t1, t2, t3;
                   if (selectRGB == 0)
                   {
                       t1 = 0.8;
                       t2 = 0.5;
                       t3 = 0.5;
                   }
                   else if (selectRGB == 1)
                   {
                       t1 = 0.8;
                       t2 = 0.5;
                       t3 = 0.5;
                   }
                   else
                   {
                       t1 = 0.8;
                       t2 = 0.8;
                       t3 = 0.5;
                   }

                   for (int k = 0; k < minLen; k++)
                   {
                      bmpData[i, k * 3 + colPoint * 3 + 0] = (byte)cutNum(0,255,  (int)((b[0]*t1) * (k - xAves[minLen]) + (t1+1)*a[0]));
                      bmpData[i, k * 3 + colPoint * 3 + 1] = (byte)cutNum(0, 255, (int)((b[1]*t2) * (k - xAves[minLen]) + (t2+1)*a[1]));
                      bmpData[i, k * 3 + colPoint * 3 + 2] = (byte)cutNum(0, 255, (int)((b[2]*t3) * (k - xAves[minLen]) + (t3+1)*a[2]));
                      
                   }
                       colPoint+=minLen; 
               }

           } while (colPoint  < w );
           }

           Color c;
           for (int i = 0; i < inBit.Height; i++)
           {
               for (int j = 0; j < inBit.Width; j++)
               {

                   c = Color.FromArgb(bmpData[i, j * 3 + 0],
                   bmpData[i, j * 3 + 1],
                   bmpData[i, j * 3 + 2]);
                   inBit.SetPixel(j, i, c);
               }
           }
           return inBit;
       }





       public PictToCircle()
       {
           
       }








       public void changeCircle(Bitmap bmp1)
       {
           this.b1 = bmp1;
           this.b2 = null;
           this.b1 = bmp1;
           this.h = bmp1.Height;
           this.w = bmp1.Width;
           this.max = Math.Max(this.h, this.w);
           this.b2 = new Bitmap(b1.Width, b1.Height);
           for (int i = 0; i < w; i++)
           {
               for (int j = 0; j < h; j++)
               {
                   b2.SetPixel(i, j, Color.White);
               }

           }
           
           int nowSize = (int)Math.Floor(max / 3.0);
           int tUp = 0;
           int incK = 1;

           while (nowSize > 1)
           {

               nowSize = (int)(nowSize / 1.717);
               for (int i = 0; i < b1.Width / nowSize; i++)
               {
                   for (int j = 0; j < b1.Height / nowSize; j++)
                   {
                       if (nowSize > 5)
                       {
                           tUp = 8;
                       }
                       else
                       {
                           tUp = 3;
                           incK = 2;
                       }
                       for (int k = 0; k < tUp; k+=incK)
                       {
                           CellToCircle(rnd.Next(4 * nowSize) - 2 * nowSize + i * nowSize, rnd.Next(4 * nowSize) - 2 * nowSize + j * nowSize, nowSize);
                       }
                   }
               }

           }


       }






       public void CellToCircle(int x, int y, int size)
       {
           if (rnd.Next(100) > 95)
           {
               size += rnd.Next(2);
           }

           int sx = cutNum(0, this.b1.Width - 1, x - size);
           int sy = cutNum(0, this.b1.Height - 1, y - size);
           int ex = cutNum(1, this.b1.Width, x + size);
           int ey = cutNum(1, this.b1.Height, y + size);

           int checkR = 1600;
           if (size > 4)
           {
               checkR = 2500;
           }
           else
           {
               checkR = 4900;
           }
           float aveR = 0;
           float aveG = 0;
           float aveB = 0;
           Color c1;
           int th = (int)Math.Floor((Math.Sqrt(size * 3)));
           int tw = th;
           int t1 = ((ex - sx) / tw + 1) * ((ey - sy) / tw + 1);


           for (int i = sx; i < ex; i += tw)
           {
               for (int j = sy; j < ey; j += th)
               {
                   //各色の平均をとる
                   c1 = b1.GetPixel(i, j);
                   aveR += c1.R;
                   aveG += c1.G;
                   aveB += c1.B;
               }
           }

           aveR /= t1;
           aveG /= t1;
           aveB /= t1;


           float ave = 0;
           float count = 0;
           for (int i = sx; i < ex; i += tw)
           {
               for (int j = sy; j < ey; j += th)
               {
                   //平均からの距離を図る
                   c1 = b1.GetPixel(i, j);
                   ave = (aveR - c1.R) * (aveR - c1.R);
                   ave += (aveG - c1.G) * (aveG - c1.G);
                   ave += (aveB - c1.B) * (aveB - c1.B);

                   if (ave < checkR)
                   {
                       count++;
                   }
               }
           }
           if (rnd.Next(10) > 3)
           {
               c1 = b1.GetPixel(rnd.Next(ex - sx) + sx, rnd.Next(ey - sy) + sy);

           }
           else
           {
               c1 = Color.FromArgb((int)(aveR), (int)(aveG), (int)(aveB));
           }
           float tUp2 = 0;
           if (size > 12)
           {
               tUp2 = 0.5F;
           }
           else if (size > 7)
           {
               tUp2 = 0.4F;
           }
           else
           {
               tUp2 = 0.3F;
           }

           if (count / t1 > tUp2)
           {
               cellToCircle2(sx, sy, ex, ey, x, y, size, c1);
           }
       }


       void cellToCircle2(int sx, int sy, int ex, int ey, int x, int y, int size, Color c)
       {
           Color c2;
           int tHeight, sy2, ey2;

           int size2 = size * size;
           byte r1, g1, b1;

           for (int i = sx; i < ex; i++)
           {
               if (size > 2)
               {
                   tHeight = (int)Math.Floor(Math.Sqrt(size2 - (double)((x - i) * (x - i))));
                   sy2 = cutNum(sy, ey, y - tHeight);
                   ey2 = cutNum(sy, ey, y + tHeight);
               }
               else
               {
                   sy2 = sy;
                   ey2 = ey;
               }
               for (int j = sy; j < ey; j++)
               {

                   if (size >7)
                   {
                       c2 = this.b1.GetPixel(i, j);
                       
                       r1 = (byte)cutNum(0, 255, (int)(c.R * 0.7 +  c2.R * 0.3));
                       g1 = (byte)cutNum(0, 255, (int)(c.G * 0.7 + c2.G * 0.3));
                       b1 = (byte)cutNum(0, 255, (int)(c.B * 0.7 + c2.B * 0.3));
                       c2 = Color.FromArgb(r1, g1, b1);
                       this.b2.SetPixel(i, j, c2);
                   }
                   else
                   {
                       c2 = this.b1.GetPixel(i, j);
                       g1 = c2.G;
                       b1 = c2.B;
                       r1 = c2.R;
                       c2 = this.b2.GetPixel(i, j);
                       if (((int)(r1) - g1) - b1 > 100)
                       {
                          r1 = (byte)(r1 * 0.3 + 255 * 0.7);
                          g1 =(byte)((g1 * 0.5) + rnd.Next(10));
                          b1 = (byte)((g1 * 0.5)+ rnd.Next(10));
                       }
                       if (((int)(g1) - r1) - b1 > 100)
                       {
                           g1 = (byte)(g1 * 0.3 + 255 * 0.7);
                           r1 = (byte)((g1 * 0.4)+rnd.Next(10));
                           b1 = (byte)((b1 * 0.4)+rnd.Next(10));
                       }
                       if (((int)(b1) - r1) - g1 > 100)
                       {
                           b1 = (byte)(b1 * 0.3 + 255 * 0.7);
                           r1 = (byte)((r1 * 0.4)+rnd.Next(10));
                           g1 = (byte)((g1 * 0.4)+rnd.Next(10));
                       }

                       if (((int)(b1) + r1) + g1 <400)
                       {
                           b1 = (byte)(b1 * 0.6);
                           r1 = (byte)(r1 * 0.6);
                           g1 = (byte)(g1 * 0.6);
                       }
                       r1 = (byte)cutNum(0, 255, (int)(c.R * 0.4 + r1 * 0.3+c2.R*0.4));
                       g1 = (byte)cutNum(0, 255, (int)(c.G * 0.4+  g1 * 0.3+c2.G*0.4 ));
                       b1 = (byte)cutNum(0, 255, (int)(c.B * 0.4 + b1 * 0.3+c2.B*0.4 ));
                       c2 = Color.FromArgb(r1, g1, b1);
                       this.b2.SetPixel(i, j, c2);
                   }



               }
           }
       }
       public Bitmap getPict()
       {
           return this.b2;
       }









       private int cutNum(int min, int max, int t)
       {
           if (t < min)
           {
               t = min;
           }
           if (t > max)
           {
               t = max;
           }
           return t;
       }

   }
}

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2010年05月23日 14:21