質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

2926閲覧

C#のガベージコレクションについて

seiyayamamot

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2018/08/16 03:57

編集2018/08/17 16:04

前提・実現したいこと

イクイレクタングラー形式の全方位映像をキューブマップ形式の全方位映像に変換し再生するプログラムを作っています。
動画の扱い等はopencvsharpのvideocaptureクラスを使っていて、毎フレーム毎に画像を変換しています。
変換と再生自体は一応上手く言っているので問題ないのですが、プロセスメモリを見るとGCが凄い勢いで発生しています。
GCの発生がどの程度、処理速度に影響を与えるのかよく知らないのですが、低下の一因にはなっていると思うのでこのGCを減らしたいと考えています。

発生している問題・エラーメッセージ

GCの発生頻度が高すぎる(気がする)。

(追記)
GCというよりは処理速度をどうすれば向上させられるかということの方が主題だったのかもしれません。

該当のソースコード

C#

1//capは変換したい映像が入ったVideocaptuer型 2//imgはMat型 3//pictはpictureBox 4//int[] 型のposは外側で計算させている変換のために必要な値です。 5//Play()をtimerで繰り返して映像を表示させています 6public void Play() 7 { 8 if(cap.PosFrames < cap.FrameCount - 1){ 9 cap.Read(img); 10 Cv2.Resize(img, img, new OpenCvSharp.Size(pict.Width, pict.Height * 2)); 11 var old = pict.Image; 12 pict.Image = cubechange(img.ToBitmap(), pos); 13 if (old != null) 14 old.Dispose(); 15 } 16 } 17 18 19 Bitmap cubechange(Bitmap img, int[] pos) 20 { 21 // Bitmapをロックし、BitmapDataを取得する 22 System.Drawing.Imaging.BitmapData srcBitmapData = 23 img.LockBits( 24 new System.Drawing.Rectangle(0, 0, img.Width, img.Height), 25 System.Drawing.Imaging.ImageLockMode.WriteOnly, img.PixelFormat); 26 27 // 変換対象のカラー画像の情報をバイト列へ書き出す 28 byte[] srcPixels = new byte[srcBitmapData.Stride * img.Height]; 29 byte[] copyPixels = new byte[srcBitmapData.Stride * img.Height]; 30 Marshal.Copy(srcBitmapData.Scan0, srcPixels, 0, srcPixels.Length); 31 Marshal.Copy(srcBitmapData.Scan0, copyPixels, 0, copyPixels.Length); 32 33 for (int i = 0; i < srcPixels.Length; i += 3) 34 { 35 if (i < srcPixels.Length / 2) 36 { 37 srcPixels[i] = copyPixels[pos[i / 3]]; 38 srcPixels[i + 1] = copyPixels[pos[i / 3] + 1]; 39 srcPixels[i + 2] = copyPixels[pos[i / 3] + 2]; 40 } 41 else 42 { 43 srcPixels[i] = 255; 44 srcPixels[i + 1] = 255; 45 srcPixels[i + 2] = 255; 46 } 47 48 } 49 Marshal.Copy(srcPixels, 0, srcBitmapData.Scan0, srcPixels.Length); 50 img.UnlockBits(srcBitmapData); 51 52 return img; 53 }

試したこと

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

あまり問題がわかっていないけど、

画像処理だと、
https://github.com/SixLabors/ImageSharp
これがいいらしいよ。
span構造体を多用しているので、生メモリーの操作とか、unsafeがいらなくなる。

span構造体の解説記事
https://ufcpp.net/study/csharp/resource/span/

投稿2018/08/16 09:23

編集2018/08/16 09:38
kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

seiyayamamot

2018/08/17 10:59

画像処理については詳しく調べていなかったので情報ありがたいです。 元々はsetPixcel,getPixcelを使っていて動画で使うには遅すぎる!となりその方向から調べていき 最初の方に見つけたのが今の方法でした。 試してみます!
kiichi54321

2018/08/17 13:34

昔の定番だからね。 あと他の方法は、opencv側のイメージオブジェクトで、完結させることですかね。 最終出力でBitmap を使うのはしょうがないけど、それまでは、opencvの方が扱いやすいし速いと思う。
guest

0

1,img.LockBitsの引数がImageLockMode.WriteOnlyになっていますが。
ImageLockMode.ReadWriteに変更してsrcPixelsの値を直接編集すれば、copyPixelsのメモリ割り当てが不要になります。

2,画像のResize処理と一緒になんらかの処理(※単純な処理)をするなら、
ImageAttributes#SetColorMatrixGraphics#DrawImageが使えるかと。

3, あとはunsafeコードで生Bitmapデータに直接アクセスでしょうか。(最後のMarshal.Copyが消せます)

投稿2018/08/16 04:32

編集2018/08/16 09:06
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

seiyayamamot

2018/08/17 12:59 編集

1についてやってみたところGCの回数が半分ほどになりました! 2については調べてみたのですが、ちょっとよく分からずで・・すみません。 3についてはunsafeコードについてよく知らなかったので、調べながらやってみます。
guest

0

pict.imageのオブジェクトが毎フレーム捨てられてるように見えるので
それが原因かも?

投稿2018/08/16 04:08

編集2018/08/16 04:14
tekka

総合スコア514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

seiyayamamot

2018/08/17 10:52

この辺りは自分で試行錯誤していたところの残滓です・・・ bitmapを毎フレーム毎に作成しているのでdispoceは必要かなと思ったのですが、 あってもなくてもあまり変わらない(GCの量と処理速度が)のでこの辺りは関係ないような気がします。
guest

0

まずはどの程度GCが影響しているか確認してみてはどうでしょうか。
ガベージ コレクションとパフォーマンス

投稿2018/08/16 09:34

YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

seiyayamamot

2018/08/17 10:42

確かにそれもそうですね・・・ 問題をGCが多発しているといいましたが最終的な目標は処理速度向上なので この問題が解決しても処理速度向上するか分かりませんもんね・・ リンク先を参考に調べてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問