I want to draw a rectangle with opencv from the image acquired by camerax and display it in imageview.
The top of the attached image is Image View and the bottom is Preview View.
An image with noise or a completely black image is output.
I suspect there is a problem with the process of converting ImageProxy to Mat or Bitmap.
class MyImageAnalyzer(previewview:PreviewView,imageview:ImageView) : ImageAnalysis.Analyzer {
var previewView:PreviewView = previewview
var imageView:ImageView = imageview
override fun analyze(image: ImageProxy) {
/* Create cv::mat(RGB888) from image(NV21) */
val matOrg = getMatFromImage(image)
/* Fix image rotation (it looks image in PreviewView is automatically fixed by CameraX???) */
val mat = fixMatRotation(matOrg)
/* Do some image processing */
val matOutput = Mat(mat.rows(), mat.cols(), mat.type())
/* Draw something for test */
Imgproc.rectangle(
matOutput,
Rect(10, 10, 100, 100),
Scalar(255.0, 0.0, 0.0)
)
/* Convert cv::mat to bitmap for drawing */
val bitmap =
Bitmap.createBitmap(matOutput.cols(), matOutput.rows(), Bitmap.Config.ARGB_8888)
Utils.matToBitmap(matOutput, bitmap)
/* Display the result onto ImageView */
Handler(Looper.getMainLooper()).post {
imageView.setImageBitmap(bitmap)
}
/* Close the image otherwise, this function is not called next time */
image.close()
}
private fun getMatFromImage(image: ImageProxy): Mat {
/* https://stackoverflow.com/questions/30510928/convert-android-camera2-api-yuv-420-888-to-rgb */
val yBuffer: ByteBuffer = image.planes[0].buffer
val uBuffer: ByteBuffer = image.planes[1].buffer
val vBuffer: ByteBuffer = image.planes[2].buffer
val ySize: Int = yBuffer.remaining()
val uSize: Int = uBuffer.remaining()
val vSize: Int = vBuffer.remaining()
val nv21 = ByteArray(ySize + uSize + vSize)
yBuffer.get(nv21, 0, ySize)
vBuffer.get(nv21, ySize, vSize)
uBuffer.get(nv21, ySize + vSize, uSize)
val yuv = Mat(image.height + image.height / 2, image.width, CvType.CV_8UC1)
yuv.put(0, 0, nv21)
val mat = Mat()
Imgproc.cvtColor(yuv, mat, Imgproc.COLOR_YUV2RGB_NV21, 3)
return mat
}
private fun fixMatRotation(matOrg: Mat): Mat {
val mat: Mat
when (previewView.display.rotation) {
Surface.ROTATION_0 -> {
mat = Mat(matOrg.cols(), matOrg.rows(), matOrg.type())
Core.transpose(matOrg, mat)
Core.flip(mat, mat, 1)
}
Surface.ROTATION_90 -> mat = matOrg
Surface.ROTATION_270 -> {
mat = matOrg
Core.flip(mat, mat, -1)
}
else -> {
mat = Mat(matOrg.cols(), matOrg.rows(), matOrg.type())
Core.transpose(matOrg, mat)
Core.flip(mat, mat, 1)
}
}
return mat
}
}
I hope the processed image is displayed smoothly on the ImageView