※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

C#プログラム
製作者 堀江伸一
色使いまねフィルタ2

pictureBox2つ、ボタン3つおいて使うサンプルフィルタ。

ボタン2を押すとダイアログが出るので、フィルタの教師データとなる画像を選択。
ボタン3も押すと、フィルタが適用される画像が準備される。


ボタン1を押すと、フィルタが適用される。
ボタン1を押すと、ボタン3で用意した画像からカラーテーブルが作成され、フィルタされる画像をそのカラーテーブルに近づける処理が実行される。







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.Threading;
public delegate void ExampleCallback(Bitmap outBit, PictureBox p1);

namespace WindowsFormsApplication2
{
   public partial class Form1 : Form
   {
       int tc = 0;
       //Bitmap lastB;
       public Form1()
       {
           InitializeComponent();

       }

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

       private void button1_Click(object sender, EventArgs e)
       {
           Bitmap b2 = new Bitmap(pictureBox1.Image);
           
           Bitmap b1 = new Bitmap(pictureBox2.Image);
           



           //pictureBox1.Image  =b1;

           pictFilter PTC1 = new WindowsFormsApplication2.pictFilter();
           //pict_RGB_And_Deviation aveDev = new pict_RGB_And_Deviation(150, 150, 150, 70, 70, 70);
           //上記メソッドは
           //b2 = PTC1.cercleChange(b2);
           //b1 = PTC1.cercleChange(b1);
  
           //pictureBox1.Image = b2;  
           pictureBox1.Image= PTC1.Color_imitation_filter(b1,b2,10);

           //pictureBox1.Image = PTC1.standard_deviation_filter(aveDev, b2);
           //pictureBox1.Image  =PTC1.lineFilter(b1);
           //b1=PTC1.lineFilter(b1);

           /*pictFilter PTC = new WindowsFormsApplication2.pictFilter(PTC1.lineFilter (b1), new ExampleCallback(ResultCallback),pictureBox1);
           Thread t1 =new Thread(new ThreadStart(PTC.cercleChange));
           t1.Start();
           t1.Join();
           */
           //pictFilter PTC = new WindowsFormsApplication2.pictFilter();
           //pictureBox1.Image = PTC.lineFilter(b1);
           //pictureBox1.Image = PTC.flatFilter2( PTC.cercleChange      (b1)) ;
           //b1.Dispose();
       }
       public static void ResultCallback(Bitmap outBit, PictureBox p1)
       {
           p1.Image = outBit;
       }


       private void pictureBox1_Click(object sender, EventArgs e)
       {
           tc++;
           pictureBox1.Top = 0;
           pictureBox1.Left = 0;

       }

       private void button2_Click(object sender, EventArgs e)
       {
           OpenFileDialog ofd = new OpenFileDialog();
           ofd.Filter = "画像ファイル(*.jpeg;*.jpg;*.gif)|*.jpeg;*.jpg;*.gif|すべてのファイル(*.*)|*.*";
           if (ofd.ShowDialog() == DialogResult.OK)
           {
               pictureBox2.Image = Image.FromFile(ofd.FileName); 
           }
       }

       private void button3_Click(object sender, EventArgs e)
       {
           OpenFileDialog ofd = new OpenFileDialog();
           ofd.Filter = "画像ファイル(*.jpeg;*.jpg;*.gif)|*.jpeg;*.jpg;*.gif|すべてのファイル(*.*)|*.*";
           if (ofd.ShowDialog() == DialogResult.OK)
           {
               pictureBox1.Image = Image.FromFile(ofd.FileName);
           }
       }

   }
   class pictFilter
   {
       Random rnd = new Random();
       Bitmap pictOut = null;
       int h;//絵の高さ
       int w;//絵の横幅
       Bitmap pictIn;
       ExampleCallback callback;
       PictureBox lastPict;
       cell[, ,] cells;
       int cell_size;
       public pictFilter()
       {
           h = 0;
           w = 0;
       }


       public Bitmap Color_imitation_filter(Bitmap b1, Bitmap b2,int c_size)
       {
           cell_size = c_size;
           int size=255/cell_size+5;
           cells = new cell[size, size, size];

           for (int i = 0; i < size; i++)
           {
               for (int j = 0; j < size; j++)
               {
                   for (int k = 0; k < size; k++)
                   {
                       cells[i, j, k] = new cell();
                   }
               }
           }

           pict_RGB_And_Deviation aveDev1=new pict_RGB_And_Deviation(b1);
           pict_RGB_And_Deviation aveDev2 = new pict_RGB_And_Deviation(b2);

           int sabunR =(int)Math.Floor ( aveDev1.aveR - aveDev2.aveR);
           int sabunG =(int)Math.Floor ( aveDev1.aveG - aveDev2.aveG);
           int sabunB = (int)Math.Floor(aveDev1.aveB - aveDev2.aveB);    

           Color C1;
           Bitmap b3=new Bitmap (b2.Width,b2.Height );
           for (int i = 0; i < b1.Width; i++)
           {
               for (int j = 0; j < b1.Height; j++)
               {
                   C1 = b1.GetPixel(i, j);
                  
                   cells[get_cell_point(C1.R), get_cell_point(C1.G), get_cell_point(C1.B)].add(C1.R, C1.G, C1.B);
               }
           }
           Color nextColor;
           


           for (int i = 0; i < b2.Width; i++)
           {
               for (int j = 0; j < b2.Height; j++)
               {
                   C1 = b2.GetPixel(i, j);
                   //nextColor=C1;
                   nextColor =Color.FromArgb(cutNum(0, 255, C1.R + sabunR/2),
                       cutNum(0, 255, C1.G + sabunG/2),
                       cutNum(0, 255, C1.B + sabunB/2));
                   //nextColor = getAveCountCell(nextColor);
                   nextColor  = getMaxCountCell(nextColor);
                   //
                   b3.SetPixel(i, j, nextColor); 
               }
           }


               return b3;
       }


       public Color getAveCountCell(Color C1)
       {
           List<cell> cell_list = new List<cell>(); //
           int rPoint, gPoint, bPoint;
           cell myCell;
           //Count数の比率からセルを平均的に返す処理
           rPoint = get_cell_point(C1.R);
           gPoint = get_cell_point(C1.G);
           bPoint = get_cell_point(C1.B);
           int sumCount=0;

           for (int i = -2; i < 3; i++)
           {
               for (int j = -2; j < 3; j++)
               {
                   for (int k = -2; k < 3; k++)
                   {
                       myCell = cells[rPoint+i, gPoint+j, bPoint+k];
                       
                       if (myCell.getCount() > 0)
                       {
                           cell_list.Add(myCell);
                           sumCount  +=myCell.getCount(); 
                       }
                   }
               }
           }

           if (cell_list.Count > 0)
           {
               int rndC=rnd.Next(sumCount);
               int tSum=0;
               Color C2=C1;
               foreach (cell myCell1 in cell_list)
               {
                   tSum +=myCell1.getCount();  
                   if(tSum>rndC){
                       C2=myCell1.aveColor() ;
                       break;
                   }
               }
               
               
               
               
               return Color.FromArgb(
                   (int)Math.Floor(C2.R * 0.1d + C1.R * 0.9d),
                   (int)Math.Floor(C2.G * 0.1d + C1.G * 0.9d),
                   (int)Math.Floor(C2.B * 0.1d + C1.B * 0.9d)
                   );
           }
           else
           {
               return C1;
           }

       }
       
       public Color getMaxCountCell(Color C1)
       {
           List<cell> cell_list = new List<cell>(); //
           int maxCount = 1;
           int rPoint,gPoint,bPoint;
           cell myCell;
           //Countが最も大きいセルを返す処理
           rPoint=get_cell_point(C1.R );  
           gPoint=get_cell_point(C1.G);
           bPoint=get_cell_point (C1.B);
           for (int i = -2; i < 3; i++)
           {
               for (int j = -2; j < 3; j++)
               {
                   for (int k = -2; k < 3; k++)
                   {
                       myCell=cells[rPoint+i,gPoint+j,bPoint+k]; 
                       if(myCell.getCount ()>maxCount ){
                           cell_list.Clear();
                           cell_list.Add(myCell);
                           maxCount = myCell.getCount(); 
                       }else if(myCell.getCount ()==maxCount ){
                           cell_list.Add(myCell);
                       }

                   }
               }
           }

           if (cell_list.Count>0)
           {                
               Color C2;
               C2=cell_list[rnd.Next(cell_list.Count)].aveColor()  ;

               return Color.FromArgb(
                   (int)Math.Floor (C2.R * 0.8d + C1.R * 0.2d),
                   (int)Math.Floor (C2.G * 0.8d + C1.G * 0.2d),
                   (int)Math.Floor (C2.B * 0.8d + C1.B * 0.2d)
                   ); 
           }
           else
           {
               return C1;
           }
           
       }



       public int get_cell_point(int rgb)
       {
           return (rgb / cell_size) +2; 
       }
     

       public Bitmap standard_deviation_filter(pict_RGB_And_Deviation aveDev1, Bitmap b2)
       {
           Color C2;
           Bitmap outBit;
           double tR, tG, tB;
           int tR1, tG1, tB1;
           pict_RGB_And_Deviation aveDev2 = new pict_RGB_And_Deviation(b2);

           outBit = new Bitmap(b2.Width, b2.Height);

           for (int i = 0; i < b2.Width; i++)
           {
               for (int j = 0; j < b2.Height; j++)
               {
                   C2 = b2.GetPixel(i, j);
                   //tR = ((C2.R - aveDev2.aveR) / aveDev2.devR) * ((C2.R - aveDev2.aveR) / aveDev2.devR) * aveDev1.devR + aveDev1.aveR;
                   //tG = ((C2.G - aveDev2.aveG) / aveDev2.devG) * (C2.G - aveDev2.aveG) / aveDev2.devG * aveDev1.devG + aveDev1.aveG;
                   //tB = ((C2.B - aveDev2.aveB) / aveDev2.devB) * (C2.B - aveDev2.aveB) / aveDev2.devB * aveDev1.devB + aveDev1.aveB;

                   tR = Math.Log(3 * ((C2.R - aveDev2.aveR) / aveDev2.devR)) * aveDev1.devR + aveDev1.aveR;
                   tG = Math.Log(3 * ((C2.G - aveDev2.aveG) / aveDev2.devG)) * aveDev1.devG + aveDev1.aveG;
                   tB = Math.Log(3 * ((C2.B - aveDev2.aveB) / aveDev2.devB)) * aveDev1.devB + aveDev1.aveB;
                   
                   /*
                   tR = (C2.R - aveDev2.aveR);
                   tR = tR / 2.0 + 0.5;
                   if (tR > 0.5)
                   {
                       tR = -Math.Pow(2 * tR - 2, 0.7) / 2 + 1;
                   }
                   else
                   {
                       tR=2 * Math.Pow(tR, 0.7/2);
                   }
                   tR = tR * 2 - 1;
                   */
                   
                   
                   tR1 = cutNum(0, 255, (int)Math.Floor(tR));
                   tG1 = cutNum(0, 255, (int)Math.Floor(tG));
                   tB1 = cutNum(0, 255, (int)Math.Floor(tB));
                   outBit.SetPixel(i, j, Color.FromArgb(tR1, tG1, tB1));

               }
           }
           //生物の遺伝子構造解析をして病気対策をするとき、遺伝子コードのパターンマッチにパソコンを使うとか、本当はそういうプログラム書けたらなと思ったり、

           return outBit;
       }

       public Bitmap standard_deviation_filter(Bitmap b1, Bitmap b2)
       {
           Color C2;
           Bitmap outBit;
           double tR, tG, tB;
           int tR1, tG1, tB1;
           pict_RGB_And_Deviation aveDev1 = new pict_RGB_And_Deviation(b1);
           pict_RGB_And_Deviation aveDev2 = new pict_RGB_And_Deviation(b2);

           outBit = new Bitmap(b2.Width, b2.Height);

           for (int i = 0; i < b2.Width; i++)
           {
               for (int j = 0; j < b2.Height; j++)
               {
                   C2 = b2.GetPixel(i, j);
                   tR = ((C2.R - aveDev2.aveR) / aveDev2.devR) * aveDev1.devR + aveDev1.aveR;
                   tG = (C2.G - aveDev2.aveG) / aveDev2.devG * aveDev1.devG + aveDev1.aveG;
                   tB = (C2.B - aveDev2.aveB) / aveDev2.devB * aveDev1.devB + aveDev1.aveB;
                   //tR = ((C2.R - aveDev2.aveR) / aveDev2.devR) * ((C2.R - aveDev2.aveR) / aveDev2.devR) * aveDev1.devR + aveDev1.aveR;
                   //tG = ((C2.G - aveDev2.aveG) / aveDev2.devG) * ((C2.G - aveDev2.aveG) / aveDev2.devG) * aveDev1.devG + aveDev1.aveG;
                   //tB = ((C2.B - aveDev2.aveB) / aveDev2.devB) * ((C2.B - aveDev2.aveB) / aveDev2.devB) * aveDev1.devB + aveDev1.aveB;
                   

                   tR1 = cutNum(0, 255, (int)Math.Floor(tR));
                   tG1 = cutNum(0, 255, (int)Math.Floor(tG));
                   tB1 = cutNum(0, 255, (int)Math.Floor(tB));
                   outBit.SetPixel(i, j, Color.FromArgb(tR1, tG1, tB1));

               }
           }
           //生物の遺伝子構造解析をして病気対策をするとき、遺伝子コードのパターンマッチにパソコンを使うとか、本当はそういうプログラム書けたらなと思ったり、

           return outBit;
       }






       public pictFilter(Bitmap b1, ExampleCallback callbackDelegate, PictureBox p1)
       {
           this.pictIn = b1;
           h = 0;
           w = 0;
           callback = callbackDelegate;
           lastPict = p1;
       }
       public Bitmap cercleChange(Bitmap b1)
       {
           //各ピクセルの色空間内の位置を点(ccR,ccB,ccG)を中心に体積拡大する処理
           //このメソッドはスレッドで呼ぶこと前提にしている
           float ccR = 128;
           float ccG = 128;
           float ccB = 128;
           float a = 2.0f;
           float b = 0.5f;
           double cR, cG, cB;
           double r1 = 0;
           double r2 = 0;
           Color C1;
           //double rk;

           this.h = b1.Height;
           this.w = b1.Width;
           Bitmap pictOut = new Bitmap(this.w, this.h);
           //Threadをとめる処理

           for (int i = 0; i < this.w; i++)
           {
               for (int j = 0; j < this.h; j++)
               {
                   C1 = b1.GetPixel(i, j);
                   r1 = Math.Sqrt((C1.R - ccR) * (C1.R - ccR) +
                       (C1.G - ccG) * (C1.G - ccG) +
                       (C1.B - ccB) * (C1.B - ccB)) / 255;

                   r2 = (a * r1 + b);
                   cR = r2 * (C1.R - ccR) + ccR;
                   cG = r2 * (C1.G - ccG) + ccG;
                   cB = r2 * (C1.B - ccB) + ccB;


                   pictOut.SetPixel(i, j,
                       Color.FromArgb(
                       cutNum(0, 255, (int)(cR)),
                       cutNum(0, 255, (int)(cG)),
                       cutNum(0, 255, (int)(cB))));
                   //これはLispではありませんw
               }
           }



           //テンプレ
           //this.h = pictIn.Height;
           //this.w = pictIn.Width;
           //pictOut = new Bitmap(this.w, this.h);
           //for(int i=0;i<this.w;i++){
           //    for (int j = 0; j < this.h; j++)
           //    {   
           //    }
           //}
           return pictOut;
       }
       public void cercleChange()
       {
           //各ピクセルの色空間内の位置を点(ccR,ccB,ccG)を中心に体積拡大する処理
           //このメソッドはスレッドで呼ぶこと前提にしている
           float ccR = 128;
           float ccG = 128;
           float ccB = 128;
           float a = 2.0f;
           float b = 0.5f;
           double cR, cG, cB;
           double r1 = 0;
           double r2 = 0;
           Color C1;
           //double rk;

           this.h = pictIn.Height;
           this.w = pictIn.Width;
           pictOut = new Bitmap(this.w, this.h);
           //Threadをとめる処理

           for (int i = 0; i < this.w; i++)
           {
               for (int j = 0; j < this.h; j++)
               {
                   C1 = pictIn.GetPixel(i, j);
                   r1 = Math.Sqrt((C1.R - ccR) * (C1.R - ccR) +
                       (C1.G - ccG) * (C1.G - ccG) +
                       (C1.B - ccB) * (C1.B - ccB)) / 255;

                   r2 = (a * r1 + b);
                   cR = r2 * (C1.R - ccR) + ccR;
                   cG = r2 * (C1.G - ccG) + ccG;
                   cB = r2 * (C1.B - ccB) + ccB;


                   pictOut.SetPixel(i, j,
                       Color.FromArgb(
                       cutNum(0, 255, (int)(cR)),
                       cutNum(0, 255, (int)(cG)),
                       cutNum(0, 255, (int)(cB))));
                   //これはLispではありませんw
               }
               if (i % 10 == 0)
               {
                   Thread.Sleep(30);
               }
           }
           //スレッドのOutput用命令
           callback(pictOut, lastPict);



           //テンプレ
           //this.h = pictIn.Height;
           //this.w = pictIn.Width;
           //pictOut = new Bitmap(this.w, this.h);
           //for(int i=0;i<this.w;i++){
           //    for (int j = 0; j < this.h; j++)
           //    {   
           //    }
           //}
           //return pictOut;
       }
       public Bitmap flatFilter2(Bitmap pictIn)
       {
           //色空間内の点の色座標をを法線ベクトル(1,1,1),rgbAve=r+g+bとなる平面から遠くへ引き離したり、近づけたりする処理
           Color C1;
           this.h = pictIn.Height;
           this.w = pictIn.Width;
           double flatLen = 0;
           double r1 = 0;

           float rgbAve = 256;
           pictOut = new Bitmap(this.w, this.h);
           double a = -1.0;
           double b = 2.0;
           double root3 = Math.Sqrt(3);
           double v1 = 184;
           double maxRGB = 0, minRGB = 0;

           for (int i = 0; i < this.w; i++)
           {
               for (int j = 0; j < this.h; j++)
               {
                   C1 = pictIn.GetPixel(i, j);
                   flatLen = (C1.R + C1.G + C1.B - rgbAve) / (root3); //点と平面までの距離
                   r1 = Math.Sign(flatLen) * ((a * Math.Abs(flatLen) / v1 + b));//点と平面までの距離に基づいて、次の点の平面からの距離を決定する。
                   maxRGB = Math.Max(C1.R + r1 * v1, Math.Max(C1.G + r1 * v1, C1.B + r1 * v1));
                   if (maxRGB > 255)
                   {
                       if (C1.R > C1.G && C1.R > C1.B)
                       {
                           r1 = r1 - (255 - C1.R) / v1 - 1;
                       }
                       else if (C1.G > C1.R && C1.G > C1.B)
                       {
                           r1 = r1 - (255 - C1.G) / v1 - 1;
                       }
                       else
                       {
                           r1 = r1 - (255 - C1.B) / v1 - 1;
                       }
                   }
                   minRGB = Math.Min(C1.R + r1 * v1, Math.Min(C1.G + r1 * v1, C1.B + r1 * v1));
                   if (minRGB < 0)
                   {
                       if (C1.R < C1.G && C1.R < C1.B)
                       {
                           r1 = r1 - (C1.R) / v1 - 1;
                       }
                       else if (C1.G < C1.R && C1.G < C1.B)
                       {
                           r1 = r1 - (C1.G) / v1 - 1;
                       }
                       else
                       {
                           r1 = r1 - (C1.B) / v1 - 1;
                       }
                   }


                   pictOut.SetPixel(i, j, Color.FromArgb(
                       cutNum(0, 255, (int)(C1.R + r1 * v1)),
                       cutNum(0, 255, (int)(C1.G + r1 * v1)),
                       cutNum(0, 255, (int)(C1.B + r1 * v1))));
               }
           }
           return pictOut;
       }


       public Bitmap adsorptionFilter(Bitmap pictIn)
       {
           //テンプレ
           Color C1;
           this.h = pictIn.Height;
           this.w = pictIn.Width;
           pictOut = new Bitmap(this.w, this.h);
           byte maxRGB;
           byte minRGB;
           double rgbR, rgbG, rgbB;

           for (int i = 0; i < this.w; i++)
           {
               for (int j = 0; j < this.h; j++)
               {



                   C1 = pictIn.GetPixel(i, j);
                   rgbR = C1.R;
                   rgbG = C1.G;
                   rgbB = C1.B;

                   maxRGB = (byte)Math.Max(rgbR, Math.Max(rgbG, rgbB));
                   minRGB = (byte)Math.Min(rgbR, Math.Min(rgbG, rgbB));


                   if (255 - maxRGB < minRGB)
                   {
                       if (rgbR == maxRGB)
                       {
                           rgbR = 255 * 0.5 + rgbR * 0.5;
                       }
                       else if (rgbB == maxRGB)
                       {
                           rgbB = 255 * 0.5 + rgbB * 0.5;
                       }
                       else
                       {
                           rgbG = 255 * 0.5 + rgbG * 0.5;
                       }
                   }
                   else
                   {
                       if (C1.R == minRGB)
                       {
                           rgbR = rgbR * 0.5;
                       }
                       else if (C1.G == minRGB)
                       {
                           rgbG = rgbG * 0.5;
                       }
                       else
                       {
                           rgbB = rgbB * 0.5;
                       }
                   }

                   pictOut.SetPixel(i, j,
                       Color.FromArgb(
                           (int)rgbR,
                           (int)rgbG,
                           (int)rgbB));
               }
           }
           return pictOut;
       }





       public Bitmap lineFilter(Bitmap pictIn)
       {
           //テンプレ
           Color C1;
           this.h = pictIn.Height;
           this.w = pictIn.Width;
           double r1;
           double r2;
           double[] vecOB = { -1, -1, 1 };
           double[] vecOH = { 0, 0, 0 };
           double[] vecOA = { 0, 0, 0 };
           double[] vecHA = { 0, 0, 0 };
           double[] vecOA2 = { 0, 0, 0 };
           double[] vecCen = { 255, 255, 0 };
           double LenOH, LenOB, LenHA = 0;

           double a = -1.0;
           double b = 2.0;
           LenOB = Math.Sqrt(vecOB[0] * vecOB[0] + vecOB[1] * vecOB[1] + vecOB[2] * vecOB[2]);
           pictOut = new Bitmap(this.w, this.h);



           for (int i = 0; i < this.w; i++)
           {
               for (int j = 0; j < this.h; j++)
               {
                   LenHA = 0;


                   C1 = pictIn.GetPixel(i, j);
                   vecOA[0] = C1.R - vecCen[0];
                   vecOA[1] = C1.G - vecCen[1];
                   vecOA[2] = C1.B - vecCen[2];

                   LenOH = (vecOA[0] * vecOB[0] + vecOA[1] * vecOB[1] + vecOA[2] * vecOB[2]) / LenOB;


                   for (int k = 0; k < 3; k++)
                   {
                       vecOH[k] = LenOH / LenOB * vecOB[k];
                       vecHA[k] = -vecOH[k] + vecOA[k];
                       LenHA += vecHA[k] * vecHA[k];
                   }
                   LenHA = Math.Sqrt(LenHA);
                   r1 = LenHA / 255;
                   r2 = (a * r1 + b);


                   for (int k = 0; k < 3; k++)
                   {
                       //vecOA2[k] = cutNum(0,255,(int)( r2 * vecHA[k]  + vecOH[k]+vecCen[k]));
                       vecOA2[k] = cutNum(0, 255, (int)(r2 * vecHA[k] * 0 + vecOH[k] + vecCen[k]));
                   }

                   pictOut.SetPixel(i, j,
                       Color.FromArgb(
                           (int)vecOA2[0],
                           (int)vecOA2[1],
                           (int)vecOA2[2]));
               }
           }
           return pictOut;
       }


       public Bitmap flatFilter(Bitmap pictIn)
       {
           //テンプレ
           Color C1;
           this.h = pictIn.Height;
           this.w = pictIn.Width;
           int rgbR, rgbG, rgbB;
           pictOut = new Bitmap(this.w, this.h);



           for (int i = 0; i < this.w; i++)
           {
               for (int j = 0; j < this.h; j++)
               {
                   C1 = pictIn.GetPixel(i, j);
                   if (C1.R + C1.G + C1.B > 255)
                   {
                       rgbR = (int)(C1.R * 0.5 + 255 * 0.5);
                       rgbG = (int)(C1.G * 0.5 + 255 * 0.5);
                       rgbB = (int)(C1.B * 0.5 + 255 * 0.5);
                   }
                   else
                   {
                       rgbR = (int)(C1.R * 0.5);
                       rgbG = (int)(C1.G * 0.5);
                       rgbB = (int)(C1.B * 0.5);
                   }
                   pictOut.SetPixel(i, j, Color.FromArgb(rgbR, rgbG, rgbB));
               }
           }
           return pictOut;
       }


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

   }
   public class pict_RGB_And_Deviation
   {
       public double aveR, aveG, aveB;
       public double devR, devG, devB;
       public pict_RGB_And_Deviation(double inAveR, double inAveG, double inAveB, double inDevR, double inDevG, double inDevB)
       {
           aveR = inAveR;
           aveG = inAveG;
           aveB = inAveB;
           devR = inDevR;
           devG = inDevG;
           devB = inDevB;
       }
       public pict_RGB_And_Deviation(Bitmap b1)
       {
           Color C1;
           double countPictSize;
           for (int i = 0; i < b1.Width; i++)
           {
               for (int j = 0; j < b1.Height; j++)
               {
                   C1 = b1.GetPixel(i, j);
                   aveR += (double)C1.R;
                   aveG += (double)C1.G;
                   aveB += (double)C1.B;
               }
           }
           countPictSize = b1.Width * b1.Height;
           aveR /= countPictSize;
           aveG /= countPictSize;
           aveB /= countPictSize;
           for (int i = 0; i < b1.Width; i++)
           {
               for (int j = 0; j < b1.Height; j++)
               {
                   C1 = b1.GetPixel(i, j);
                   devR += ((double)C1.R - aveR) * ((double)C1.R - aveR);
                   devG += ((double)C1.G - aveG) * ((double)C1.G - aveG);
                   devB += ((double)C1.B - aveB) * ((double)C1.B - aveB);
               }
           }
           if (countPictSize > 1)
           {
               countPictSize--;
           }
           else
           {
               countPictSize = 1;
           }

           devR = Math.Sqrt(devR / countPictSize);
           devG = Math.Sqrt(devG / countPictSize);
           devB = Math.Sqrt(devB / countPictSize);
       }
   }
   public class cell
   {
       int sumR = 0;
       int sumG = 0;
       int sumB = 0;
       int count = 0;

       public int getCount()
       {
           return count;
       }

       public void add(int r, int g, int b)
       {
           count++;
           sumR += r;
           sumG += g;
           sumB += b;
       }
       public void add(Color C)
       {
           count++;
           sumR += C.R;
           sumG += C.G;
           sumB += C.B;

       }
       public Color aveColor()
       {
           if (count > 0)
           {
               

               return Color.FromArgb(
                   (int)sumR/count,
                   (int)sumG/count,
                   (int)sumB/count) ;
           }else{
               return (Color.FromArgb(0,0,0) );
           }
       }
   }

}