「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;
}
}
}