LoginSignup
0
1

Camera X Android Java 実装 (TextureView)

Posted at

■ UI

【01】
Camera X img_01 toshiyuki natsume
【02】
Camera X img_02 toshiyuki natsume
【03】
Camera X img_03 toshiyuki natsume

■ ソースコード

●MainActivity.java

java MainActivity.java

package com.example.camera_x_001;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraX;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageAnalysisConfig;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureConfig;
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 androidx.lifecycle.LifecycleOwner;

import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.media.Image;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.common.util.concurrent.ListenableFuture;

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class MainActivity extends AppCompatActivity {

    // 定数
    private final int REQUEST_CODE_PERMISSIONS = 101;


    // UI
    private TextureView textureView;
    private Button captureButton, opne_button, capture_button;

    private TextView get_with, get_height, get_gyouretu;
    private String str_get_with, str_get_height;

    // === ピンチアウト用
    private ScaleGestureDetector scaleGestureDetector;
    private float scaleFactor = 0.05f;

    private int test_count = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();

        textureView = findViewById(R.id.texture_view);

     //   scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());

        /**
         *   === カメラ起動 ===
         */
        opne_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // カメラ 起動
                startCamera();
            }
        });

    } // === END onCreate

    /**
     *   === カメラ 画面タッチ イベント ===
     */

    /*
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        scaleGestureDetector.onTouchEvent(event);
        return true;
    }

     */

    /**
     *   === カメラ 画面タッチ イベント ===
     */

    /*
    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            scaleFactor *= detector.getScaleFactor();

            // 最小・最大スケールを制限する場合は、適宜設定
            scaleFactor = Math.max(0.01f, Math.min(scaleFactor, 2.0f));

            // TextureViewのサイズを更新する
            int width = (int) (textureView.getWidth() * scaleFactor);
            int height = (int) (textureView.getHeight() * scaleFactor);
            textureView.setLayoutParams(new FrameLayout.LayoutParams(width, height));

            return true;
        }
    }

*/

        /**
         * ========= カメラの開始 =========
         */
        private void startCamera() {
            // プレビューの表示
            PreviewConfig pConfig = new PreviewConfig.Builder().build();
            Preview preview = new Preview(pConfig);
            preview.setOnPreviewOutputUpdateListener(

                    output -> {
                        // SurfaceTextureの更新
                        ViewGroup parent = (ViewGroup)this.textureView.getParent();
                        parent.removeView(this.textureView);
                        parent.addView(this.textureView, 0);

                        // SurfaceTextureをTextureViewに指定
                        this.textureView.setSurfaceTexture(output.getSurfaceTexture());

                        // TextureViewのサイズの調整
                        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);
                        params.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
                        params.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
                        params.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
                        params.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
                        textureView.setLayoutParams(params);;

                    });


                    /**
                     * ========= 画像の解析 =========
                     */
                    ImageAnalysisConfig config = new ImageAnalysisConfig.Builder()
                            .setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
                            .build();
                    ImageAnalysis imageAnalysis = new ImageAnalysis(config);
                    imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(),
                            new ImageAnalysis.Analyzer() {
                                @Override
                                public void analyze(ImageProxy image, int rotationDegrees) {

                                    // === 横 、縦 取得
                                    str_get_with = String.valueOf(image.getWidth() * test_count);
                                    str_get_height = String.valueOf(image.getHeight() * test_count);

                                    // === 表示行列 取得
                                    Matrix transformMatrix = new Matrix();
                                    String Tmp_Matrix = String.valueOf(textureView.getTransform(transformMatrix));

                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            get_with.setText(str_get_with); // 横
                                            get_height.setText(str_get_height); // 縦

                                            get_gyouretu.setText(Tmp_Matrix); // 表示行列
                                        }
                                    });

                                    android.util.Log.d("出力:::analyze:::",+image.getWidth()+"x"+image.getHeight());
                                    android.util.Log.d("出力:::analyze:::",Tmp_Matrix);

                                    test_count++;


                                }
                            });


                    /**
                     * ========= 画像のキャプチャ =========
                     */
                    ImageCaptureConfig cConfig = new ImageCaptureConfig.Builder()
                            .setTargetRotation(getWindowManager().getDefaultDisplay().getRotation())
                            .build();
                    ImageCapture imageCapture = new ImageCapture(cConfig);

                    // ボタンのイベントリスナー
                    captureButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // 画像のキャプチャ
                            File file = new File(getFilesDir(), "captured.jpg");
                            imageCapture.takePicture(file, Executors.newSingleThreadExecutor(),
                                    new ImageCapture.OnImageSavedListener() {
                                        // 成功時に呼ばれる
                                        @Override
                                        public void onImageSaved(File file) {
                                            android.util.Log.d("debug","success フォト保存OKOKOK");
                                        }

                                        // エラー時に呼ばれる
                                        @Override
                                        public void onError(
                                                ImageCapture.ImageCaptureError imageCaptureError,
                                                String message, Throwable cause) {
                                            android.util.Log.d("debug","error");
                                        }
                                    });
                        }
                    });


            // カメラのライフサイクルのバインド
           // CameraX.bindToLifecycle(this, imageAnalysis,preview);
            CameraX.bindToLifecycle(this, imageCapture, imageAnalysis, preview);
        }


        private void init() {

            captureButton = findViewById(R.id.capture_button); // 画面キャプチャ
            opne_button = findViewById(R.id.opne_button); // カメラ起動

            get_with = findViewById(R.id.get_with); // 横
            get_height = findViewById(R.id.get_height); // 縦

            get_gyouretu = findViewById(R.id.get_gyouretu); // 表示行列

        }


}

●activity_main.xml

xml activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/get_with"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12dp"
        android:textColor="#000"
        android:text="横:"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <TextView
        android:id="@+id/get_height"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12dp"
        android:textColor="#000"
        android:text="縦:"
        app:layout_constraintTop_toBottomOf="@+id/get_with"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <TextView
        android:id="@+id/get_gyouretu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12dp"
        android:textColor="#000"
        android:text="表示行列:"
        app:layout_constraintTop_toBottomOf="@+id/get_height"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <TextureView
        android:id="@+id/texture_view"
        android:layout_width="540px"
        android:layout_height="540px"
        app:layout_constraintTop_toBottomOf="@+id/get_gyouretu"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />


    <Button
        android:id="@+id/opne_button"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="カメラ起動"
        android:layout_marginTop="22dp"
        android:layout_marginBottom="22dp"
        app:layout_constraintTop_toBottomOf="@+id/texture_view"
        app:layout_constraintRight_toLeftOf="@+id/capture_button"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <Button
        android:id="@+id/capture_button"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="撮影"
        android:layout_marginTop="22dp"
        android:layout_marginBottom="22dp"
        app:layout_constraintTop_toBottomOf="@+id/texture_view"
        app:layout_constraintLeft_toRightOf="@+id/opne_button"
        app:layout_constraintRight_toRightOf="parent"
       />

</androidx.constraintlayout.widget.ConstraintLayout>

●AndroidManifest.xml

xml AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- パーミッション 追加 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.Camera_x_001"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

●build.gradle(Module:app)


plugins {
    id 'com.android.application'
}

android {
    namespace 'com.example.camera_x_001'
    compileSdk 33

    defaultConfig {
        applicationId "com.example.camera_x_001"
        minSdk 25
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation project(path: ':sdk')
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    // === モジュール 追加 ===
   //  def camerax_version = "1.0.0-beta03"
    def camerax_version = '1.0.0-alpha06'
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-core:${camerax_version}"




}

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1