Android Face detection only works with pictures not with images from an SD card

So, I have a code to detect up to 10 faces in any image file and return information to me, such as the location of the eyes and other similar things. Therefore, when I tell him to use the image file, which is stored in the resource folder for my project, it works fine. But when I have an attempt to find faces from a bitmap, I import from the SD card, it will not find any faces. But these are accurate accurate images. Any ideas? my code is below:

Edit: After further verification, I found that when I insert this line of code System.out.println("Row Bytes: " + sourceImage.getRowBytes()); I get drawable 352 and the image of the SD card is 704. Which, I think, means that the drawable is compressed in the .apk file, but the image on the SD card is obviously not. Not sure if this will affect anything.

  public class FaceView extends View { private static final int NUM_FACES = 10; // max is 64 private static final boolean DEBUG = true; private FaceDetector arrayFaces; private FaceDetector.Face getAllFaces[] = new FaceDetector.Face[NUM_FACES]; private FaceDetector.Face getFace = null; private PointF eyesMidPts[] = new PointF[NUM_FACES]; private float eyesDistance[] = new float[NUM_FACES]; private Bitmap sourceImage; private Paint tmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint pOuterBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint pInnerBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG); private int picWidth, picHeight; private float xRatio, yRatio; public FaceView(Context context) { super(context); pInnerBullsEye.setStyle(Paint.Style.FILL); pInnerBullsEye.setColor(Color.RED); pOuterBullsEye.setStyle(Paint.Style.STROKE); pOuterBullsEye.setColor(Color.RED); tmpPaint.setStyle(Paint.Style.STROKE); tmpPaint.setTextAlign(Paint.Align.CENTER); BitmapFactory.Options bfo = new BitmapFactory.Options(); bfo.inPreferredConfig = Bitmap.Config.RGB_565; //********This code imports the image from the SD card which does not work String imageInSD = Environment.getExternalStorageDirectory() .getAbsolutePath() + "/testfolder/" + "face1" + ".png"; Bitmap sourceImage = BitmapFactory.decodeFile(imageInSD,bfo); //**********This code uses an image in the projects drawable folder, this code works. sourceImage = BitmapFactory.decodeResource( getResources() ,R.drawable.face1, bfo); picWidth = sourceImage.getWidth(); picHeight = sourceImage.getHeight(); arrayFaces = new FaceDetector( picWidth, picHeight, NUM_FACES ); arrayFaces.findFaces(sourceImage, getAllFaces); for (int i = 0; i < getAllFaces.length; i++) { getFace = getAllFaces[i]; try { PointF eyesMP = new PointF(); getFace.getMidPoint(eyesMP); eyesDistance[i] = getFace.eyesDistance(); eyesMidPts[i] = eyesMP; if (DEBUG) { Log.i("Face", i + " " + getFace.confidence() + " " + getFace.eyesDistance() + " " + "Pose: ("+ getFace.pose(FaceDetector.Face.EULER_X) + "," + getFace.pose(FaceDetector.Face.EULER_Y) + "," + getFace.pose(FaceDetector.Face.EULER_Z) + ")" + "Eyes Midpoint: ("+eyesMidPts[i].x + "," + eyesMidPts[i].y +")" ); } } catch (Exception e) { if (DEBUG) Log.e("Face", i + " is null"); } } } @Override protected void onDraw(Canvas canvas) { xRatio = getWidth()*1.0f / picWidth; yRatio = getHeight()*1.0f / picHeight; canvas.drawBitmap( sourceImage, null , new Rect(0,0,getWidth(),getHeight()),tmpPaint); for (int i = 0; i < eyesMidPts.length; i++) { if (eyesMidPts[i] != null) { pOuterBullsEye.setStrokeWidth(eyesDistance[i] /6); canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 2 , pOuterBullsEye); canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 6 , pInnerBullsEye); } } } } 
+4
source share
2 answers

It turns out that the problem is that the pictures taken by the camera are saved as PNG files, and face recognition can only work successfully from an SD card if it uses JPG files. Just convert the files to jpg and it works great.

+5
source

Well, I believe that I know what the problem is. The device cannot display the image in a bitmap because it is in external memory. Face recognition works by simply not making it on canvas. All devices have a rendering limit on my xoom (2048x2048), which I found here here . The reason it works when adding an image as a resource is because your file is shortened as it creates .apk (to be honest, I'm not sure why it does it, but I left a little println to test who something else could answer that better). Anyway, I just scaled the bitmap by dividing it by 2 after your code looked for faces and before trying to display the bitmap on the canvas. Now everything is working fine. You can customize your face indicators, but its functionality. Hope this helps.

 public class FaceView extends View { private static final int NUM_FACES = 1; // max is 64 private static final boolean DEBUG = true; private FaceDetector arrayFaces; private FaceDetector.Face getAllFaces[] = new FaceDetector.Face[NUM_FACES]; private FaceDetector.Face getFace = null; private PointF eyesMidPts[] = new PointF[NUM_FACES]; private float eyesDistance[] = new float[NUM_FACES]; private Bitmap sourceImage; private Paint tmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint pOuterBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint pInnerBullsEye = new Paint(Paint.ANTI_ALIAS_FLAG); private int picWidth, picHeight; private float xRatio, yRatio; public FaceView(Context context) { super(context); pInnerBullsEye.setStyle(Paint.Style.FILL); pInnerBullsEye.setColor(Color.RED); pOuterBullsEye.setStyle(Paint.Style.STROKE); pOuterBullsEye.setColor(Color.RED); tmpPaint.setStyle(Paint.Style.STROKE); tmpPaint.setTextAlign(Paint.Align.CENTER); BitmapFactory.Options bfo = new BitmapFactory.Options(); bfo.inPreferredConfig = Bitmap.Config.RGB_565; //********This code imports the image from the SD card which does not work String imageInSD = Environment.getExternalStorageDirectory().getAbsolutePath() + "/face1" + ".jpg"; System.out.println(imageInSD); sourceImage = BitmapFactory.decodeFile(imageInSD, bfo); //Bitmap sourceImage;// = BitmapFactory.decodeFile(imageInSD,bfo); //**********This code uses an image in the projects drawable folder, this code works. //sourceImage = BitmapFactory.decodeResource( getResources() ,R.drawable.face1, bfo); picWidth = sourceImage.getWidth(); picHeight = sourceImage.getHeight(); System.out.println(picWidth + "x" + picHeight); arrayFaces = new FaceDetector( picWidth, picHeight, NUM_FACES ); arrayFaces.findFaces(sourceImage, getAllFaces); sourceImage = Bitmap.createScaledBitmap (sourceImage, picWidth/2, picHeight/2, false); for (int i = 0; i < getAllFaces.length; i++) { getFace = getAllFaces[i]; try { PointF eyesMP = new PointF(); getFace.getMidPoint(eyesMP); eyesDistance[i] = getFace.eyesDistance(); eyesMidPts[i] = eyesMP; if (DEBUG) { Log.i("Face", i + " " + getFace.confidence() + " " + getFace.eyesDistance() + " " + "Pose: ("+ getFace.pose(FaceDetector.Face.EULER_X) + "," + getFace.pose(FaceDetector.Face.EULER_Y) + "," + getFace.pose(FaceDetector.Face.EULER_Z) + ")" + "Eyes Midpoint: ("+eyesMidPts[i].x + "," + eyesMidPts[i].y +")" ); } } catch (Exception e) { if (DEBUG) Log.e("Face", i + " is null"); } } } @Override protected void onDraw(Canvas canvas) { xRatio = getWidth()*1.0f / picWidth; yRatio = getHeight()*1.0f / picHeight; canvas.drawBitmap( sourceImage, null , new Rect(0,0,getWidth(),getHeight()),tmpPaint); for (int i = 0; i < eyesMidPts.length; i++) { if (eyesMidPts[i] != null) { pOuterBullsEye.setStrokeWidth(eyesDistance[i] /6); canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 2 , pOuterBullsEye); canvas.drawCircle(eyesMidPts[i].x*xRatio, eyesMidPts[i].y*yRatio, eyesDistance[i] / 6 , pInnerBullsEye); } } } 

}

+5
source

Source: https://habr.com/ru/post/1400847/


All Articles