Issue
I am using OpenCV in Android and I have the JavaCamera2View
which is an implementation of CameraBridgeViewBase
. I can display the preview with no problems. But I also want to capture an image on a button press and this is where I am having issues.
I have looked around and saw that in some SO questions it is suggested to use JavaCameraView.takePicture
but I think that function is not present in the second iteration.
What I tried instead is the following code:
class MainViewModel(application: Application) : AndroidViewModel(application),
CameraBridgeViewBase.CvCameraViewListener2 {
...
private var currentFrame: Mat? = null
...
override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame?): Mat {
inputFrame?.let {
currentFrame = it.rgba()
return currentFrame!!
}
return Mat().setTo(Scalar.all(0.0))
}
...
fun captureFrame() {
currentFrame?.let {
if (it.empty()) {
Log.e(tag, "FRAME IS EMPTY")
return
}
val directoryString =
getApplication<Application>().getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!.absolutePath
val directory = File(directoryString, "calibration")
if (!directory.mkdirs() && !directory.isDirectory) {
Log.e(tag, "Failed to create image directory")
return
}
val imageFile =
File(directory, dateFormat.format(Date()) + _distance.value.toString() + ".jpg")
val success = Imgcodecs.imwrite(imageFile.path, it)
if (success) {
Log.d(tag, "image saved")
} else {
Log.d(tag, "failed to save")
}
}
I call the captureFrame
method when the user taps on a button in UI, and the problem here is that I get FRAME IS EMPTY
response way too much. I can save the picture in around only 30% of the clicks. The camera is working with 15 fps so is it because when the user clicks to capture a frame, the currentFrame
is in the process of being written? Or is there any other reason that can cause this? Is there a better way to capture a frame? Should I implement saving the image into the JavaCamera2View
code myself? This feels like not a very trivial task, though.
Solution
In the end, I came up with another architecture where I have a boolean shouldSave
which is updated from the UI. I check this flag within the onCameraFrame
callback and if it is true, I save the frame and set it to false. This approach has the drawback of saving the next frame after the flag is set, but works 100% of the time nonetheless.
Answered By - mcy
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.