0

i really need some help with this one. this error has been haunting me for a month and i still couldn't get the solution right.

so i'm trying to make a face detection using android for my essay.

public class MainActivity extends AppCompatActivity {
//static {System.loadLibrary("openCVLibrary310");}

ImageView imageView;
Button BtnGallery, BtnCamera, BtnProcess;
int x, y, height, width;
Imgproc imgproc = new Imgproc();
Imgcodecs imgcodecs = new Imgcodecs();
String PathImage;
Bitmap btmp, TempImage;
/**
 * ATTENTION: This was auto-generated to implement the App Indexing API.
 * See https://g.co/AppIndexing/AndroidStudio for more information.
 */
private GoogleApiClient client;
//System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

@Override
protected void onCreate(Bundle savedInstanceState) {

    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    }
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    imageView = (ImageView) findViewById(R.id.ShowImage);
    BtnGallery = (Button) findViewById(R.id.btnGallery);
    BtnCamera = (Button) findViewById(R.id.btnCamera);
    BtnProcess = (Button) findViewById(R.id.btnProcess);

    BtnGallery.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent pickPhoto = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(pickPhoto, 1);//one can be replaced with any action code
        }
    });

    BtnCamera.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(takePicture, 0);//zero can be replaced with any action code
        }
    });

    BtnProcess.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //Uri selectedImage = imageReturnedIntent.getData();
            //Uri myImageUri = imageReturnedIntent.getData;
            //Uri selectedImage = getImageUri(this, UriImage);
            Detector(PathImage);
            imageView.setImageURI(getImageUri(MainActivity.this, btmp));

            //Intent SendImage = new Intent();
            //SendImage.putExtra("imageUri", imageView.toString());
            //SendImage.setData(UriImage); //throw ImageUri to another function
            //startActivityForResult(SendImage, 2);
        }
    });
    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    switch (requestCode) {
        case 0:
            if (resultCode == RESULT_OK) {
                Uri selectedImage = imageReturnedIntent.getData();
                imageView.setImageURI(selectedImage);
                PathImage = selectedImage.getPath();
            }

            break;
        case 1:
            if (resultCode == RESULT_OK) {
                Uri selectedImage = imageReturnedIntent.getData();
                imageView.setImageURI(selectedImage);
                PathImage = selectedImage.getPath();
            }
            break;

    }
}

private void Detector(String myImagePath){

    InputStream is = getResources().openRawResource(R.raw.haarcascade_frontalface_alt);
    File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
    File mCascadeFile = new File(cascadeDir,
            "haarcascade_frontalface_alt.xml");
    //String detect = Environment.getExternalStorageDirectory()+"/data/haarcascade_frontalface_alt.xml";
    CascadeClassifier faceDetector = new CascadeClassifier(mCascadeFile.getAbsolutePath());
    faceDetector.load(mCascadeFile.getAbsolutePath());
    if (faceDetector.empty()) {
        Log.w("FAILED", "Failed to load cascade classifier"+ mCascadeFile.getAbsolutePath());
        faceDetector = null;
    } else
        Log.w("SUCCESSFULL", "Loaded cascade classifier from "
                + mCascadeFile.getAbsolutePath());

    Log.e("STEP 2", "ADDING .JPEG");
    String trueFilePath = myImagePath+".JPEG";
    Mat image = imgcodecs.imread(myImagePath, Imgcodecs.CV_LOAD_IMAGE_COLOR);
    MatOfRect facedetect = new MatOfRect();
    org.opencv.core.Size MinS = new org.opencv.core.Size(0, 30);
    org.opencv.core.Size MaxS = new org.opencv.core.Size(30, 0);
    faceDetector.detectMultiScale(image, facedetect, 1.1, 3, 0, MinS, MaxS);
    //faceDetector.detectMultiScale(image, facedetect, 1.1, 2);
    Mat tmp = new Mat(height, width, CvType.CV_8U, new Scalar(4));

    for (Rect rect : facedetect.toArray()) {
        imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
    }//create rectangle

    try {
        //Imgproc.cvtColor(seedsImage, tmp, Imgproc.COLOR_RGB2BGRA);
        Imgproc.cvtColor(image, tmp, Imgproc.COLOR_GRAY2RGBA, 4);
        btmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(tmp, btmp);
        //change Mat to Bitmap
    } catch (CvException e) {
        Log.d("Exception", e.getMessage());
    }
}

public Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}

so my application will ask an image from the user it can be either an image from gallery or from camera, after that the application will throw the Uri to String Image to the OpenCV Haarcascade to be processed and then show it again on the main menu. i think my image Uri to String is kinda wrong too but i don't have any idea how to make the OpenCV able to process the image beside of that and when i tried to run the program i got 2 errors. the first one is

CvException [org.opencv.core.CvException: cv::Exception: /Volumes/Linux/builds/master_pack-android/opencv/modules/objdetect/src/cascadedetect.cpp:1639: error: (-215) !empty() in function void cv::CascadeClassifier::detectMultiScale(cv::InputArray, std::vector >&, double, int, int, cv::Size,

and the second one is this one. i got this one after trying to make this line of code

    org.opencv.core.Size MinS = new org.opencv.core.Size(0, 30);
    org.opencv.core.Size MaxS = new org.opencv.core.Size(30, 0);
    faceDetector.detectMultiScale(image, facedetect, 1.1, 3, 0, MinS, MaxS);

java.lang.NullPointerException: Attempt to invoke virtual method 'void org.opencv.objdetect.CascadeClassifier.detectMultiScale(org.opencv.core.Mat, org.opencv.core.MatOfRect, double, int, int, org.opencv.core.Size, org.opencv.core.Size)' on a null object

i think the error is because my program can't read the haarcascade_frontalface_alt.xml. i have place the XML file on android resource, on android external and internal device and trying to call them using function Environment.getExternalStorageDirectory() and Environment.getDataDirectory()but still can't detect them.

please help i'm very desperate here. my lecturer suggest using a web service but i didn't tell me what should i learn to make it. i mean i don't know what should i learn first to make it. i really appreciate for any input here. Thank you

  • after trying to load the classifier you are calling log.w() so can you verify from the log, that the classifier wasn't loaded correctly? – Micka Jul 03 '17 at 22:44
  • Step through the code yet? – Namphibian Jul 03 '17 at 23:48
  • yea i read some on stack overflow my error is because i cant load the classifier correctly so i'm trying to check it using log.w() @Micka – Kevin Historia Jul 04 '17 at 10:54
  • @Namphibian you mean write log.w() for every function on the code? – Kevin Historia Jul 04 '17 at 10:55
  • after trying to load the classifier in your code there already is log.w which writes whether loading was successful or failed. You just have to find out how to read the log now... – Micka Jul 04 '17 at 10:57
  • `if (faceDetector.empty()) { Log.w("FAILED", "Failed to load cascade classifier"+ mCascadeFile.getAbsolutePath()); faceDetector = null; } else Log.w("SUCCESSFULL", "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());` – Micka Jul 04 '17 at 10:57
  • @Micka yea it always failed. i checked the path many times and it's correct. as a note i run the application on real hardware phone not on emulator – Kevin Historia Jul 04 '17 at 11:24
  • does your app have the rights to access that path? – Micka Jul 04 '17 at 11:28
  • @Micka no, i didn't know how to setting the app to make the code have the rights to access internal storage. i do read at some article on internet that i need rights to access internal storage. so, once i try to switch to external storage and it still got the error. since they said that external storage didn't need the right to access the path – Kevin Historia Jul 04 '17 at 11:42
  • I don't know enough about android to help you there. Maybe it is a rights problem or not, I don't known, it was just a guess. But apps might still need rights to access external storage since some andoid version, afaik. – Micka Jul 04 '17 at 11:47
  • @Micka hmm ok ill try to fix that problems. thanks for the suggestion :) – Kevin Historia Jul 04 '17 at 12:25
  • @Micka i got this error. do you understand what it means?? – Kevin Historia Jul 04 '17 at 14:22
  • @Micka Attempt to invoke virtual method 'void org.opencv.objdetect.CascadeClassifier.detectMultiScale(org.opencv.core.Mat, org.opencv.core.MatOfRect, double, int, int, org.opencv.core.Size, org.opencv.core.Size)' on a null object reference – Kevin Historia Jul 04 '17 at 14:22
  • I'm not a C# pro, but it looks like your code tries to call .detectMultiScale after the cascade classifier wasnt created successfully. After `Log.w("FAILED", "Failed to load cascade classifier"+ mCascadeFile.getAbsolutePath()); faceDetector = null;` you should close your program or at least just don't use any functions of faceDetector in that case. You just have to successfully load the .xml file instead... – Micka Jul 04 '17 at 14:24
  • @Micka ooh i see. i want to ask too if maybe you have any experience using Web Services. the .xml file that i'm trying to load here is it the same xml file on web service? if it same then can i parse it from web service? – Kevin Historia Jul 04 '17 at 14:37
  • no experience using Web Services, sorry. Did you search about loading the classifier? Maybe this one helps? https://stackoverflow.com/questions/34953704/opencv-for-android-failed-to-load-cascade-classifier-error – Micka Jul 04 '17 at 14:40
  • @Micka hey, i'd like to ask a question about opencv face detection. i got this error while trying to do FD using video. – Kevin Historia Jul 07 '17 at 10:18
  • @Micka java.lang.UnsatisfiedLinkError: No implementation found for void sunrise.ndkopencvtest1.OpencvClass.faceDetection(long) (tried Java_sunrise_ndkopencvtest1_OpencvClass_faceDetection and Java_sunrise_ndkopencvtest1_OpencvClass_faceDetection__J) – Kevin Historia Jul 07 '17 at 10:18
  • looks like you didn't link some needed libaries. I have no idea how this works in java, in C++ you would have to add opencv_objdetect.lib to your linker input. – Micka Jul 07 '17 at 10:21
  • @Micka yea its on C++ languange, since im using NDK on android studio. i got that error while trying to make another application using opencv for live detection so i can know how to load the .xml. so i need to link opencv_objdetect.lib on linker input? like on android.mk file? or on .cpp file? – Kevin Historia Jul 08 '17 at 00:42
  • linking is pro ably parametrized in the project settings. the right filename depends on your opencv version and build type. – Micka Jul 08 '17 at 00:45
  • @Micka i heard opencv 3.1 got a lot more bugs compare to its previous version. maybe its because of that? – Kevin Historia Jul 08 '17 at 01:03
  • @Micka and now the program is working, but it wont detect face on camera live haha – Kevin Historia Jul 08 '17 at 03:19
  • does it detect the face in lenna.png? – Micka Jul 08 '17 at 07:54
  • @Micka you mean on a file?? currently i didn't continue my main project application instead i'm trying to make a normal live face detection on android to understand how it works and what's the usage of the NDK – Kevin Historia Jul 08 '17 at 22:02
  • to reduce error sources you could test on static images instead of live camera images. If it doesn't work on the standard lenna.png image, there is probably some problem in your program and not in the image material – Micka Jul 08 '17 at 22:04
  • @Micka ahhh i see, thanks for the idea and reply. ill try to make face detection on static image for a while – Kevin Historia Jul 08 '17 at 22:14
  • @Micka do you know how to change .jpg image file to bitmap? seems like my error faceDetector.detectMultiScale(image, facedetect); the image variable on that file contains Mat image = imgcodecs.imread(myImagePath, Imgcodecs.CV_LOAD_IMAGE_COLOR); while myImagePath contains a UriToString data. – Kevin Historia Jul 09 '17 at 01:19

0 Answers0