Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
demba003 committed May 23, 2020
1 parent 9cc592c commit fcd2d0a
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 63 deletions.
10 changes: 6 additions & 4 deletions app/src/main/java/pl/pk/binarycamera2/ProcessorProxy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pl.pk.binarycamera2
import android.renderscript.Allocation
import android.renderscript.RenderScript
import android.util.Log
import android.util.Size
import android.view.Surface
import io.reactivex.rxjava3.subjects.PublishSubject
import org.koin.core.KoinComponent
Expand All @@ -17,6 +18,7 @@ import kotlin.concurrent.thread
class ProcessorProxy(rs: RenderScript) : Processor, Benchmarkable, KoinComponent {
private val inputAllocation: Allocation by inject(named("Input"))
private val outputAllocation: Allocation by inject(named("Output"))
private val previewSize: Size by inject()
private var currentMode = ProcessingMode.ORIGINAL

val processingTime: PublishSubject<Long> = PublishSubject.create()
Expand All @@ -33,10 +35,10 @@ class ProcessorProxy(rs: RenderScript) : Processor, Benchmarkable, KoinComponent
ProcessingMode.SIMPLE_CPP to pl.pk.binarizer.cpp.SimpleBinarization(rs),
ProcessingMode.SIMPLE_RS to pl.pk.binarizer.rs.SimpleBinarization(rs),

ProcessingMode.BRADLEY_KT to pl.pk.binarizer.jvm.BradleyBinarization(rs),
ProcessingMode.BRADLEY_INT_KT to pl.pk.binarizer.jvm.BradleyIntegralBinarization(rs),
ProcessingMode.BRADLEY_CPP to pl.pk.binarizer.cpp.BradleyBinarization(rs),
ProcessingMode.BRADLEY_INT_CPP to pl.pk.binarizer.cpp.BradleyIntegralBinarization(rs),
ProcessingMode.BRADLEY_KT to pl.pk.binarizer.jvm.BradleyBinarization(rs, previewSize),
ProcessingMode.BRADLEY_INT_KT to pl.pk.binarizer.jvm.BradleyIntegralBinarization(rs, previewSize),
ProcessingMode.BRADLEY_CPP to pl.pk.binarizer.cpp.BradleyBinarization(rs, previewSize),
ProcessingMode.BRADLEY_INT_CPP to pl.pk.binarizer.cpp.BradleyIntegralBinarization(rs, previewSize),
ProcessingMode.BRADLEY_RS to pl.pk.binarizer.rs.BradleyBinarizationFS(rs)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package pl.pk.binarizer.cpp

import android.renderscript.Allocation
import android.renderscript.RenderScript
import android.util.Size
import pl.pk.binarizer.Processor
import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome

class BradleyBinarization(rs: RenderScript) : Processor {
class BradleyBinarization(rs: RenderScript, private val dimensions: Size) : Processor {

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

init {
System.loadLibrary("native-lib")
Expand All @@ -21,7 +22,7 @@ class BradleyBinarization(rs: RenderScript) : Processor {

input.copy1DRangeTo(0, monochromeBytesSize, originalBytes)

binarize(originalBytes, processedBytes, monochromeBytesSize)
binarize(originalBytes, processedBytes, monochromeBytesSize, dimensions.width, dimensions.height)

input.copy1DRangeFrom(0, monochromeBytesSize, processedBytes)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package pl.pk.binarizer.cpp

import android.renderscript.Allocation
import android.renderscript.RenderScript
import android.util.Size
import pl.pk.binarizer.Processor
import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome

class BradleyIntegralBinarization(rs: RenderScript) : Processor {
class BradleyIntegralBinarization(rs: RenderScript, private val dimensions: Size) : Processor {

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

init {
System.loadLibrary("native-lib")
Expand All @@ -21,7 +22,7 @@ class BradleyIntegralBinarization(rs: RenderScript) : Processor {

input.copy1DRangeTo(0, monochromeBytesSize, originalBytes)

binarize(originalBytes, processedBytes, monochromeBytesSize)
binarize(originalBytes, processedBytes, monochromeBytesSize, dimensions.width, dimensions.height)

input.copy1DRangeFrom(0, monochromeBytesSize, processedBytes)

Expand Down
26 changes: 16 additions & 10 deletions binarizer/src/main/java/pl/pk/binarizer/jvm/BradleyBinarization.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package pl.pk.binarizer.jvm

import android.renderscript.Allocation
import android.renderscript.RenderScript
import android.util.Size
import pl.pk.binarizer.Processor
import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome
import java.util.concurrent.Executors
import java.util.concurrent.Future

class BradleyBinarization(rs: RenderScript) : Processor {
class BradleyBinarization(rs: RenderScript, private val dimensions: Size) : Processor {

private val kernel = ScriptC_YuvToMonochrome(rs)
private val threadCount = Runtime.getRuntime().availableProcessors()
Expand Down Expand Up @@ -38,7 +39,7 @@ class BradleyBinarization(rs: RenderScript) : Processor {

private fun processSegment(originalBytes: ByteArray, processedBytes: ByteArray, size: Int, threadId: Int) {
for (i in threadId until size step threadCount) {
val th = threshold(originalBytes, i, 1280, 720)
val th = threshold(originalBytes, i)
if ((originalBytes[i].toInt() and 0xFF) > th) {
processedBytes[i] = -1
} else {
Expand All @@ -47,22 +48,27 @@ class BradleyBinarization(rs: RenderScript) : Processor {
}
}

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

val start = index - cols * 7 - 7
val maxOffset = 7 * 2 * cols + 7 * 2
val start = index - dimensions.width * radius - radius
val maxOffset = radius * 2 * dimensions.width + radius * 2

if (start + maxOffset > cols * rows || start < 0) return 127
if (start + maxOffset > dimensions.width * dimensions.height || start < 0) return 127

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

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

companion object {
private const val radius = 7
private const val area = ((radius * 2 + 1) * (radius * 2 + 1))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package pl.pk.binarizer.jvm

import android.renderscript.Allocation
import android.renderscript.RenderScript
import android.util.Size
import pl.pk.binarizer.Processor
import pl.pk.binarizer.rs.ScriptC_YuvToMonochrome
import java.util.concurrent.Executors
import java.util.concurrent.Future

class BradleyIntegralBinarization(rs: RenderScript) : Processor {
class BradleyIntegralBinarization(rs: RenderScript, private val dimensions: Size) : Processor {

private val kernel = ScriptC_YuvToMonochrome(rs)
private val threadCount = Runtime.getRuntime().availableProcessors()
Expand Down Expand Up @@ -48,27 +49,25 @@ class BradleyIntegralBinarization(rs: RenderScript) : Processor {
}

private fun calculateIntegral(originalBytes: ByteArray, integral: IntArray) {
val height = 720
val width = 1280
for (row in 0 until height) {
for (row in 0 until dimensions.height) {
var sum = 0
for (column in 0 until width) {
sum += originalBytes[column + width * row].toInt() and 0xFF
for (column in 0 until dimensions.width) {
sum += originalBytes[column + dimensions.width * row].toInt() and 0xFF
if (row == 0) {
integral[column + width * row] = sum
integral[column + dimensions.width * row] = sum
} else {
integral[column + width * row] = integral[column + width * (row - 1)] + sum
integral[column + dimensions.width * row] = integral[column + dimensions.width * (row - 1)] + sum
}
}
}
}

private fun getIntegralAverage(index: Int, integral: IntArray): Int {
val one = integral[index + 7 * 1280 + 7]
val two = integral[index - 7 * 1280 - 7]
val three = integral[index + 7 * 1280 - 7]
val four = integral[index - 7 * 1280 + 7]
return (one + two - three - four) / 225
val one = integral[index + radius * dimensions.width + radius]
val two = integral[index - radius * dimensions.width - radius]
val three = integral[index + radius * dimensions.width - radius]
val four = integral[index - radius * dimensions.width + radius]
return (one + two - three - four) / area
}

private fun processSegment(
Expand All @@ -79,7 +78,7 @@ class BradleyIntegralBinarization(rs: RenderScript) : Processor {
threadId: Int
) {
for (i in threadId until size step threadCount) {
val th = threshold(integral, i, 1280, 720)
val th = threshold(integral, i)
if ((originalBytes[i].toInt() and 0xFF) > th) {
processedBytes[i] = -1
} else {
Expand All @@ -88,11 +87,15 @@ class BradleyIntegralBinarization(rs: RenderScript) : Processor {
}
}

private fun threshold(integral: IntArray, index: Int, cols: Int, rows: Int): Int {
if (index + 7 * 1280 + 7 >= cols * rows || index - 7 * 1280 - 7 < 0) return 127
private fun threshold(integral: IntArray, index: Int): Int {
if (index + radius * dimensions.width + radius >= dimensions.width * dimensions.height || index - radius * dimensions.width - radius < 0) return 127

val average = getIntegralAverage(index, integral)
return average * 78 / 100
}

companion object {
private const val radius = 7
private const val area = ((radius * 2 + 1) * (radius * 2 + 1))
}
}
76 changes: 49 additions & 27 deletions binarizer/src/main/jni/native-lib.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
#include <jni.h>

//////////// CONSTANTS ////////////

constexpr int radius = 7;
constexpr int area = ((radius * 2 + 1) * (radius * 2 + 1));

//////////// SIMPLE BINARIZATION ////////////

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

#pragma omp parallel for num_threads(8) schedule(static) shared(originalBytes, processedBytes, size) default(none)
#pragma omp parallel for schedule(static) shared(originalBytes, processedBytes, size) default(none)
for (int i = 0; i < size; ++i) {
if (originalBytes[i] < 0) {
processedBytes[i] = -1;
Expand All @@ -27,30 +37,37 @@ Java_pl_pk_binarizer_cpp_SimpleBinarization_binarize(JNIEnv *env, jobject thiz,
int bradleyThreshold(jbyte *data, int index, int cols, int rows) {
long sum = 0;

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

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

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

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

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

#pragma omp parallel for num_threads(8) schedule(static) shared(originalBytes, processedBytes, size) default(none)
#pragma omp parallel for schedule(static) shared(originalBytes, processedBytes, size, width, height) default(none)
for (int i = 0; i < size; ++i) {
int th = bradleyThreshold(originalBytes, i, 1280, 720);
int th = bradleyThreshold(originalBytes, i, width, height);
if ((originalBytes[i] & 0xFF) > th) {
processedBytes[i] = -1;
} else {
Expand All @@ -65,9 +82,7 @@ Java_pl_pk_binarizer_cpp_BradleyBinarization_binarize(JNIEnv *env, jobject thiz,

//////////// BRADLEY INTEGRAL BINARIZATION ////////////

void calculateIntegral(jbyte* originalBytes, int* integral) {
int height = 720;
int width = 1280;
void calculateIntegral(jbyte *originalBytes, int *integral, int width, int height) {
for (int row = 0; row < height; row++) {
int sum = 0;
for (int column = 0; column < width; column++) {
Expand All @@ -81,33 +96,40 @@ void calculateIntegral(jbyte* originalBytes, int* integral) {
}
}

int getIntegralAverage(int index, int* integral) {
int one = integral[index + 7 * 1280 + 7];
int two = integral[index - 7 * 1280 - 7];
int three = integral[index + 7 * 1280 - 7];
int four = integral[index - 7 * 1280 + 7];
return (one + two - three - four) / 225;
int getIntegralAverage(int index, int *integral, int width) {
int one = integral[index + radius * width + radius];
int two = integral[index - radius * width - radius];
int three = integral[index + radius * width - radius];
int four = integral[index - radius * width + radius];
return (one + two - three - four) / area;
}

int bradleyIntegralThreshold(int* integral, int index, int cols, int rows) {
if (index + 7 * 1280 + 7 >= cols * rows || index - 7 * 1280 - 7 < 0) return 127;
int bradleyIntegralThreshold(int *integral, int index, int width, int height) {
if (index + radius * width + radius >= width * height || index - radius * width - radius < 0) return 127;

int average = getIntegralAverage(index, integral);
int average = getIntegralAverage(index, integral, width);
return average * 78 / 100;
}

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

int* integral = new int[size];
calculateIntegral(originalBytes, integral);
int *integral = new int[size];
calculateIntegral(originalBytes, integral, width, height);

#pragma omp parallel for num_threads(8) schedule(static) shared(originalBytes, processedBytes, integral, size) default(none)
#pragma omp parallel for schedule(static) shared(originalBytes, processedBytes, integral, size, width, height) default(none)
for (int i = 0; i < size; ++i) {
int th = bradleyIntegralThreshold(integral, i, 1280, 720);
int th = bradleyIntegralThreshold(integral, i, width, height);
if ((originalBytes[i] & 0xFF) > th) {
processedBytes[i] = -1;
} else {
Expand Down

0 comments on commit fcd2d0a

Please sign in to comment.