2

I'm working with several new things at once, making it hard to see where I'm going wrong. I'm new to Android, Kotlin (and Java), Renderscript, kernel convolutions, and Laplacians.

But I've managed to get LoG working in Python with OpenCV and JavaScript by hand and I've managed other Renderscript intrinsics on Android. But I can't get LoG to work using the 5x5 convolve intrinsic. Here's some code:

val bm = BitmapFactory.decodeStream(istr, null, opts)
val bm2 = Bitmap.createBitmap(bm.width, bm.height, bm.config) // ?? Bitmap.Config.ARGB_8888

val rs = RenderScript.create(this@MainActivity)
val conv = ScriptIntrinsicConvolve5x5.create(rs, U8_4(rs)) // ??
val allIn = Allocation.createFromBitmap(rs, bm)
val allOut = Allocation.createFromBitmap(rs, bm2)

val coefs = floatArrayOf(
    0f, 0f,   1f, 0f, 0f, // the most standard 5x5 LoG kernel out there
    0f, 1f,   2f, 1f, 0f,
    1f, 2f, -16f, 2f, 1f,
    0f, 1f,   2f, 1f, 0f,
    0f, 0f,   1f, 0f, 0f
    // attempted "prenormalization"
    //0f,       0f,       0.03125f, 0f,       0f,
    //0f,       0.03125f, 0.0625f,  0.03125f, 0f,
    //0.03125f, 0.0625f,  0.5f,     0.0625f,  0.03125f,
    //0f,       0.03125f, 0.0625f,  0.03125f, 0f,
    //0f,       0f,       0.03125f, 0f,       0f
)) // ?? .map to "prenormalize" ...

conv.setCoefficients(coefs)
conv.setInput(allIn)
conv.forEach(allOut)
allOut.copyTo(bm2)

You can see I'm uncertain about a few things. But I think it might come down to the fact that LoG usually produces outputs in signed floating point. If you want to display it you have to normalize it afterwards to unsigned 8-bit ints.

In create I've tried using element types other than U8_4. Sometimes I get weird results, sometimes crashes. Maybe Renderscript only allows you to use the same element type for input and output? Maybe only for Intrinsics? I couldn't find that documented. Maybe I missed it. Maybe you can but I didn't set it up right.

I've tried using the usual signed integer convolution kernel for LoG. In case the problem is that the negative centre element in the kernel results in wrapping a negative to a high positive or in case the multiplications overflow or saturate to 255, I've tried "prenormalizing" my kernel so that outputs will always be in the range 0-255.

Depending on what I try, I mostly get almost white bitmaps with a faint impression of the original bitmap. Some variations results in flat grey, but multiplying to amplify the LoG just changes the grey level. Sometimes the output looks just like the input.

The strangest thing is that at first my output bitmap was a duplicate of the input, which internally resulted in the same storage. When I did this the result was actually perfect for about half my test images! The other half were corrupted.

So is this maybe not possible with the 5x5 intrinsic but I could do it manually in plain Renderscript? Or is there a way I can go from U8 input to floating point output? Or am I just using an element type incompatible with my bitmap? Or is the way to fix it by prenormalizing but my attempts are wrong?

hippietrail
  • 15,848
  • 18
  • 99
  • 158

0 Answers0