Android multithreading

I am trying to use the multi-threaded code of OpenCV4Android. I split the 432x432 image into 9 144x144 segments and pass each one to a different stream:

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) {}; 

Here is the stream class:

 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); } } 

I have two problems:

  • Although threads correctly modify individual blocks, modifications are not displayed in the final image. This would make sense if the Mat block passed by value to the stream, but Java instead passed a reference to the stream.

  • The execution time is longer than the inaccurate code - in my emulator it increases from ~ 1200 to ~ 1500 ms. Is this a problem with the emulator, or is for some reason a multithreaded idea really bad?

+4
source share
3 answers

I have no experience with OpenCV, so I will only consider the second problem.

A thread requires a processor to run (or a kernel that acts as a virtual processor). Thus, you will never have more threads running in silmultaneous, and then the real number of cores available in the device.

Suppose you have a device with 2 cores, and you divided the work into 9 threads. The end result is that only 2 out of 9 threads will work in an instant, while the remaining 7 will be in the queue, expecting the processor to have their turn.

Since the cost of creating and switching threads, the overall performance result will be worse than with two threads.

If you share work between threads differently, do not do more threads, and then the number of cores in the device.

I believe most devices on the market are limited to 1 or 2 cores ...

Hello

+3
source

The first problem was caused by converting the block Mat to another type in this section:

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

I'm not sure why this is a problem, but I fixed it by storing the intermediate floating point matrix in closed and returning the final answer in block :

 Core.divide(block, closed, closed, 1, CvType.CV_32F); Core.normalize(closed, block, 0, 255, Core.NORM_MINMAX, CvType.CV_8U); 
+1
source

Louis addressed the second issue. And I think the first problem is that you are processing the new Mat for the stream, the modification on the new Mat will not affect the old.

I find the source code of rowRange, there is native code, but it explicitly creates a new object.

  public Mat rowRange(int startrow, int endrow) { Mat retVal = new Mat(n_rowRange(nativeObj, startrow, endrow)); return retVal; } 
0
source

All Articles