RGBデータ取得の処理速度

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
russell

RGBデータ取得の処理速度

#1

投稿記事 by russell » 12年前

現在C#にて画像処理を行おうとしています。
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;
                }
            }
        }
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: RGBデータ取得の処理速度

#2

投稿記事 by softya(ソフト屋) » 12年前

C#のスレッドを使ったことがないのですが確認してみたところJoin();でスレッド終了の同期をしていない様に見えます。
そうするとsw.Stop();が全スレッドの終了時間を反映していない事になりますね。

あと同じバッファを処理してますか? テストとしては余り意味が無い様と思うので別の内容を処理させましょう。
それにリリースビルドしないと実行速度のテストとして不的確です。リリースビルドされてますか?

※ ちなみにCPUを全力で使うスレッドのためCPUのコア数でスレッドの数の上限が決まると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る