「砂絵フィルタを作りたいんだけど」の編集履歴(バックアップ)一覧に戻る

砂絵フィルタを作りたいんだけど - (2010/05/23 (日) 14:21:36) のソース

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

砂絵フィルタのテスト

最初の絵が左上、右上がフィルタ一回、左下がフィルタ2回、右下がフィルタ3回適用結果です。
&ref(自分で作った画像処理ソフトの力はこの程度だったsono7.png)
このイラストはPixivイラストID 10471204を元に作成しました。


その他のフィルタ適用後イラスト
&ref(自分で作った画像処理ソフトの力はこの程度だったsono6.png)
おまけ話
このフィルタ連続適用すると、爆発に巻き込まれたような絵を作れます。
元写真 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;
        }

    }
}