Hackster is hosting Hackster Holidays, Ep. 5: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 5 on Friday!
Yang
Created October 18, 2017

Hello Driver

Driver Monitor System, Thermal Camera (FLIR ONE for Android), Raspberry Pi, Android things

97
Hello Driver

Things used in this project

Story

Read more

Schematics

block diagram

Code

Hello Driver DEMO

Java
Android Studio 2.3.3
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PorterDuff;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.widget.ImageView;

import com.flir.flironesdk.Device;
import com.flir.flironesdk.FlirUsbDevice;
import com.flir.flironesdk.Frame;
import com.flir.flironesdk.FrameProcessor;
import com.flir.flironesdk.RenderedImage;

import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.EnumSet;

public class MainActivity extends AppCompatActivity implements Device.Delegate, FrameProcessor.Delegate, Device.StreamDelegate {

    private ImageView thermalImageView;
    private volatile Device flirOneDevice;
    private FrameProcessor frameProcessor;
    private Device.TuningState currentTuningState = Device.TuningState.Unknown;
    public Bitmap thermalBitmap;
    private CascadeClassifier cascadeClassifier;
    private ImageView faceImageView;
    private Bitmap thermalFaceBitmap = null;

    @Override
    public void onTuningStateChanged(Device.TuningState tuningState) {

        currentTuningState = tuningState;
        if (tuningState == Device.TuningState.InProgress) {
            runOnUiThread(new Thread() {
                @Override
                public void run() {
                    super.run();
                    thermalImageView.setColorFilter(Color.DKGRAY, PorterDuff.Mode.DARKEN);
                }
            });
        } else {
            runOnUiThread(new Thread() {
                @Override
                public void run() {
                    super.run();
                    thermalImageView.clearColorFilter();
                }
            });
        }
    }

    @Override
    public void onAutomaticTuningChanged(boolean b) {
    }

    @Override
    public void onDeviceConnected(Device device) {
        flirOneDevice = device;
        flirOneDevice.startFrameStream(this);
    }

    @Override
    public void onDeviceDisconnected(Device device) {
        flirOneDevice = null;
    }

    //
    private void updateThermalImageView(final Bitmap frame) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                convGray(frame);
            }
        });
    }

    //
    private void convGray(Bitmap frame) {
        Mat src = new Mat();
        Mat temp = new Mat();
        MatOfRect faces = new MatOfRect();

        frame = rotateToDegrees(frame, -90);

        int absoluteFaceSize = 70;
        Utils.bitmapToMat(frame,src);
        Imgproc.cvtColor(src,temp, Imgproc.COLOR_BGR2GRAY);

        // Use the classifier to detect faces
        if (cascadeClassifier != null) {
            cascadeClassifier.detectMultiScale(temp, faces, 1.1, 2, 1,
                    new Size(absoluteFaceSize, absoluteFaceSize), new Size());
        }

        // If there are any faces found, draw a rectangle around it
        Rect[] facesArray = faces.toArray();
        int max = 0,sizeRectangle = 0;
        int face_H = 0, face_W = 0,face_maxH = 0, face_maxW = 0;
        int num = 0, face_X = 0,face_Y = 0;
        for (int i = 0; i <facesArray.length; i++){

            face_H =(int) Math.abs(facesArray[i].tl().x-facesArray[i].br().x);
            face_W = (int) Math.abs(facesArray[i].tl().y-facesArray[i].br().y);
            sizeRectangle = face_H * face_W;
            if ( sizeRectangle > max){
                max = sizeRectangle;
                num = i;
                face_X = (int)facesArray[i].tl().x;
                face_Y = (int)facesArray[i].tl().y;
                face_maxH = face_H;
                face_maxW = face_W;
            }

        }
        if (facesArray.length > 0)
        {
            Imgproc.rectangle(src, facesArray[num].tl(), facesArray[num].br(), new Scalar(0, 255, 0, 255), 3);
            //MatROI
            //
            Rect rect = new Rect(face_X, face_Y , face_maxH, face_maxW ); // ROI
            saveFaceImage(temp, rect);
        }
        Utils.matToBitmap(src,frame);
        thermalImageView.setImageBitmap(frame);
    }

    /**
     * 
     * @param tmpBitmap
     * @param degrees
     * @return
     */
    public static Bitmap rotateToDegrees(Bitmap tmpBitmap, float degrees) {
        Matrix matrix = new Matrix();
        matrix.reset();
        matrix.setRotate(degrees);
        return tmpBitmap =
                Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(), tmpBitmap.getHeight(), matrix,
                        true);
    }

    /**
     * 
     *
     * @param image    Mat
     * @param rect     
     */
    public void saveFaceImage(Mat image, Rect rect) {

        // 
        Mat sub = image.submat(rect);
        Mat mat = new Mat();
        Size size = new Size(100, 100);
        Imgproc.resize(sub, mat, size);

        //
        thermalFaceBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(mat,thermalFaceBitmap );
        faceImageView.setImageBitmap(thermalFaceBitmap );
    }

    @Override
    public void onFrameReceived(Frame frame) {
        if (currentTuningState != Device.TuningState.InProgress) {
            frameProcessor.processFrame(frame);
        }
    }

    @Override
    public void onFrameProcessed(final RenderedImage renderedImage) {
            thermalBitmap = renderedImage.getBitmap();
            updateThermalImageView(thermalBitmap);
    }

    @Override
    protected void onStart() {
        super.onStart();
        thermalImageView = (ImageView) findViewById(R.id.imageView);

        //""
        if (Device.getSupportedDeviceClasses(this).contains(FlirUsbDevice.class)) {

        }

        try {

            Device.startDiscovery(this, this);

        } catch (IllegalStateException e) {

        } catch (SecurityException e) {

            finish();
        }
    }

    private void initializeOpenCVDependencies() {

        try {
            // Copy the resource into a temp file so OpenCV can load it
            InputStream is = getResources().openRawResource(R.raw.cascade_face );
            File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
            File mCascadeFile = new File(cascadeDir, "cascade_face.xml");
            FileOutputStream os = new FileOutputStream(mCascadeFile);


            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            is.close();
            os.close();

            // Load the cascade classifier
            cascadeClassifier = new CascadeClassifier(mCascadeFile.getAbsolutePath());
        } catch (Exception e) {
            Log.e("OpenCVActivity", "Error loading cascade", e);
        }
    }



    //OpenCV
    private void staticLoadCVLibraries(){
        boolean load = OpenCVLoader.initDebug();
        if(load) {
            Log.i("CV", "Open CV Libraries loaded...");
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        staticLoadCVLibraries();
        initializeOpenCVDependencies();

        faceImageView =  (ImageView) findViewById(R.id.faceImage);

        RenderedImage.ImageType defaultImageType = RenderedImage.ImageType.ThermalRGBA8888Image;
        frameProcessor = new FrameProcessor(this, this, EnumSet.of(defaultImageType, RenderedImage.ImageType.ThermalRGBA8888Image));


    }


    @Override
    public void onPause() {
        super.onPause();
        if (flirOneDevice != null) {
            flirOneDevice.stopFrameStream();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (flirOneDevice != null) {
            flirOneDevice.startFrameStream(this);
        }
    }

    @Override
    public void onStop() {
        // We must unregister our usb receiver, otherwise we will steal events from other apps
        Device.stopDiscovery();
        flirOneDevice = null;
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }


}

Credits

Yang

Yang

0 projects • 1 follower

Comments