写真を点描画風味や水彩画風味にすることが可能な画像フィルタクラスをC#で作成しました。

このページでは、これを実行するためのクラスとソースコードを掲載しています。
このページ掲載のサンプルコードのパラメータをいじって作ったフィルタ処理の例。
ボタン一回で下画像のようなフィルタ処理が可能です。
現在適切なパラメータを模索中です。

パラメータをいじって作ったもう一つの例。
http://www.pixiv.net/member_illust.php?mode=medium&illust_id=10719474



PictToCircleというクラスがBitmap型に対するフィルタ処理を行います。
このクラスにBitMap型を渡して使用します。
FormにPictureBox1つとボタンを一つおいてお試し下さい。



コード製作者 〒675-0033-79-16 堀江伸一
  • コード使用例


           Bitmap b1 = new Bitmap(pictureBox1.Image);    // FormにPictureBoxクラスを貼り付けておりイラストをImageに設定済み。

           PictToCircle PTC = new WindowsFormsApplication2.PictToCircle(b1);//PictToCircleというクラスにb1というBitMapオブジェを設定している

           PTC.changeCircle();//このメソッドでb1の絵を元にb1の絵を円の集合でまねした絵が作られる。
           b1 = (PTC.getPict());//真似た絵を取り出している。
           pictureBox1.Image =b1;//出来た絵をPictureBoxクラスに戻している



以下サンプルソースコード

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;
using System.IO;


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);    // 変数の宣言
           PictToCircle PTC = new WindowsFormsApplication2.PictToCircle(b1);       
           PTC.changeCircle();
           b1 = null;
           b1 = (PTC.getPict());
           pictureBox1.Image =b1;
           
       }

       private void pictureBox1_Click(object sender, EventArgs e)
       {
           pictureBox1.Image = Image.FromFile("ファイルの絶対パスを入力してください");
       }
   }

   class PictToCircle
   {
       Random rnd = new Random();
       Bitmap b1 = null;
       Bitmap b2 = null;
       int h;//高さ
       int w;//横幅
       int max;//横と高さのうちで大きいほう
       public PictToCircle(Bitmap bmp1)
       {
           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);
                   
               }

           }
       }
       
      
       
       
       
       
       
       
       public void  changeCircle(){
           int nowSize = (int)Math.Floor(max / 3.0);
           int tUp = 0;

           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 = 7;
                       }
                       else if (nowSize > 2)
                       {
                           tUp = 4;
                       }
                       else
                       {
                           tUp = 1;
                       }
                       for (int k = 0; k <tUp; k++)
                       {
                           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>3){
                   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>9){
               tUp2=0.3F;
           }else if(size>3){
               tUp2 = 0.2F;
           }else{
               tUp2=0.7F;
           }
          
          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 size2=size*size;
           byte r1, g1, b1;
           
           for (int i = sx; i < ex; i ++)
           {
               for (int j = sy; j < ey; j ++)
               {
               
                   if ((i - x) * (i - x) + (j - y) * (j - y) < size2)
                   {
                       c2 = this.b1.GetPixel(i, j);
                       if (rnd.Next(10) >2)
                       {
                           
                           r1 = (byte)cutNum(0, 255, (int)(c.R * 0.8 + c2.R * 0.4));
                           g1 = (byte)cutNum(0, 255, (int)(c.G * 0.8 + c2.G * 0.4));
                           b1 = (byte)cutNum(0, 255, (int)(c.B * 0.8 + c2.B * 0.3));
                           c2 = Color.FromArgb(r1, g1, b1);
                       }
                       else
                       {
                           r1 = (byte)cutNum(0, 255, (int)(c.R * 0.5 + c2.R * 0.5)+10);
                           g1 = (byte)cutNum(0, 255, (int)(c.G * 0.5 + c2.G * 0.5)+10);
                           b1 = (byte)cutNum(0, 255, (int)(c.B * 0.5 + c2.B * 0.5));
                           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;
       }
       
   }
}












+ タグ編集
  • タグ:
  • コード
  • C#
  • 点描画
  • 写真加工
  • 色鉛筆
  • フィルタ
  • 水彩画Filter

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

最終更新:2010年05月21日 12:00