protected void integrateLineDim0( final Converter<R, T> converter, final RandomAccess<R> cursorIn, final RandomAccess<T> cursorOut, final T sum, final T tmpVar, final long size) { // compute the first pixel converter.convert(cursorIn.get(), sum); cursorOut.get().set(sum); for (long i = 2; i < size; ++i) { cursorIn.fwd(0); cursorOut.fwd(0); converter.convert(cursorIn.get(), tmpVar); sum.add(tmpVar); cursorOut.get().set(sum); } }
@Override public boolean process() { final int numDimensions = img.numDimensions(); final long integralSize[] = new long[numDimensions]; // the size of the first dimension is changed for (int d = 0; d < numDimensions; ++d) integralSize[d] = img.dimension(d) + 1; final Img<T> integral = imgFactory.create(integralSize, type); // not enough RAM or disc space if (integral == null) return false; this.integral = integral; if (numDimensions > 1) { final long[] fakeSize = new long[numDimensions - 1]; // the size of dimension 0 final long size = integralSize[0]; for (int d = 1; d < numDimensions; ++d) fakeSize[d - 1] = integralSize[d]; final long imageSize = getNumPixels(fakeSize); final AtomicInteger ai = new AtomicInteger(0); final Thread[] threads = SimpleMultiThreading.newThreads(); final Vector<Chunk> threadChunks = SimpleMultiThreading.divideIntoChunks(imageSize, threads.length); for (int ithread = 0; ithread < threads.length; ++ithread) threads[ithread] = new Thread( new Runnable() { @Override public void run() { // Thread ID final int myNumber = ai.getAndIncrement(); // get chunk of pixels to process final Chunk myChunk = threadChunks.get(myNumber); final long loopSize = myChunk.getLoopSize(); final LocalizingZeroMinIntervalIterator cursorDim = new LocalizingZeroMinIntervalIterator(fakeSize); // location for the input location final long[] tmpIn = new long[numDimensions]; // location for the integral location final long[] tmpOut = new long[numDimensions]; final long[] tmp = new long[numDimensions - 1]; final RandomAccess<R> cursorIn = img.randomAccess(); final RandomAccess<T> cursorOut = integral.randomAccess(); final T tmpVar = integral.firstElement().createVariable(); final T sum = integral.firstElement().createVariable(); cursorDim.jumpFwd(myChunk.getStartPosition()); // iterate over all dimensions except the one we are computing the integral in, // which is dim=0 here main: for (long j = 0; j < loopSize; ++j) { cursorDim.fwd(); // get all dimensions except the one we are currently doing the integral on cursorDim.localize(tmp); tmpIn[0] = 0; tmpOut[0] = 1; for (int d = 1; d < numDimensions; ++d) { tmpIn[d] = tmp[d - 1] - 1; tmpOut[d] = tmp[d - 1]; // all entries of position 0 are 0 if (tmpOut[d] == 0) continue main; } // set the cursor to the beginning of the correct line cursorIn.setPosition(tmpIn); // set the cursor in the integral image to the right position cursorOut.setPosition(tmpOut); // integrate over the line integrateLineDim0(converter, cursorIn, cursorOut, sum, tmpVar, size); } } }); SimpleMultiThreading.startAndJoin(threads); } else { final T tmpVar = integral.firstElement().createVariable(); final T sum = integral.firstElement().createVariable(); // the size of dimension 0 final long size = integralSize[0]; final RandomAccess<R> cursorIn = img.randomAccess(); final RandomAccess<T> cursorOut = integral.randomAccess(); cursorIn.setPosition(0, 0); cursorOut.setPosition(1, 0); // compute the first pixel converter.convert(cursorIn.get(), sum); cursorOut.get().set(sum); for (long i = 2; i < size; ++i) { cursorIn.fwd(0); cursorOut.fwd(0); converter.convert(cursorIn.get(), tmpVar); sum.add(tmpVar); cursorOut.get().set(sum); } return true; } for (int d = 1; d < numDimensions; ++d) { final int dim = d; final long[] fakeSize = new long[numDimensions - 1]; // the size of dimension d final long size = integralSize[d]; // get all dimensions except the one we are currently doing the integral on int countDim = 0; for (int e = 0; e < numDimensions; ++e) if (e != d) fakeSize[countDim++] = integralSize[e]; final long imageSize = getNumPixels(fakeSize); final AtomicInteger ai = new AtomicInteger(0); final Thread[] threads = SimpleMultiThreading.newThreads(); final Vector<Chunk> threadChunks = SimpleMultiThreading.divideIntoChunks(imageSize, threads.length); for (int ithread = 0; ithread < threads.length; ++ithread) threads[ithread] = new Thread( new Runnable() { @Override public void run() { // Thread ID final int myNumber = ai.getAndIncrement(); // get chunk of pixels to process final Chunk myChunk = threadChunks.get(myNumber); final long loopSize = myChunk.getLoopSize(); final LocalizingZeroMinIntervalIterator cursorDim = new LocalizingZeroMinIntervalIterator(fakeSize); // local instances final long[] tmp2 = new long[numDimensions - 1]; final long[] tmp = new long[numDimensions]; final RandomAccess<T> cursor = integral.randomAccess(); final T sum = integral.firstElement().createVariable(); cursorDim.jumpFwd(myChunk.getStartPosition()); for (long j = 0; j < loopSize; ++j) { cursorDim.fwd(); // get all dimensions except the one we are currently doing the integral on cursorDim.localize(tmp2); tmp[dim] = 1; int countDim = 0; for (int e = 0; e < numDimensions; ++e) if (e != dim) tmp[e] = tmp2[countDim++]; // update the cursor in the input image to the current dimension position cursor.setPosition(tmp); // sum up line integrateLine(dim, cursor, sum, size); } } }); SimpleMultiThreading.startAndJoin(threads); } return true; }