Nehmen Sie das Bild mit drawable/Farbe auf Gesicht mit vision-api

Was ich versuche?

Ich versuche zu fotografieren mit drawable/malen auf dem Gesicht, aber ich bin nicht in der Lage, beide auf dem gleichen Bild.

Nehmen Sie das Bild mit drawable/Farbe auf Gesicht mit vision-api

Was ich versucht habe?

Habe ich versucht, mit CameraSource.takePicture aber ich bin nur das erste Gesicht, ohne drawable/Farbe auf.

mCameraSource.takePicture(shutterCallback, new CameraSource.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] bytes) {
                try {
                    String mainpath = getExternalStorageDirectory() + separator + "TestXyz" + separator + "images" + separator;
                    File basePath = new File(mainpath);
                    if (!basePath.exists())
                        Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success": "Failed");
                    String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
                    File captureFile = new File(path);
                    captureFile.createNewFile();
                    if (!captureFile.exists())
                        Log.d("CAPTURE_FILE_PATH", captureFile.createNewFile() ? "Success": "Failed");
                    FileOutputStream stream = new FileOutputStream(captureFile);
                    stream.write(bytes);
                    stream.flush();
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

Ich habe auch versucht mit :

mPreview.setDrawingCacheEnabled(true);
        Bitmap drawingCache = mPreview.getDrawingCache();
        try {
            String mainpath = getExternalStorageDirectory() + separator + "TestXyz" + separator + "images" + separator;
            File basePath = new File(mainpath);
            if (!basePath.exists())
                Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success": "Failed");
            String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
            File captureFile = new File(path);
            captureFile.createNewFile();
            if (!captureFile.exists())
                Log.d("CAPTURE_FILE_PATH", captureFile.createNewFile() ? "Success": "Failed");
            FileOutputStream stream = new FileOutputStream(captureFile);
            drawingCache.compress(Bitmap.CompressFormat.PNG, 100, stream);
            stream.flush();
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

in diesem Fall bin ich nur bekomme, was ich zeichnen auf dem Gesicht. Hier mPreview ist die CameraSourcePreview.

Nur Hinzugefügt capture-Taste und oben hinzugefügten code in diese google Beispiel.

  • Bitte geben Sie eine minimale reproduzierbare Beispiel.
  • Sicher, lassen Sie mich zu aktualisieren.
  • Frage aktualisiert, mit code.
  • Bitte Lesen Sie den link gab ich wieder.
  • Könntest du ein Beispiel-Bild, das zeigt, was Sie zu erreichen versuchen?
  • Bild Hinzugefügt.

InformationsquelleAutor SANAT | 2017-07-31



3 Replies
  1. 11

    Sind Sie sehr nah zu erreichen, was Sie brauchen 🙂

    Haben Sie:

    1. Ein Bild von der Kamera von der face (First code-snippet)
    2. Ein Bild von der Leinwand aus den Augen overlay (der Zweite code-snippet)

    Was Sie brauchen:

    • Ein Bild, das das Gesicht mit den Augen-overlay auf der Oberseite – Eine zusammengeführte Bild.

    Wie Zusammenführen?

    Zusammenführen 2 Bilder, die einfach mit einem canvas-Bereich, etwa so:

    public Bitmap mergeBitmaps(Bitmap face, Bitmap overlay) {
        //Create a new image with target size
        int width = face.getWidth();
        int height = face.getHeight();
        Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    
        Rect faceRect = new Rect(0,0,width,height);
        Rect overlayRect = new Rect(0,0,overlay.getWidth(),overlay.getHeight());
    
        //Draw face and then overlay (Make sure rects are as needed)
        Canvas canvas = new Canvas(newBitmap); 
        canvas.drawBitmap(face, faceRect, faceRect, null);
        canvas.drawBitmap(overlay, overlayRect, faceRect, null);
        return newBitmap
    }

    Dann können Sie speichern Sie das neue Bild, als Sie jetzt tun.

    Vollständige code würde wie folgt Aussehen:

    mCameraSource.takePicture(shutterCallback, new 
    CameraSource.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] bytes) {
                //Generate the Face Bitmap
                BitmapFactory.Options options = new BitmapFactory.Options();
                Bitmap face = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    
                //Generate the Eyes Overlay Bitmap
                mPreview.setDrawingCacheEnabled(true);
                Bitmap overlay = mPreview.getDrawingCache();
    
                //Generate the final merged image
                Bitmap result = mergeBitmaps(face, overlay);
    
                //Save result image to file
                try {
                    String mainpath = getExternalStorageDirectory() + separator + "TestXyz" + separator + "images" + separator;
                    File basePath = new File(mainpath);
                    if (!basePath.exists())
                        Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success": "Failed");
                    String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
                    File captureFile = new File(path);
                    captureFile.createNewFile();
                    if (!captureFile.exists())
                        Log.d("CAPTURE_FILE_PATH", captureFile.createNewFile() ? "Success": "Failed");
                    FileOutputStream stream = new FileOutputStream(captureFile);
                    result.compress(Bitmap.CompressFormat.PNG, 100, stream);
                    stream.flush();
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    Beachten Sie, dass die oben ist nur ein Beispiel code.
    Sie sollten vermutlich das verschmelzen und zu speichern, um eine Datei in einen hintergrund-thread.

    • Danke für deine Antwort. Ich habe bereits versucht, was du hier erwähnt und ich habe Erfolg mit meinem code. Lassen Sie mich post meine Antwort. Hilft es anderen auch.
  2. 5

    Ich bin in der Lage zu erfassen Bild mit drawable/Farbe auf, die von unten Lösung :

    private void captureImage() {
            mPreview.setDrawingCacheEnabled(true);
            Bitmap drawingCache = mPreview.getDrawingCache();
    
            mCameraSource.takePicture(shutterCallback, new CameraSource.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] bytes) {
                    int orientation = Exif.getOrientation(bytes);
                    Bitmap temp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                    Bitmap picture = rotateImage(temp,orientation);
                    Bitmap overlay = Bitmap.createBitmap(mGraphicOverlay.getWidth(),mGraphicOverlay.getHeight(),picture.getConfig());
                    Canvas canvas = new Canvas(overlay);
    
                    Matrix matrix = new Matrix();
    
                    matrix.setScale((float)overlay.getWidth()/(float)picture.getWidth(),(float)overlay.getHeight()/(float)picture.getHeight());
    
                    //mirror by inverting scale and translating
                    matrix.preScale(-1, 1);
                    matrix.postTranslate(canvas.getWidth(), 0);
    
                    Paint paint = new Paint();
                    canvas.drawBitmap(picture,matrix,paint);
                    canvas.drawBitmap(drawingCache,0,0,paint);
    
                    try {
                        String mainpath = getExternalStorageDirectory() + separator + "MaskIt" + separator + "images" + separator;
                        File basePath = new File(mainpath);
                        if (!basePath.exists())
                            Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success": "Failed");
                        String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
                        File captureFile = new File(path);
                        captureFile.createNewFile();
                        if (!captureFile.exists())
                            Log.d("CAPTURE_FILE_PATH", captureFile.createNewFile() ? "Success": "Failed");
                        FileOutputStream stream = new FileOutputStream(captureFile);
                        overlay.compress(Bitmap.CompressFormat.PNG, 100, stream);
                        stream.flush();
                        stream.close();
                        picture.recycle();
                        drawingCache.recycle();
                        mPreview.setDrawingCacheEnabled(false);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

    Manchmal Ausrichtung Problem tritt auch auf einigen Geräten. Für die, die ich verwendet Exif Klasse und rotateImage() Funktion.

    Exif-Klasse (Verweis aus hier) :

    public class Exif {
        private static final String TAG = "CameraExif";
    
        //Returns the degrees in clockwise. Values are 0, 90, 180, or 270.
        public static int getOrientation(byte[] jpeg) {
            if (jpeg == null) {
                return 0;
            }
    
            int offset = 0;
            int length = 0;
    
            //ISO/IEC 10918-1:1993(E)
            while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) {
                int marker = jpeg[offset] & 0xFF;
    
                //Check if the marker is a padding.
                if (marker == 0xFF) {
                    continue;
                }
                offset++;
    
                //Check if the marker is SOI or TEM.
                if (marker == 0xD8 || marker == 0x01) {
                    continue;
                }
                //Check if the marker is EOI or SOS.
                if (marker == 0xD9 || marker == 0xDA) {
                    break;
                }
    
                //Get the length and check if it is reasonable.
                length = pack(jpeg, offset, 2, false);
                if (length < 2 || offset + length > jpeg.length) {
                    Log.e(TAG, "Invalid length");
                    return 0;
                }
    
                //Break if the marker is EXIF in APP1.
                if (marker == 0xE1 && length >= 8 &&
                        pack(jpeg, offset + 2, 4, false) == 0x45786966 &&
                        pack(jpeg, offset + 6, 2, false) == 0) {
                    offset += 8;
                    length -= 8;
                    break;
                }
    
                //Skip other markers.
                offset += length;
                length = 0;
            }
    
            //JEITA CP-3451 Exif Version 2.2
            if (length > 8) {
                //Identify the byte order.
                int tag = pack(jpeg, offset, 4, false);
                if (tag != 0x49492A00 && tag != 0x4D4D002A) {
                    Log.e(TAG, "Invalid byte order");
                    return 0;
                }
                boolean littleEndian = (tag == 0x49492A00);
    
                //Get the offset and check if it is reasonable.
                int count = pack(jpeg, offset + 4, 4, littleEndian) + 2;
                if (count < 10 || count > length) {
                    Log.e(TAG, "Invalid offset");
                    return 0;
                }
                offset += count;
                length -= count;
    
                //Get the count and go through all the elements.
                count = pack(jpeg, offset - 2, 2, littleEndian);
                while (count-- > 0 && length >= 12) {
                    //Get the tag and check if it is orientation.
                    tag = pack(jpeg, offset, 2, littleEndian);
                    if (tag == 0x0112) {
                        //We do not really care about type and count, do we?
                        int orientation = pack(jpeg, offset + 8, 2, littleEndian);
                        switch (orientation) {
                            case 1:
                                return 0;
                            case 3:
                                return 3;
                            case 6:
                                return 6;
                            case 8:
                                return 8;
                        }
                        Log.i(TAG, "Unsupported orientation");
                        return 0;
                    }
                    offset += 12;
                    length -= 12;
                }
            }
    
            Log.i(TAG, "Orientation not found");
            return 0;
        }
    
        private static int pack(byte[] bytes, int offset, int length,
                boolean littleEndian) {
            int step = 1;
            if (littleEndian) {
                offset += length - 1;
                step = -1;
            }
    
            int value = 0;
            while (length-- > 0) {
                value = (value << 8) | (bytes[offset] & 0xFF);
                offset += step;
            }
            return value;
        }
    }

    rotateImage Funktion :

        private Bitmap rotateImage(Bitmap bm, int i) {
            Matrix matrix = new Matrix();
            switch (i) {
                case ExifInterface.ORIENTATION_NORMAL:
                    return bm;
                case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                    matrix.setScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    matrix.setRotate(180);
                    break;
                case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                    matrix.setRotate(180);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_TRANSPOSE:
                    matrix.setRotate(90);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    matrix.setRotate(90);
                    break;
                case ExifInterface.ORIENTATION_TRANSVERSE:
                    matrix.setRotate(-90);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    matrix.setRotate(-90);
                    break;
                default:
                    return bm;
            }
            try {
                Bitmap bmRotated = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
                bm.recycle();
                return bmRotated;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return null;
            }
        }
  3. 4

    Können Sie erreichen den Effekt, den Sie wollen, indem man es in kleinere Schritte auf.

    1. Nehmen Sie das Bild
    2. Senden der bitmap zu Google Mobile Vision zu erkennen, die „Sehenswürdigkeiten“ in das Gesicht, und die Wahrscheinlichkeit, dass jedes Auge ist offen
    3. Farbe der entsprechenden „Augen“ auf Ihr Bild

    Bei der Verwendung von Google Mobile Vision FaceDetector, Sie zurück zu bekommen ein SparseArray Gesichts-Objekte (die enthalten möglicherweise mehr als ein Gesicht, oder kann leer sein). So werden Sie brauchen, um diese Fälle zu behandeln. Aber Sie können eine Schleife durch die SparseArray und finden Sie die Gesicht-Objekt, das Sie wollen, zu spielen.

    static Bitmap processFaces(Context context, Bitmap picture) {
        //Create a "face detector" object, using the builder pattern
        FaceDetector detector = new FaceDetector.Builder(context)
                .setTrackingEnabled(false) //disable tracking to improve performance
                .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
                .build();
    
        //create a "Frame" object, again using a builder pattern (and passing in our picture)
        Frame frame = new Frame.Builder().setBitmap(picture).build(); //build frame
    
        //get a sparse array of face objects
        SparseArray<Face> faces = detector.detect(frame); //detect the faces
    
        //This example just deals with a single face for the sake of simplicity,
        //but you can change this to deal with multiple faces.
        if (faces.size() != 1) return picture;
    
        //make a mutable copy of the background image that we can modify
        Bitmap bmOverlay = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), picture.getConfig());
        Canvas canvas = new Canvas(bmOverlay);
        canvas.drawBitmap(picture, 0, 0, null);
        //get the Face object that we want to manipulate, and process it
        Face face = faces.valueAt(0);
        processFace(face, canvas);
        detector.release();
        return bmOverlay;
    }

    Sobald Sie haben ein Gesicht, Objekt, finden Sie die Funktionen, die Sie interessieren, wie diese

    private static void processFace(Face face, Canvas canvas) {
        //The Face object can tell you the probability that each eye is open.
        //I'm comparing this probability to an arbitrary threshold of 0.6 here,
        //but you can vary it between 0 and 1 as you please.
        boolean leftEyeClosed = face.getIsLeftEyeOpenProbability() < .6;
        boolean rightEyeClosed = face.getIsRightEyeOpenProbability() < .6;
        //Loop through the face's "landmarks" (eyes, nose, etc) to find the eyes.
        //landmark.getPosition() gives you the (x,y) coordinates of each feature.
        for (Landmark landmark : face.getLandmarks()) {
            if (landmark.getType() == Landmark.LEFT_EYE)
                overlayEyeBitmap(canvas, leftEyeClosed, landmark.getPosition().x, landmark.getPosition().y);
            if (landmark.getType() == Landmark.RIGHT_EYE)
                overlayEyeBitmap(canvas, rightEyeClosed, landmark.getPosition().x, landmark.getPosition().y);
        }
    }

    Dann können Sie Ihre Farbe!

    private static void overlayEyeBitmap(Canvas canvas, boolean eyeClosed, float cx, float cy) {
        float radius = 40;
    
        //draw the eye's background circle with appropriate color
        Paint paintFill = new Paint();
        paintFill.setStyle(Paint.Style.FILL);
        if (eyeClosed)
            paintFill.setColor(Color.YELLOW);
        else
            paintFill.setColor(Color.WHITE);
        canvas.drawCircle(cx, cy, radius, paintFill);
    
        //draw a black border around the eye
        Paint paintStroke = new Paint();
        paintStroke.setColor(Color.BLACK);
        paintStroke.setStyle(Paint.Style.STROKE);
        paintStroke.setStrokeWidth(5);
        canvas.drawCircle(cx, cy, radius, paintStroke);
    
        if (eyeClosed)
            //draw horizontal line across closed eye
            canvas.drawLine(cx - radius, cy, cx + radius, cy, paintStroke);
        else {
            //draw big off-center pupil on open eye
            paintFill.setColor(Color.BLACK);
            float cxPupil = cx - 10;
            float cyPupil = cy + 10;
            canvas.drawCircle(cxPupil, cyPupil, 25, paintFill);
        }
    }

    In dem snippet oben, ich habe gerade hardcoded das Auge Radien, um zu zeigen, proof-of-concept. Sie werden wahrscheinlich wollen, zu tun, einige weitere flexible Skalierung mit Prozentsatz der face.getWidth() zur Bestimmung der entsprechenden Werte. Aber hier ist, was diese Bildbearbeitung machen kann:

    Nehmen Sie das Bild mit drawable/Farbe auf Gesicht mit vision-api

    Einige weitere details über die Mobile Vision-API sind hier, und Udacity aktuellen Advanced Android natürlich hat ein nettes walkthrough von diesem Zeug (ein Bild, senden an Mobile Vision, und das hinzufügen einer bitmap, die auf Sie). Der Kurs ist kostenlos, oder Sie können nur sehen, was Sie Tat auf Github.

    • Kann ich die capture-Bild mit paint? Ich brauche Bild mit paint auf Bild der Kamera.
    • Nicht sicher was genau du fragst. Sie können erfassen, einfachen Bilder mit einer Kamera-Vorsatz. Sie können merge-gemalte Bilder auf, die, wie ich beschrieben. Sie speichern ein Bild, wie die, die ich zu einer Datei, oder teilen Sie es, oder die Verwendung als hintergrund in Ihrem eigenen Fingermalerei als Aktivität oder was auch immer.
    • Ich will einfach nur, um das Bild zu speichern, das ist in meiner Frage. Kamera-Bild + Drawable/Farbe auf.
    • Nun, Sie zeigte ein Bild, und ich gab Sie code erstellen können, die ein ähnliches Bild (Bild der Kamera mit Drawable/Farbe auf). So sind Sie wenigstens glücklich mit der image processing-code, die ich angegeben habe? Kann ich zusätzlichen code hinzufügen speichern Sie ein Bild in die user Galerie, wenn es das ist, was Sie brauchen. Aber versuchen Sie bitte, darüber im klaren sein, was genau Sie wollen.
    • Ich habe bereits code für die Farbe auf Bild-mit Google-Vision. Ich will einfach nur, um das Bild zu speichern mit Bild und drawable/Farbe auf.
    • Lassen Sie uns weiter, diese Diskussion im chat.
    • Ich habe bereits beschrieben, was ich will. Ich weiß nicht, warum Menschen nicht in der Lage zu verstehen. Bereits erwähnt, das Google-Beispiel-code, den ich verwendet.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.