「TVの砂嵐を再現するフィルタ」の編集履歴(バックアップ)一覧はこちら

TVの砂嵐を再現するフィルタ」(2010/05/23 (日) 12:02:13) の最新版変更点

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

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

TVの砂嵐を再現するフィルタ 何に使うかは不明。 とりあえず作ったら出来てしまった。 C#サンプルソース。 &ref(テレビの砂嵐を再現するフィルタ.png) という変換を行う。 こんなフィルタを作る何て何か間違っている気がする。 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]; double[] bBunbos=new double[12]; double[] xAves=new double[12]; double[] yVers=new double[12]; for (int i = 4; i < 12;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; for (int i = 0; i < inBit.Height; i++) { colPoint = 0; do { if (w - colPoint < 5) { //とりあえずの数式 colPoint = w; } else { if (w - colPoint < 12) { loopUp = w - colPoint; } else { loopUp = 12; } 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]; b[1] += bmpData[i, colPoint * 3 + u * 3 + 1] *1.0* xAves[k]; b[2] += bmpData[i, colPoint * 3 + u * 3 + 2] *1.0* xAves[k]; } 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]; } double minVer=yVers[4] ; int minLen=4; for (int k = 4; k < loopUp; k++) { if (minVer > yVers[k]) { minVer = yVers[k]; minLen = k; } } for (int k = 0; k < minLen; k++) { bmpData[i, k*3+colPoint*3+0]=(byte )(b[0] * (xAves[minLen] - k)+a[0]); bmpData[i, k*3+colPoint*3+1]=(byte )(b[1] * (xAves[minLen] - k)+a[1]); bmpData[i, k*3+colPoint*3+2]=(byte )(b[2] * (xAves[minLen] - k)+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; } } }
TVの砂嵐を再現するフィルタ 何に使うかは不明。 とりあえず作ったら予定と違うこんなフィルタが出来てしまった。 C#サンプルソース。 &ref(テレビの砂嵐を再現するフィルタ.png) という変換を行う。 こんなフィルタを作るって何か間違っている気がする。 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]; double[] bBunbos=new double[12]; double[] xAves=new double[12]; double[] yVers=new double[12]; for (int i = 4; i < 12;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; for (int i = 0; i < inBit.Height; i++) { colPoint = 0; do { if (w - colPoint < 5) { //とりあえずの数式 colPoint = w; } else { if (w - colPoint < 12) { loopUp = w - colPoint; } else { loopUp = 12; } 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]; b[1] += bmpData[i, colPoint * 3 + u * 3 + 1] *1.0* xAves[k]; b[2] += bmpData[i, colPoint * 3 + u * 3 + 2] *1.0* xAves[k]; } 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]; } double minVer=yVers[4] ; int minLen=4; for (int k = 4; k < loopUp; k++) { if (minVer > yVers[k]) { minVer = yVers[k]; minLen = k; } } for (int k = 0; k < minLen; k++) { bmpData[i, k*3+colPoint*3+0]=(byte )(b[0] * (xAves[minLen] - k)+a[0]); bmpData[i, k*3+colPoint*3+1]=(byte )(b[1] * (xAves[minLen] - k)+a[1]); bmpData[i, k*3+colPoint*3+2]=(byte )(b[2] * (xAves[minLen] - k)+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; } } }

表示オプション

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