【问题标题】:Android Face detection only works with drawables not with images from SD cardAndroid 人脸检测仅适用于可绘制对象,不适用于 SD 卡中的图像
【发布时间】:2012-03-15 03:36:05
【问题描述】:

所以我有代码可以在任何给定的图像文件中检测多达 10 个面孔,并将眼睛的位置和其他类似信息返回给我。因此,当我告诉它为我的项目使用存储在资源的可绘制文件夹中的图像文件时,它工作得很好。但是当我尝试从我从 sd 卡导入的位图中查找面孔时,它不会找到任何面孔。但这些是完全相同的图像。有任何想法吗?我的代码如下:

编辑: 经过进一步检查,我发现当我插入这行代码System.out.println("Row Bytes: " + sourceImage.getRowBytes()); 我得到drawable是352,SD卡图像是704。我认为这意味着drawable在.apk文件中被压缩,但SD卡图像显然不是。不确定这是否会产生任何影响。

 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);
                           }
                   }


           }  

}

【问题讨论】:

    标签: android


    【解决方案1】:

    好的,我相信我知道您的问题是什么。该设备无法将图像渲染为位图图像,因为它位于外部存储器中。人脸识别正在工作,只是没有进入画布。所有设备在我的 xoom 上都有渲染限制 (2048x2048) 我发现 here。当您将图像添加为资源时它起作用的原因是因为您的文件在构建 .apk 时被缩小(老实说我不确定它为什么这样做,但我留下了一点 println 用于测试,其他人可以更好地回答)。无论如何,我只是在您的代码查找面孔之后并尝试将位图渲染到画布之前通过除以 2 来缩放位图。现在一切似乎都很好。您可能想要调整您的面部指标,但它的功能。我希望这会有所帮助。

    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);
                    }
            }
    
    
    }
    

    }

    【讨论】:

    • 当我尝试运行你的代码时,我在这一行得到一个空指针异常: picWidth = sourceImage.getWidth();此外,我认为它实际上并没有找到人脸,因为当我运行代码时,它说即使是 SD 卡中的文件也没有检测到人脸
    • 我更改了外部存储文件路径。只需将其替换为您的文件路径即可。我相信这就是问题所在。因为它在我这边工作正常。 :-)
    • 我更改了它,但我忘记将 jpg 更改为 png.. 让我试试,因为我看了看,并不是我的程序不会打印它打印的最终产品,它实际上没有找到任何面孔
    • 哦,是的,我没有一张有 10 张面孔的照片,所以我把它改成了 1 张。对不起,我忘了我也改了。
    • 它显示图像但仍在 logcat 中我得到:“Face: 0 is null”,顺便说一下,它打印的尺寸是 176x144
    【解决方案2】:

    原来问题是相机拍摄的照片保存为PNG文件,如果使用JPG文件,人脸检测只能从SD卡成功工作。只需将文件转换为 JPG 即可。

    【讨论】:

      猜你喜欢
      • 2019-02-20
      • 2020-11-12
      • 2018-03-16
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      • 2013-09-22
      • 1970-01-01
      相关资源
      最近更新 更多