「写真の円形補正法C#サンプルプログラム2」の編集履歴(バックアップ)一覧はこちら

写真の円形補正法C#サンプルプログラム2」(2010/05/21 (金) 16:46:23) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

&ref(自分で作った画像処理ソフトの力はこの程度だったsono5.png) このページに掲載しているのは絵を水彩画風にするフィルタのサンプルプログラム。 右がフィルタ加工後、左が加工前の元写真。 PictToCircleというクラスを使って写真を加工する。 このページのサンプルコードの使用例 FormにPictureBoxとコマンドボタンを一つずつ用意し、PictureBoxにイラストを設定しておく。 //PictToCircleと言うクラスにb1というBitmapを渡し、PTC.changeCircle()メソッドを実行すると //PTC内に左のフィルタ後画像が出来る。 //(PTC.getPict())でフィルタ済みの画像を取り出すことが可能。 private void button1_Click(object sender, EventArgs e) { Bitmap b1 = new Bitmap(pictureBox1.Image); // フィルタ処理したい画像をセットする //pictureBox1.Image =b1; PictToCircle PTC = new WindowsFormsApplication2.PictToCircle(b1);//フィルタ処理をするためのクラスを準備、クラスにはフィルタ処理したい画像がセットされる PTC.changeCircle();//右写真を左の水彩画風にするフィルタをかける b1 = (PTC.getPict());//フィルタ済みの画像を取り出す pictureBox1.Image = b1;//画像をセットしなおす //b1.Dispose(); } -以下サンプルプログラム、FormにPictureBoxとコマンドボタンを一つずつ用意し、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; 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(b1); PTC.changeCircle(); b1 = (PTC.getPict()); pictureBox1.Image = b1; //b1.Dispose(); } private void pictureBox1_Click(object sender, EventArgs e) { pictureBox1.Image = Image.FromFile("D:/色々/中高生向け戦争小説 ギガンダム討伐/10774542.jpg"); } } 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; 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 = 2; 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.6F; } else { tUp2 = 0.4F; } 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 > 8) { c2 = this.b1.GetPixel(i, j); r1 = (byte)cutNum(0, 255, (int)(c.R * 0.5+ c2.R * 0.5)); g1 = (byte)cutNum(0, 255, (int)(c.G * 0.5 + c2.G * 0.5)); 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); } 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.2+ 255 * 0.8); g1 =(byte)(g1 * 0.5); b1 =(byte)(g1 * 0.5); } if (((int)(g1) - r1) - b1 > 100) { g1 = (byte)(g1 * 0.2 + 255 * 0.8); r1 = (byte)(g1 * 0.4); b1 = (byte)(b1 * 0.4); } if (((int)(b1) - r1) - g1 > 100) { b1 = (byte)(b1 * 0.2 + 255 * 0.8); r1 = (byte)(r1 * 0.4); g1 = (byte)(g1 * 0.4); } if (((int)(b1) + r1) + g1 <240) { b1 = (byte)(b1 * 0.4); r1 = (byte)(r1 * 0.4); g1 = (byte)(g1 * 0.4); } r1 = (byte)cutNum(0, 255, (int)(c.R * 0.3 + r1 * 0.4+c2.R*0.5)); g1 = (byte)cutNum(0, 255, (int)(c.G * 0.3+ g1 * 0.4+c2.G*0.5 )); b1 = (byte)cutNum(0, 255, (int)(c.B * 0.3 + b1 * 0.4+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; } } }
&ref(自分で作った画像処理ソフトの力はこの程度だったsono5.png) このページに掲載しているのは絵を水彩画風にするフィルタのサンプルプログラム。 右がフィルタ加工後、左が加工前の元写真。 PictToCircleというクラスを使って写真を加工する。 このページのサンプルコードの使用例 FormにPictureBoxとコマンドボタンを一つずつ用意し、PictureBoxにイラストを設定しておく。 //PictToCircleと言うクラスにb1というBitmapを渡し、PTC.changeCircle()メソッドを実行すると //PTC内に左のフィルタ後画像が出来る。 //(PTC.getPict())でフィルタ済みの画像を取り出すことが可能。 private void button1_Click(object sender, EventArgs e) { Bitmap b1 = new Bitmap(pictureBox1.Image); // フィルタ処理したい画像をセットする //pictureBox1.Image =b1; PictToCircle PTC = new WindowsFormsApplication2.PictToCircle(b1);//フィルタ処理をするためのクラスを準備、クラスにはフィルタ処理したい画像がセットされる PTC.changeCircle();//右写真を左の水彩画風にするフィルタをかける b1 = (PTC.getPict());//フィルタ済みの画像を取り出す pictureBox1.Image = b1;//画像をセットしなおす //b1.Dispose(); } -以下サンプルプログラム、FormにPictureBoxとコマンドボタンを一つずつ用意し、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; 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(b1); PTC.changeCircle(); b1 = (PTC.getPict()); pictureBox1.Image = b1; //b1.Dispose(); } private void pictureBox1_Click(object sender, EventArgs e) { pictureBox1.Image = Image.FromFile("D:/色々/中高生向け戦争小説 ギガンダム討伐/10774542.jpg"); } } 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; 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 = 2; 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.6F; } else { tUp2 = 0.4F; } 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 > 8) { c2 = this.b1.GetPixel(i, j); r1 = (byte)cutNum(0, 255, (int)(c.R * 0.5+ c2.R * 0.5)); g1 = (byte)cutNum(0, 255, (int)(c.G * 0.5 + c2.G * 0.5)); 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); } 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.2+ 255 * 0.8); g1 =(byte)(g1 * 0.5); b1 =(byte)(g1 * 0.5); } if (((int)(g1) - r1) - b1 > 100) { g1 = (byte)(g1 * 0.2 + 255 * 0.8); r1 = (byte)(g1 * 0.4); b1 = (byte)(b1 * 0.4); } if (((int)(b1) - r1) - g1 > 100) { b1 = (byte)(b1 * 0.2 + 255 * 0.8); r1 = (byte)(r1 * 0.4); g1 = (byte)(g1 * 0.4); } if (((int)(b1) + r1) + g1 <240) { b1 = (byte)(b1 * 0.4); r1 = (byte)(r1 * 0.4); g1 = (byte)(g1 * 0.4); } r1 = (byte)cutNum(0, 255, (int)(c.R * 0.3 + r1 * 0.4+c2.R*0.5)); g1 = (byte)cutNum(0, 255, (int)(c.G * 0.3+ g1 * 0.4+c2.G*0.5 )); b1 = (byte)cutNum(0, 255, (int)(c.B * 0.3 + b1 * 0.4+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; } } }

表示オプション

横に並べて表示:
変化行の前後のみ表示: