4

OpenCV4Androidコードをマルチスレッド化しようとしています。432x432の画像を9つの144x144セグメントに分割し、それぞれを異なるスレッドに渡します。

Thread[] threads = new Thread[9];
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        threads[3*i+j] = new Thread(new MyThread(image.rowRange(144*i, 144*(i+1)).colRange(144*j, 144*(j+1))));
        threads[3*i+j].start();
    }
}

for (Thread thread : threads) try {thread.join();} catch (InterruptedException e) {};

スレッドクラスは次のとおりです。

public class MyThread implements Runnable {
    final Mat block;

    public MyThread(Mat block) {
        this.block = block;
    }

    public void run() {
        /* do image processing on block */
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));
        Mat closed = new Mat();
        Imgproc.morphologyEx(block, closed, Imgproc.MORPH_CLOSE, kernel);
        Core.divide(block, closed, block, 1, CvType.CV_32F);
        Core.normalize(block, block, 0, 255, Core.NORM_MINMAX);
        block.convertTo(block, CvType.CV_8UC1);     
        Imgproc.threshold(block, block, -1, 255, Imgproc.THRESH_BINARY_INV+Imgproc.THRESH_OTSU);
    }
}

私には2つの問題があります:

  1. スレッドは個々のブロックを正しく変更していますが、変更は最終的な画像に表示されていません。これは、値によってスレッドに渡された場合は意味Mat blockがありますが、Javaは代わりにスレッドへの参照を渡す必要があります。

  2. ランタイムはスレッド化されていないコードよりも長くなります。私のエミュレーターでは、1200ミリ秒から1500ミリ秒になります。これはエミュレーターの問題ですか、それともマルチスレッド化は何らかの理由でここで本当に悪い考えですか?

4

3 に答える 3

3

私はOpenCVの経験がないので、2番目の問題のみを取り上げます。

スレッドを実行するにはCPU(または仮想CPUとして機能するコア)が必要です。そのため、デバイスで使用可能なコアの実際の数よりも多くのスレッドが同時に実行されることはありません。

2コアのデバイスがあり、作業を9スレッドに分割するとします。最終的な結果として、9つのスレッドのうち2つだけが同時に実行され、残りの7つはCPUを搭載する順番を待つキューに入れられます。

スレッドの作成と切り替えにはコストがかかるため、全体的なパフォーマンスの結果は、スレッドが2つしかない場合よりも悪くなります。

パフォーマンス上の理由でスレッド間で作業を分割する場合は、デバイスのコア数よりも多くのスレッドを作成しないでください。

市場に出回っているほとんどのデバイスは1コアまたは2コアに制限されていると思います...

よろしく

于 2012-12-10T01:21:31.337 に答える
1

block最初の問題は、このセクションでマットを別のタイプに 変換することによって引き起こされていました。

Core.divide(block, closed, block, 1, CvType.CV_32F);
Core.normalize(block, block, 0, 255, Core.NORM_MINMAX);
block.convertTo(block, CvType.CV_8UC1);     

なぜこれが問題になるのかわかりませんが、中間浮動小数点行列をに格納しclosed、最終的な答えを次のように戻すことで修正しましたblock

Core.divide(block, closed, closed, 1, CvType.CV_32F);
Core.normalize(closed, block, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);
于 2012-12-11T02:17:51.173 に答える
0

ルイスは2番目の問題に取り組んでいます。そして、最初の問題は、新しいマットをスレッドに処理するため、新しいマットを変更しても古いマットには影響しないためだと思います。

rowRangeのソースコードを見つけました。ネイティブコードがいくつかありますが、明らかに新しいオブジェクトが作成されます。

 public Mat rowRange(int startrow, int endrow)
 {

     Mat retVal = new Mat(n_rowRange(nativeObj, startrow, endrow));

     return retVal;
 }
于 2012-12-10T03:07:51.033 に答える