「写真の円式補正法C」の編集履歴(バックアップ)一覧はこちら
「写真の円式補正法C」(2010/05/21 (金) 12:00:10) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
写真を点描画風味や水彩画風味にすることが可能な画像フィルタクラスをC#で作成しました。
このページでは、これを実行するためのクラスとソースコードを掲載しています。
このページ掲載のサンプルコードのパラメータをいじって作ったフィルタ処理の例。
ボタン一回で下画像のようなフィルタ処理が可能です。
現在適切なパラメータを模索中です。
&ref(自分で作った画像処理ソフトの力はこの程度だったsono3.png)
パラメータをいじって作ったもう一つの例。
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#で作成しました。
このページでは、これを実行するためのクラスとソースコードを掲載しています。
このページ掲載のサンプルコードのパラメータをいじって作ったフィルタ処理の例。
ボタン一回で下画像のようなフィルタ処理が可能です。
現在適切なパラメータを模索中です。
&ref(自分で作った画像処理ソフトの力はこの程度だったsono3.png)
パラメータをいじって作ったもう一つの例。
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#サンプルプログラム2]]