前提・実現したいこと
1か月ほど前からandroid studioを始めた初心者です。
MainActivity.javaのsetAnalyzerでカメラでキャプチャした画像のアドレスをC++に渡し、そこで画像処理を行ってからMainActivity.javaのimageViewに出力するというコードです.
実装するとpreviewはでき、処理後の画像は1枚目だけimageViewに表示されますが、その後アプリは落ちてしまいます。
発生している問題・エラーメッセージ
デバッグするとImageAnalysisNonBlockingAnalyzer.javaのprivate synchronized void analyze(@NonNull ImageProxy imageProxy)のmPostedImageTimestamp.set(imageProxy.getTimestamp());という関数?のところで処理後の画像が画面に出た後落ちてしまいます。
処理後の画像が見えないとこれ以降の作業がやりづらいので見えるようにしたいです。。。
該当のソースコード
MainActivity.java import androidx.appcompat.app.AppCompatActivity; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Matrix; import android.os.Bundle; import android.view.TextureView; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.Toast; import org.opencv.android.Utils; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; import androidx.camera.core.CameraX; import androidx.camera.core.ImageAnalysis; import androidx.camera.core.ImageAnalysisConfig; import androidx.camera.core.ImageProxy; import androidx.camera.core.Preview; import androidx.camera.core.PreviewConfig; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.nio.ByteBuffer; import java.util.concurrent.Executors; public class MainActivity extends AppCompatActivity { private final int REQUEST_CODE_PERMISSIONS = 1234; private final String[] REQUIRED_PERMISSIONS = new String[]{"android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE"}; private TextureView textureView; private ImageView imageView; static { System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.textureView = findViewById(R.id.texture_view); if (allPermissionsGranted()) { this.textureView.post(() -> startCamera()); } else { ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_CODE_PERMISSIONS) { if (allPermissionsGranted()) { startCamera(); } else { Toast.makeText(this, "ユーザーから権限が許可されていません。", Toast.LENGTH_SHORT).show(); finish(); } } } private boolean allPermissionsGranted() { for (String permission : REQUIRED_PERMISSIONS) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } private void startCamera(){ PreviewConfig pConfig = new PreviewConfig.Builder().build(); Preview preview = new Preview(pConfig); preview.setOnPreviewOutputUpdateListener(output -> { ViewGroup parent = (ViewGroup)this.textureView.getParent(); parent.removeView(this.textureView); parent.addView(this.textureView, 0); this.textureView.setSurfaceTexture(output.getSurfaceTexture()); int w = output.getTextureSize().getWidth(); int h = output.getTextureSize().getHeight(); int degree = output.getRotationDegrees(); if (degree == 90 || degree == 270) { w = output.getTextureSize().getHeight(); h = output.getTextureSize().getWidth(); } h = h * textureView.getWidth() / w; w = textureView.getWidth(); ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(w,h); textureView.setLayoutParams(params);; }); // 画像の解析 ImageAnalysisConfig imageConfig = new ImageAnalysisConfig.Builder().setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE).build(); ImageAnalysis analysis = new ImageAnalysis(imageConfig); analysis.setAnalyzer(Executors.newSingleThreadExecutor(), new ImageAnalysis.Analyzer() { @Override public void analyze(ImageProxy image, int i) { imageView = findViewById(R.id.imageView); ByteBuffer yBuffer = image.getPlanes()[0].getBuffer(); ByteBuffer uBuffer = image.getPlanes()[1].getBuffer(); ByteBuffer vBuffer = image.getPlanes()[2].getBuffer(); int ySize = yBuffer.remaining(); int uSize = uBuffer.remaining(); int vSize = vBuffer.remaining(); byte[] nv21 = new byte[ySize + uSize + vSize]; yBuffer.get(nv21, 0, ySize); vBuffer.get(nv21, ySize, vSize); uBuffer.get(nv21, ySize + vSize, uSize); Mat yuv = new Mat(image.getHeight() + image.getHeight() / 2, image.getWidth(), CvType.CV_8UC1); yuv.put(0, 0, nv21); Mat mat = new Mat(); Imgproc.cvtColor(yuv, mat, Imgproc.COLOR_YUV2RGB_NV21, 3); Mat matOutput = new Mat(mat.rows(), mat.cols(), mat.type()); processImage(mat.getNativeObjAddr(), matOutput.getNativeObjAddr()); Bitmap bitmap1 = Bitmap.createBitmap(matOutput.cols(), matOutput.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(matOutput, bitmap1); int imageWidth = bitmap1.getWidth(); int imageHeight = bitmap1.getHeight(); Matrix matrix = new Matrix(); matrix.setRotate(90, imageWidth/2, imageHeight/2); 成 Bitmap bitmap2 = Bitmap.createBitmap(bitmap1, 0, 0, imageWidth, imageHeight, matrix, true); imageView.setImageBitmap(bitmap2); } }); CameraX.bindToLifecycle(this, preview, analysis); } public native int processImage(long objMatSrc, long objMatDst); } native-lib.cpp #include <jni.h> #include <string> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> extern "C" JNIEXPORT jint JNICALL Java_com_example_opencv_1org_MainActivity_processImage(JNIEnv *env, jobject, jlong objMatSrc, jlong objMatDst) { cv::Mat *srcImage = (cv::Mat *) objMatSrc; cv::Mat *dst = (cv::Mat *) objMatDst; cv::Mat grayImage, edgeImage; cv::cvtColor(*srcImage, *dst, cv::COLOR_BGR2GRAY); return 0; }
試したこと
多分、CameraX.bindToLifecycleとimageView.setImageBitmapの使い方が間違っているのかと思い調べてみましたがよくわかりませんでした。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。