私のプロジェクトでは、まずファイルから画像を読み込み、すべてのピクセルを 2Dpixels[,]
配列に入れます。次に、各ピクセルを調べて、色に基づいて「ビン」に分割し、各ビンを並べ替えます。したがって、 aBin
をカプセル化するオブジェクトがあり、(比較的少数の) ビンを含む がありますList<Pixel>
。List<Bin>
私の問題は、非常に大きな画像 (1920x1200 = 230 万ピクセルなど) からこれらのビンを埋めようとすると、使用しているアルゴリズムが思ったよりも遅くなり、問題をいくつかの C# まで追跡したことです。私が予想していたよりも時間がかかっているように見える言語固有の機能。これらのボトルネックを解消するために C# をより適切に使用する方法についてアドバイスをお願いします。
画像を読み込んだ後、「fillBinsFromSource」という関数を呼び出します。この関数は、列挙可能なピクセルのリストを取得し、それらが属するビンを見つけてそこに配置します。
public void fillBinsFromSource(IEnumerable<Pixel> source)
{
Stopwatch s = new Stopwatch();
foreach (Pixel p in source)
{
s.Start();
// algorithm removed for brevity
// involves a binary search of all Bins and a List.Add call
s.Stop();
}
}
大きな画像の場合、私のアルゴリズムにはしばらく時間がかかることが予想されますが、ストップウォッチを関数呼び出しの外に置くと、で発生した時間の約 2 倍の時間がかかることがわかりましs
たforeach
。この関数の半分の時間 (1920x1200 画像の場合、1.6 秒のうち約 800 ミリ秒)。
列挙可能なリストを渡す必要がある理由は、ユーザーが画像全体ではなく、画像の小さな領域のみを追加する場合があるためです。時間のかかる呼び出しでは、最初に画像のリストから、次にリスト内の各画像から、次のように (簡略化して) 複数のイテレータを渡します。
class ImageList : IEnumerable<Pixel>
{
private List<Image> imageList;
public IEnumerator<Pixel> GetEnumerator()
{
foreach (Image i in imageList)
foreach (Pixel p in i)
yield return p;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class Image : IEnumerable<Pixel>
{
private Pixel[,] pixels; // all pixels in the image
private List<Pixel> selectedPixels;// all pixels in the user's selection
public IEnumerator<Pixel> GetEnumerator()
{
if (selectedPixels == null)
for (int i = 0; i < image.Width; i++)
for (int j = 0; j < image.Height; j++)
yield return pixels[i, j];
else
for (int i = 0; i < selectedPixels.Count; i++)
yield return selectedPixels[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
それから最後に私はこれを呼び出します
ImageList list; // pretend it contains only 1 image, and it's large
fillBinsFromSource(list);
質問 1) ピクセルの 2D 配列と選択した領域の両方を列挙する必要があるため、ユーザーが選択した内容に応じて、列挙は非常に遅くなります。どうすればこれをスピードアップできますか?
Pixel
次に、これらすべてのビンをオブジェクトで満たした後、それらを並べ替えます。次のように、を呼び出しList<Pixel>.Sort()
て依存しIComparable
ます。
ImageList list; // pretend it contains only 1 image, and it's large
fillBinsFromSource(list);
foreach(Bin b in allBins)
b.Sort(); // calls List<Pixel>.Sort()
class Pixel : IComparable
{
// store both HSV and RGB
float h, s, v;
byte r, g, b;
// we sort by HSV's value property
public int CompareTo(object obj)
{
// this is much faster than calling CompareTo on a float
Pixel rhs = obj as Pixel;
if (v < rhs.v)
return -1;
else if (v > rhs.v)
return 1;
return 0;
}
問題 2) allBins
7 つの要素があるとします。合計 230 万Pixel
の s を持つ 7 つの個別のリストを並べ替えるには、約 2 秒かかります。230 万個の random の 1 つのリストを並べ替えるにint
は、200 ミリ秒未満かかります。プリミティブ型を使用するとある程度のスピードアップがあることは理解できますが、実際に使用すると 10 倍以上遅くなりますIComparable
か? ここで必要なスピードアップはありますか?
長い質問で申し訳ありませんが、何かアドバイスがあればよろしくお願いします。