C#でRGBデータを取得する際,GetPixel メソッドを利用すると処理速度が非常に遅いということから,生データを配列に吸い出す方法に変更しました。
これにより処理速度の大幅な向上が見られました。
そしてふと思いついたのですが,RGBデータの取得をマルチスレッド化することでより処理速度が向上するのではないかと考えました。
以下のコードで処理を行った際,処理速度が最速で約20[ms]でした。スレッド処理を行わない場合約35[ms]でしたので,処理速度の向上が得られている様な気がしますが
スレッド処理した際,60[ms]程かかる場合が多くあります。これはオーダーが非常に小さい範囲なので仕方ないことなのでしょうか?
ご教授よろしくお願いします。
開発環境:visual sutadio2012 .NET Framework4.5
public partial class Form1 : Form
{
//画像サイズ
static public new int Width;//横幅
static public new int Height;//縦幅
//画像データ保存用
static public Bitmap org_img = null;
static public Bitmap out_img = null;
byte[,] m_ImgOutGray = new byte[640, 480];
byte[,] m_ImgR1 = new byte[640, 480];
byte[,] m_ImgG1 = new byte[640, 480];
byte[,] m_ImgB1 = new byte[640, 480];
/*----画像を開く----*/
private void OpenIMG(object sender, EventArgs e)
{
//画像の読み込み
if (openFileDialogImage.ShowDialog() == DialogResult.OK)
{
org_img = new Bitmap(openFileDialogImage.FileName);
Pict.ImageLocation = openFileDialogImage.FileName;
Width = org_img.Width;
Height = org_img.Height;
}
out_img = new Bitmap(Width, Height);//出力用配列
//RGBデータの取得
RGB_DATA();
}
/*----画像を開く----*/
/*----元画像をRGB値に分解,輝度化----*/
public void RGB_DATA()
{
Stopwatch sw = new Stopwatch();
sw.Start();
uint i, j;
double dy;
BitmapData bmpdat = org_img.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
byte[] buf = new byte[Width * Height * 4];
Marshal.Copy(bmpdat.Scan0, buf, 0, buf.Length);
org_img.UnlockBits(bmpdat);
//スレッドの作成
Thread threadA = new Thread(new ParameterizedThreadStart(ThreadMethod));
Thread threadB = new Thread(new ParameterizedThreadStart(ThreadMethod1));
Thread threadC = new Thread(new ParameterizedThreadStart(ThreadMethod2));
threadA.Start(buf);
threadB.Start(buf);
threadC.Start(buf);
int x_width = Width / 2;
int y_height = Height / 2;
for (i = 0; i < y_height; i++)
{
for (j = 0; j < x_width; j++)
{
m_ImgR1[j, i] = buf[(i * Width + j) * 4 + 2];//R値の代入
m_ImgG1[j, i] = buf[(i * Width + j) * 4 + 1];//G値の代入
m_ImgB1[j, i] = buf[(i * Width + j) * 4];//B値の代入
dy = (byte)(0.3 * buf[(i * Width + j) * 4 + 2] + 0.59 * buf[(i * Width + j) * 4 + 1] + 0.11 * buf[(i * Width + j) * 4]);//輝度化
m_ImgOutGray[j, i] = (byte)dy;
}
}
sw.Stop();
Console.WriteLine("RGB_DATA(TIME) :: {0:f3}[ms]", (1000f * sw.ElapsedTicks / Stopwatch.Frequency));// 処理時間を表示
}
/*----元画像をRGB値に分解,輝度化----*/
//RGB取得用スレッド(同様の処理スレッドをあと2つ宣言)
public void ThreadMethod(Object obj)
{
int i, j;
double dy;
byte[] buf = (byte[])obj;
int x_width = Width / 2;
int y_height = Height / 2;
for (i = 0; i < y_height; i++)
{
for (j = x_width; j < Width; j++)
{
m_ImgR1[j, i] = buf[(i * Width + j) * 4 + 2];//R値の代入
m_ImgG1[j, i] = buf[(i * Width + j) * 4 + 1];//G値の代入
m_ImgB1[j, i] = buf[(i * Width + j) * 4];//B値の代入
dy = (byte)(0.3 * buf[(i * Width + j) * 4 + 2] + 0.59 * buf[(i * Width + j) * 4 + 1] + 0.11 * buf[(i * Width + j) * 4]);//輝度化
m_ImgOutGray[j, i] = (byte)dy;
}
}
}
}