Skip to content

Commit

Permalink
Optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
demba003 committed May 17, 2020
1 parent 758ca30 commit 9a84cf9
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@ import android.renderscript.RenderScript
import pl.pk.binarizer.Processor
import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome

class BradleyBinarization(private val rs: RenderScript) : Processor {
class BradleyBinarization(rs: RenderScript) : Processor {

private val kernel = ScriptC_YuvToMonochrome(rs)
external fun binarize(input: ByteArray, size: Int)
private external fun binarize(input: ByteArray, output: ByteArray, size: Int)

init {
System.loadLibrary("native-lib")
}

override fun process(input: Allocation, output: Allocation) {
val monochromeBytesSize = (input.bytesSize / 1.5).toInt()
val bytes = ByteArray(monochromeBytesSize)
val originalBytes = ByteArray(monochromeBytesSize)
val processedBytes = ByteArray(monochromeBytesSize)

input.copy1DRangeTo(0, monochromeBytesSize, bytes)
input.copy1DRangeTo(0, monochromeBytesSize, originalBytes)

binarize(bytes, monochromeBytesSize)
binarize(originalBytes, processedBytes, monochromeBytesSize)

input.copy1DRangeFrom(0, monochromeBytesSize, bytes)
input.copy1DRangeFrom(0, monochromeBytesSize, processedBytes)

kernel._currentFrame = input
kernel.forEach_process(output)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@ import android.renderscript.RenderScript
import pl.pk.binarizer.Processor
import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome

class SimpleBinarization(private val rs: RenderScript) : Processor {
class SimpleBinarization(rs: RenderScript) : Processor {

private val kernel = ScriptC_YuvToMonochrome(rs)
external fun binarize(input: ByteArray, size: Int)
private external fun binarize(input: ByteArray, output: ByteArray, size: Int)

init {
System.loadLibrary("native-lib")
}

override fun process(input: Allocation, output: Allocation) {
val monochromeBytesSize = (input.bytesSize / 1.5).toInt()
val bytes = ByteArray(monochromeBytesSize)
val originalBytes = ByteArray(monochromeBytesSize)
val processedBytes = ByteArray(monochromeBytesSize)

input.copy1DRangeTo(0, monochromeBytesSize, bytes)
input.copy1DRangeTo(0, monochromeBytesSize, originalBytes)

binarize(bytes, monochromeBytesSize)
binarize(originalBytes, processedBytes, monochromeBytesSize)

input.copy1DRangeFrom(0, monochromeBytesSize, bytes)
input.copy1DRangeFrom(0, monochromeBytesSize, processedBytes)

kernel._currentFrame = input
kernel.forEach_process(output)
Expand Down
37 changes: 19 additions & 18 deletions binarizer/src/main/java/pl/pk/binarizer/jvm/BradleyBinarization.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,61 @@ import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome
import java.util.concurrent.Executors
import java.util.concurrent.Future

class BradleyBinarization(private val rs: RenderScript) : Processor {
class BradleyBinarization(rs: RenderScript) : Processor {

private val kernel = ScriptC_YuvToMonochrome(rs)
private val threadCount = Runtime.getRuntime().availableProcessors()
private val pool = Executors.newFixedThreadPool(threadCount)

override fun process(input: Allocation, output: Allocation) {
val monochromeBytesSize = (input.bytesSize / 1.5).toInt()
val bytes = ByteArray(monochromeBytesSize)
val originalBytes = ByteArray(monochromeBytesSize)
val processedBytes = ByteArray(monochromeBytesSize)

input.copy1DRangeTo(0, monochromeBytesSize, bytes)
input.copy1DRangeTo(0, monochromeBytesSize, originalBytes)

val tasks = mutableListOf<Future<Unit>>()

for (threadId in 0 until threadCount) {
tasks.add(
pool.submit<Unit> { processSegment(bytes, monochromeBytesSize, threadId) }
pool.submit<Unit> { processSegment(originalBytes, processedBytes, monochromeBytesSize, threadId) }
)
}

tasks.forEach { it.get() }

input.copy1DRangeFrom(0, monochromeBytesSize, bytes)
input.copy1DRangeFrom(0, monochromeBytesSize, processedBytes)

kernel._currentFrame = input
kernel.forEach_process(output)
}

private fun processSegment(bytes: ByteArray, size: Int, threadId: Int) {
private fun processSegment(originalBytes: ByteArray, processedBytes: ByteArray, size: Int, threadId: Int) {
for (i in threadId until size step threadCount) {
val th = threshold(bytes, i, 1280, 720, 7, 225)
if ((bytes[i].toInt() and 0xFF) > th) {
bytes[i] = -1
val th = threshold(originalBytes, i, 1280, 720)
if ((originalBytes[i].toInt() and 0xFF) > th) {
processedBytes[i] = -1
} else {
bytes[i] = 0
processedBytes[i] = 0
}
}
}

private fun threshold(data: ByteArray, index: Int, cols: Int, rows: Int, neighbourRadius: Int, neighbourPixels: Int): Int {
var sum = 0
private fun threshold(data: ByteArray, index: Int, cols: Int, rows: Int): Int {
var sum: Long = 0

val start = index - (cols * neighbourRadius) - neighbourRadius
val maxOffset = neighbourRadius * 2 * cols + neighbourRadius * 2
val start = index - cols * 7 - 7
val maxOffset = 7 * 2 * cols + 7 * 2

if((start + maxOffset) > (cols * rows) || start < 0) return 127
if (start + maxOffset > cols * rows || start < 0) return 127

for(y in 0 until neighbourRadius * 2) {
for(x in 0 until neighbourRadius * 2) {
for (y in 0 until 7 * 2) {
for (x in 0 until 7 * 2) {
sum += data[start + y * cols + x].toInt() and 0xFF
}
}

val average = sum / neighbourPixels
val average = (sum / 225).toInt()
return average * 78 / 100
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome
import java.util.concurrent.Executors
import java.util.concurrent.Future

class SimpleBinarization(private val rs: RenderScript) : Processor {
class SimpleBinarization(rs: RenderScript) : Processor {

private val kernel = ScriptC_YuvToMonochrome(rs)
private val threadCount = Runtime.getRuntime().availableProcessors()
Expand Down
48 changes: 26 additions & 22 deletions binarizer/src/main/jni/native-lib.cpp
Original file line number Diff line number Diff line change
@@ -1,56 +1,60 @@
#include <jni.h>

extern "C" JNIEXPORT void JNICALL
Java_pl_pk_binarizer_cpp_SimpleBinarization_binarize(JNIEnv *env, jobject thiz, jbyteArray input, jint size) {
Java_pl_pk_binarizer_cpp_SimpleBinarization_binarize(JNIEnv *env, jobject thiz, jbyteArray input, jbyteArray output, jint size) {
jboolean *isCopy = new jboolean;
jbyte *bytes = env->GetByteArrayElements(input, isCopy);
jbyte *originalBytes = env->GetByteArrayElements(input, isCopy);
jbyte *processedBytes = env->GetByteArrayElements(output, nullptr);

#pragma omp parallel for num_threads(8) schedule(static) shared(bytes, size) default(none)
#pragma omp parallel for num_threads(8) schedule(static) shared(originalBytes, processedBytes, size) default(none)
for (int i = 0; i < size; ++i) {
if (bytes[i] < 0) {
bytes[i] = -1;
if (originalBytes[i] < 0) {
processedBytes[i] = -1;
} else {
bytes[i] = 0;
processedBytes[i] = 0;
}
}

delete isCopy;
env->ReleaseByteArrayElements(input, bytes, 0);
env->ReleaseByteArrayElements(input, originalBytes, 0);
env->ReleaseByteArrayElements(output, processedBytes, 0);
}

int bradleyThreshold(jbyte *data, int index, int cols, int rows, int neighbourRadius, int neighbourPixels) {
int bradleyThreshold(jbyte *data, int index, int cols, int rows) {
long sum = 0;

int start = index - (cols * neighbourRadius) - neighbourRadius;
int maxOffset = neighbourRadius * 2 * cols + neighbourRadius * 2;
int start = index - (cols * 7) - 7;
int maxOffset = 7 * 2 * cols + 7 * 2;

if((start + maxOffset) > (cols * rows) || start < 0) return 127;
if ((start + maxOffset) > (cols * rows) || start < 0) return 127;

for(int y = 0; y < neighbourRadius * 2; y++) {
for(int x = 0; x < neighbourRadius * 2; x ++) {
for (int y = 0; y < 7 * 2; y++) {
for (int x = 0; x < 7 * 2; x++) {
sum += data[start + y * cols + x] & 0xFF;
}
}

int average = sum / neighbourPixels;
int average = sum / 225;
return average * 78 / 100;
}

extern "C" JNIEXPORT void JNICALL
Java_pl_pk_binarizer_cpp_BradleyBinarization_binarize(JNIEnv *env, jobject thiz, jbyteArray input, jint size) {
Java_pl_pk_binarizer_cpp_BradleyBinarization_binarize(JNIEnv *env, jobject thiz, jbyteArray input, jbyteArray output, jint size) {
jboolean *isCopy = new jboolean;
jbyte *bytes = env->GetByteArrayElements(input, isCopy);
jbyte *originalBytes = env->GetByteArrayElements(input, isCopy);
jbyte *processedBytes = env->GetByteArrayElements(output, nullptr);

#pragma omp parallel for num_threads(8) schedule(static) shared(bytes, size) default(none)
#pragma omp parallel for num_threads(8) schedule(static) shared(originalBytes, processedBytes, size) default(none)
for (int i = 0; i < size; ++i) {
int th = bradleyThreshold(bytes, i, 1280, 720, 7, 225);
if ((bytes[i] & 0xFF) > th) {
bytes[i] = -1;
int th = bradleyThreshold(originalBytes, i, 1280, 720);
if ((originalBytes[i] & 0xFF) > th) {
processedBytes[i] = -1;
} else {
bytes[i] = 0;
processedBytes[i] = 0;
}
}

delete isCopy;
env->ReleaseByteArrayElements(input, bytes, 0);
env->ReleaseByteArrayElements(input, originalBytes, 0);
env->ReleaseByteArrayElements(output, processedBytes, 0);
}
41 changes: 30 additions & 11 deletions binarizer/src/main/rs/BradleyBinarizationFS.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,42 @@

rs_allocation currentFrame;

uint32_t width = 1280;
uint32_t height = 720;
uint32_t cols = 1280;
uint32_t rows = 720;

uchar4 __attribute__((kernel)) process(uint32_t x, uint32_t y) {
//uint sum = 0;
//uint count = 0;
//for (int yi = y-7; yi <= y+7; ++yi) {
// for (int xi = x-7; xi <= x+7; ++xi) {
// if (xi >= 0 && xi < width && yi >= 0 && yi < height) {
// sum += rsGetElementAtYuv_uchar_Y(currentFrame, xi, yi);
// ++count;
// }
// }
// }

//uchar current = rsGetElementAtYuv_uchar_Y(currentFrame, x, y);
//uchar average = (sum / count) * 78 / 100;

//return rsYuvToRGBA_uchar4(current > average ? 255 : 0, 128, 128);

uint sum = 0;
uint count = 0;
for (int yi = y-7; yi <= y+7; ++yi) {
for (int xi = x-7; xi <= x+7; ++xi) {
if (xi >= 0 && xi < width && yi >= 0 && yi < height) {
sum += rsGetElementAtYuv_uchar_Y(currentFrame, xi, yi);
++count;
}

if (x < 7 || x > cols-7 || y < 7 || y > rows-7) {
uchar current = rsGetElementAtYuv_uchar_Y(currentFrame, x, y);
return rsYuvToRGBA_uchar4(current > 127 ? 255 : 0, 128, 128);
}

for (int yi = -7; yi < 7; yi++) {
for (int xi = -7; xi < 7; xi++) {
sum += rsGetElementAtYuv_uchar_Y(currentFrame, x + xi, y + yi);
}
}

uchar current = rsGetElementAtYuv_uchar_Y(currentFrame, x, y);
uchar average = (sum / count) * 78 / 100;
uint average = sum / 225;
uint th = average * 78 / 100;

uchar current = rsGetElementAtYuv_uchar_Y(currentFrame, x, y);
return rsYuvToRGBA_uchar4(current > average ? 255 : 0, 128, 128);
}

0 comments on commit 9a84cf9

Please sign in to comment.