Hubert Osewski
04/19/2023, 3:56 PMMichael Paus
04/19/2023, 4:23 PMHubert Osewski
04/19/2023, 4:24 PMHubert Osewski
04/19/2023, 4:24 PMStefan Oltmann
06/25/2024, 9:17 AMAlexander Zhirkevich
06/25/2024, 9:24 AMStefan Oltmann
06/25/2024, 9:29 AMfun Image.calcVarianceOfLaplacian(): Double {
val surface = Surface.makeRasterN32Premul(width, height)
surface.canvas.drawImageRect(
image = this,
dst = Rect(0f, 0f, width.toFloat(), height.toFloat()),
paint = laplaceEdgeDetectorFilterSkiaPaint
)
val newImage = surface.makeImageSnapshot()
val bitmap = Bitmap.makeFromImage(newImage)
return bitmap.calcRedVariance()
}
/**
* Laplace edge detection filter
*
* Same as OpenCV:
* Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY)
* Imgproc.Laplacian(grayImage, destination, CvType.CV_64F, 1, 1.0, 0.0, Core.BORDER_ISOLATED)
*/
@Suppress("MagicNumber")
val laplaceEdgeDetectorFilterSkiaPaint: Paint = Paint().apply {
colorFilter = grayscaleSkiaColorFilter
imageFilter = ImageFilter.makeMatrixConvolution(
kernelW = 3,
kernelH = 3,
kernel = floatArrayOf(
0F, 1F, 0F,
1F, -4F, 1F,
0F, 1F, 0F
),
gain = 1F,
bias = 0F,
offsetX = 1,
offsetY = 1,
tileMode = FilterTileMode.CLAMP,
convolveAlpha = false,
input = null,
crop = null
)
}
The problem is: While there is an colorFilter
and Android, there is no imageFilter
I tried applying this programmatically:
@Suppress("NestedBlockDepth", "MagicNumber")
fun applyLaplaceFilter(inputBitmap: Bitmap): Bitmap {
var width = inputBitmap.width
var height = inputBitmap.height
/* Create a new Bitmap to store the result */
var resultBitmap = Bitmap.createBitmap(width, height, inputBitmap.config)
/* Iterate through each pixel in the inputBitmap */
for (y in 1 until height - 1) {
for (x in 1 until width - 1) {
var sum = 0
/* Apply Laplace filter to each pixel and its neighbors */
for (i in -1..1) {
for (j in -1..1) {
var pixel = inputBitmap.getPixel(x + i, y + j)
var gray =
(Color.red(pixel) * 0.299 + Color.green(pixel) * 0.587 + Color.blue(pixel) * 0.114).toInt()
sum += gray * LAPLACE_FILTER.get(i + 1).get(j + 1)
}
}
/* Ensure the value is in the valid range [0, 255] */
var newValue = max(0.0, min(255.0, sum.toDouble())).toInt()
resultBitmap.setPixel(x, y, Color.rgb(newValue, newValue, newValue))
}
}
return resultBitmap
}
But as you might expect it's super slow. By a factor of 100.Stefan Oltmann
06/25/2024, 9:30 AMAlexander Zhirkevich
06/25/2024, 9:30 AMStefan Oltmann
06/25/2024, 9:31 AMAlexander Zhirkevich
06/25/2024, 9:31 AMStefan Oltmann
06/25/2024, 9:39 AM