Open จดจำใบหน้า CV ไม่ถูกต้อง


13

ในแอพของฉันฉันกำลังพยายามจดจำใบหน้าในภาพที่ระบุโดยใช้ Open CV นี่เป็นครั้งแรกที่ฉันทำการฝึกอบรมหนึ่งภาพแล้วหลังจากการฝึกอบรมภาพนั้นถ้าฉันเรียกใช้การจดจำใบหน้าในภาพนั้นจะจดจำใบหน้านั้นได้สำเร็จ อย่างไรก็ตามเมื่อฉันหันไปใช้รูปภาพอื่นของการจดจำบุคคลเดียวกันไม่ทำงาน มันใช้งานได้กับภาพลักษณ์ที่ผ่านการฝึกอบรมดังนั้นคำถามของฉันคือฉันจะแก้ไขได้อย่างไร?

อัปเดต: สิ่งที่ฉันต้องการทำคือผู้ใช้ควรเลือกภาพของบุคคลจากที่เก็บข้อมูลและหลังจากการฝึกอบรมแล้วภาพที่เลือกฉันต้องการดึงภาพทั้งหมดจากที่เก็บซึ่งตรงกับรูปหน้าของภาพที่ฉันฝึก

นี่คือคลาสกิจกรรมของฉัน:

public class MainActivity extends AppCompatActivity {
    private Mat rgba,gray;
    private CascadeClassifier classifier;
    private MatOfRect faces;
    private ArrayList<Mat> images;
    private ArrayList<String> imagesLabels;
    private Storage local;
    ImageView mimage;
    Button prev,next;
    ArrayList<Integer> imgs;
    private int label[] = new int[1];
    private double predict[] = new double[1];
    Integer pos = 0;
    private String[] uniqueLabels;
    FaceRecognizer recognize;
    private boolean trainfaces() {
        if(images.isEmpty())
            return false;
        List<Mat> imagesMatrix = new ArrayList<>();
        for (int i = 0; i < images.size(); i++)
            imagesMatrix.add(images.get(i));
        Set<String> uniqueLabelsSet = new HashSet<>(imagesLabels); // Get all unique labels
        uniqueLabels = uniqueLabelsSet.toArray(new String[uniqueLabelsSet.size()]); // Convert to String array, so we can read the values from the indices

        int[] classesNumbers = new int[uniqueLabels.length];
        for (int i = 0; i < classesNumbers.length; i++)
            classesNumbers[i] = i + 1; // Create incrementing list for each unique label starting at 1
        int[] classes = new int[imagesLabels.size()];
        for (int i = 0; i < imagesLabels.size(); i++) {
            String label = imagesLabels.get(i);
            for (int j = 0; j < uniqueLabels.length; j++) {
                if (label.equals(uniqueLabels[j])) {
                    classes[i] = classesNumbers[j]; // Insert corresponding number
                    break;
                }
            }
        }
        Mat vectorClasses = new Mat(classes.length, 1, CvType.CV_32SC1); // CV_32S == int
        vectorClasses.put(0, 0, classes); // Copy int array into a vector

        recognize = LBPHFaceRecognizer.create(3,8,8,8,200);
        recognize.train(imagesMatrix, vectorClasses);
        if(SaveImage())
            return true;

        return false;
    }
    public void cropedImages(Mat mat) {
        Rect rect_Crop=null;
        for(Rect face: faces.toArray()) {
            rect_Crop = new Rect(face.x, face.y, face.width, face.height);
        }
        Mat croped = new Mat(mat, rect_Crop);
        images.add(croped);
    }
    public boolean SaveImage() {
        File path = new File(Environment.getExternalStorageDirectory(), "TrainedData");
        path.mkdirs();
        String filename = "lbph_trained_data.xml";
        File file = new File(path, filename);
        recognize.save(file.toString());
        if(file.exists())
            return true;
        return false;
    }

    private BaseLoaderCallback callbackLoader = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch(status) {
                case BaseLoaderCallback.SUCCESS:
                    faces = new MatOfRect();

                    //reset
                    images = new ArrayList<Mat>();
                    imagesLabels = new ArrayList<String>();
                    local.putListMat("images", images);
                    local.putListString("imagesLabels", imagesLabels);

                    images = local.getListMat("images");
                    imagesLabels = local.getListString("imagesLabels");

                    break;
                default:
                    super.onManagerConnected(status);
                    break;
            }
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        if(OpenCVLoader.initDebug()) {
            Log.i("hmm", "System Library Loaded Successfully");
            callbackLoader.onManagerConnected(BaseLoaderCallback.SUCCESS);
        } else {
            Log.i("hmm", "Unable To Load System Library");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, callbackLoader);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        prev = findViewById(R.id.btprev);
        next = findViewById(R.id.btnext);
        mimage = findViewById(R.id.mimage);
       local = new Storage(this);
       imgs = new ArrayList();
       imgs.add(R.drawable.jonc);
       imgs.add(R.drawable.jonc2);
       imgs.add(R.drawable.randy1);
       imgs.add(R.drawable.randy2);
       imgs.add(R.drawable.imgone);
       imgs.add(R.drawable.imagetwo);
       mimage.setBackgroundResource(imgs.get(pos));
        prev.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(pos!=0){
                  pos--;
                  mimage.setBackgroundResource(imgs.get(pos));
                }
            }
        });
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(pos<5){
                    pos++;
                    mimage.setBackgroundResource(imgs.get(pos));
                }
            }
        });
        Button train = (Button)findViewById(R.id.btn_train);
        train.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public void onClick(View view) {
                rgba = new Mat();
                gray = new Mat();
                Mat mGrayTmp = new Mat();
                Mat mRgbaTmp = new Mat();
                classifier = FileUtils.loadXMLS(MainActivity.this);
                Bitmap icon = BitmapFactory.decodeResource(getResources(),
                        imgs.get(pos));
                Bitmap bmp32 = icon.copy(Bitmap.Config.ARGB_8888, true);
                Utils.bitmapToMat(bmp32, mGrayTmp);
                Utils.bitmapToMat(bmp32, mRgbaTmp);
                Imgproc.cvtColor(mGrayTmp, mGrayTmp, Imgproc.COLOR_BGR2GRAY);
                Imgproc.cvtColor(mRgbaTmp, mRgbaTmp, Imgproc.COLOR_BGRA2RGBA);
                /*Core.transpose(mGrayTmp, mGrayTmp); // Rotate image
                Core.flip(mGrayTmp, mGrayTmp, -1); // Flip along both*/
                gray = mGrayTmp;
                rgba = mRgbaTmp;
                Imgproc.resize(gray, gray, new Size(200,200.0f/ ((float)gray.width()/ (float)gray.height())));
                if(gray.total() == 0)
                    Toast.makeText(getApplicationContext(), "Can't Detect Faces", Toast.LENGTH_SHORT).show();
                classifier.detectMultiScale(gray,faces,1.1,3,0|CASCADE_SCALE_IMAGE, new Size(30,30));
                if(!faces.empty()) {
                    if(faces.toArray().length > 1)
                        Toast.makeText(getApplicationContext(), "Mutliple Faces Are not allowed", Toast.LENGTH_SHORT).show();
                    else {
                        if(gray.total() == 0) {
                            Log.i("hmm", "Empty gray image");
                            return;
                        }
                        cropedImages(gray);
                        imagesLabels.add("Baby");
                        Toast.makeText(getApplicationContext(), "Picture Set As Baby", Toast.LENGTH_LONG).show();
                        if (images != null && imagesLabels != null) {
                            local.putListMat("images", images);
                            local.putListString("imagesLabels", imagesLabels);
                            Log.i("hmm", "Images have been saved");
                            if(trainfaces()) {
                                images.clear();
                                imagesLabels.clear();
                            }
                        }
                    }
                }else {
                   /* Bitmap bmp = null;
                    Mat tmp = new Mat(250, 250, CvType.CV_8U, new Scalar(4));
                    try {
                        //Imgproc.cvtColor(seedsImage, tmp, Imgproc.COLOR_RGB2BGRA);
                        Imgproc.cvtColor(gray, tmp, Imgproc.COLOR_GRAY2RGBA, 4);
                        bmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
                        Utils.matToBitmap(tmp, bmp);
                    } catch (CvException e) {
                        Log.d("Exception", e.getMessage());
                    }*/
                    /*    mimage.setImageBitmap(bmp);*/
                    Toast.makeText(getApplicationContext(), "Unknown Face", Toast.LENGTH_SHORT).show();
                }
            }
        });
        Button recognize = (Button)findViewById(R.id.btn_recognize);
        recognize.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(loadData())
                    Log.i("hmm", "Trained data loaded successfully");
                rgba = new Mat();
                gray = new Mat();
                faces = new MatOfRect();
                Mat mGrayTmp = new Mat();
                Mat mRgbaTmp = new Mat();
                classifier = FileUtils.loadXMLS(MainActivity.this);
                Bitmap icon = BitmapFactory.decodeResource(getResources(),
                        imgs.get(pos));
                Bitmap bmp32 = icon.copy(Bitmap.Config.ARGB_8888, true);
                Utils.bitmapToMat(bmp32, mGrayTmp);
                Utils.bitmapToMat(bmp32, mRgbaTmp);
                Imgproc.cvtColor(mGrayTmp, mGrayTmp, Imgproc.COLOR_BGR2GRAY);
                Imgproc.cvtColor(mRgbaTmp, mRgbaTmp, Imgproc.COLOR_BGRA2RGBA);
                /*Core.transpose(mGrayTmp, mGrayTmp); // Rotate image
                Core.flip(mGrayTmp, mGrayTmp, -1); // Flip along both*/
                gray = mGrayTmp;
                rgba = mRgbaTmp;
                Imgproc.resize(gray, gray, new Size(200,200.0f/ ((float)gray.width()/ (float)gray.height())));
                if(gray.total() == 0)
                    Toast.makeText(getApplicationContext(), "Can't Detect Faces", Toast.LENGTH_SHORT).show();
                classifier.detectMultiScale(gray,faces,1.1,3,0|CASCADE_SCALE_IMAGE, new Size(30,30));
                if(!faces.empty()) {
                    if(faces.toArray().length > 1)
                        Toast.makeText(getApplicationContext(), "Mutliple Faces Are not allowed", Toast.LENGTH_SHORT).show();
                    else {
                        if(gray.total() == 0) {
                            Log.i("hmm", "Empty gray image");
                            return;
                        }
                        recognizeImage(gray);
                    }
                }else {
                    Toast.makeText(getApplicationContext(), "Unknown Face", Toast.LENGTH_SHORT).show();
                }
            }
        });


    }
    private void recognizeImage(Mat mat) {
        Rect rect_Crop=null;
        for(Rect face: faces.toArray()) {
            rect_Crop = new Rect(face.x, face.y, face.width, face.height);
        }
        Mat croped = new Mat(mat, rect_Crop);
        recognize.predict(croped, label, predict);
        int indice = (int)predict[0];
        Log.i("hmmcheck:",String.valueOf(label[0])+" : "+String.valueOf(indice));
        if(label[0] != -1 && indice < 125)
            Toast.makeText(getApplicationContext(), "Welcome "+uniqueLabels[label[0]-1]+"", Toast.LENGTH_SHORT).show();
        else
            Toast.makeText(getApplicationContext(), "You're not the right person", Toast.LENGTH_SHORT).show();
    }
    private boolean loadData() {
        String filename = FileUtils.loadTrained();
        if(filename.isEmpty())
            return false;
        else
        {
            recognize.read(filename);
            return true;
        }
    }
}

ไฟล์ของฉัน Utils Class:

   public class FileUtils {
        private static String TAG = FileUtils.class.getSimpleName();
        private static boolean loadFile(Context context, String cascadeName) {
            InputStream inp = null;
            OutputStream out = null;
            boolean completed = false;
            try {
                inp = context.getResources().getAssets().open(cascadeName);
                File outFile = new File(context.getCacheDir(), cascadeName);
                out = new FileOutputStream(outFile);

                byte[] buffer = new byte[4096];
                int bytesread;
                while((bytesread = inp.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesread);
                }

                completed = true;
                inp.close();
                out.flush();
                out.close();
            } catch (IOException e) {
                Log.i(TAG, "Unable to load cascade file" + e);
            }
            return completed;
        }
        public static CascadeClassifier loadXMLS(Activity activity) {


            InputStream is = activity.getResources().openRawResource(R.raw.lbpcascade_frontalface);
            File cascadeDir = activity.getDir("cascade", Context.MODE_PRIVATE);
            File mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface_improved.xml");
            FileOutputStream os = null;
            try {
                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();

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


            return new CascadeClassifier(mCascadeFile.getAbsolutePath());
        }
        public static String loadTrained() {
            File file = new File(Environment.getExternalStorageDirectory(), "TrainedData/lbph_trained_data.xml");

            return file.toString();
        }
    }

ภาพเหล่านี้เป็นภาพที่ฉันพยายามเปรียบเทียบที่นี่ใบหน้าของบุคคลยังคงเหมือนเดิมในการจดจำว่ามันไม่เข้าคู่กัน! ภาพ 1 ภาพที่ 2


เมื่อฉันสร้างการมอบหมายงานปีสุดท้ายสำหรับระบบการเข้างานอัตโนมัติฉันใช้ 8-10 ภาพของฉันด้วยสภาพท่าทางและสภาพแสงที่แตกต่างกันเล็กน้อยเพื่อฝึกฝนตัวแยกประเภท
ZdaR

คุณสามารถพลิกแผ่นภาพฝึกในแนวนอนเพื่อจัดการกับความต้องการนั้น
nfl-x

@ nfl-x การพลิกภาพจะไม่แก้ปัญหาความถูกต้องเราต้องการสิ่งที่ดีกว่าคำตอบล่าสุดใน tenorflow ดูเหมือนว่าไม่เป็นไร แต่มีข้อมูลหรือแบบฝึกหัดไม่เพียงพอในการใช้งานสำหรับ android ดังนั้นการคาดเดาที่ดีที่สุดของเราคือ เช่นที่ผู้เชี่ยวชาญสามารถแทรกแซงและให้บริการโซลูชั่นที่เหมาะสมสำหรับ Android
นาย Patel

คำตอบ:


5

ปรับปรุง

ตามการแก้ไขใหม่ในคำถามคุณต้องมีวิธีในการระบุผู้คนใหม่ ๆ ในทันทีซึ่งอาจไม่มีรูปภาพในระหว่างขั้นตอนการฝึกอบรมของแบบจำลอง งานเหล่านี้จะเรียกว่าไม่กี่เรียนรู้การถ่ายภาพ สิ่งนี้คล้ายกับข้อกำหนดของหน่วยงานข่าวกรอง / ตำรวจในการค้นหาเป้าหมายโดยใช้ภาพจากกล้องวงจรปิด ในฐานะที่เป็นมักจะมีไม่เพียงพอของภาพเป้าหมายที่เฉพาะเจาะจงในระหว่างการฝึกอบรมที่พวกเขาใช้รูปแบบเช่นFaceNet ฉันขอแนะนำให้อ่านกระดาษ แต่ฉันอธิบายไฮไลท์บางอย่างของที่นี่:

  • โดยทั่วไปแล้วเลเยอร์สุดท้ายของลักษณนามคือ * 1 เวกเตอร์ที่มี n-1 ขององค์ประกอบเกือบเท่ากับศูนย์และหนึ่งใกล้กับ 1 องค์ประกอบใกล้กับ 1 กำหนดการทำนายของลักษณนามเกี่ยวกับฉลากของอินพุต สถาปัตยกรรม CNN ทั่วไป
  • ผู้เขียนคิดว่าถ้าพวกเขาฝึกอบรมเครือข่ายลักษณนามโดยมีฟังก์ชั่นการสูญเสียเฉพาะในชุดข้อมูลขนาดใหญ่ของใบหน้าคุณสามารถใช้ผลลัพธ์เลเยอร์กึ่งสุดท้ายเป็นตัวแทนของใบหน้าใด ๆ โดยไม่คำนึงถึงมันอยู่ในชุดฝึกอบรมหรือไม่ ผู้เขียนเรียกว่าการฝังใบหน้าเวกเตอร์นี้
  • ผลลัพธ์ก่อนหน้านี้หมายความว่าเมื่อใช้แบบจำลอง FaceNet ที่ผ่านการฝึกอบรมเป็นอย่างดีคุณสามารถสรุปใบหน้าใด ๆ ลงในเวกเตอร์ได้ คุณลักษณะที่น่าสนใจมากของวิธีการนี้คือเวกเตอร์ของใบหน้าของบุคคลเฉพาะในมุมที่แตกต่างกัน / ตำแหน่ง / รัฐมีความใกล้ชิดในพื้นที่ euclidian (คุณสมบัตินี้มีการบังคับใช้โดยฟังก์ชั่นการสูญเสียที่ผู้เขียนเลือก)ป้อนคำอธิบายรูปภาพที่นี่
  • โดยสรุปคุณมีโมเดลที่รับใบหน้าเป็นอินพุตและส่งคืนเวกเตอร์ เวกเตอร์ที่อยู่ใกล้กันนั้นมีแนวโน้มที่จะเป็นของคนคนเดียวกันมาก (สำหรับการตรวจสอบว่าคุณสามารถใช้ KNN หรือระยะทางแบบยุคลิวง่าย ๆ )

หนึ่งในการดำเนินงานของ FaceNet สามารถพบได้ที่นี่ ฉันขอแนะนำให้คุณลองเรียกใช้บนคอมพิวเตอร์ของคุณเพื่อทำความรู้จักกับสิ่งที่คุณกำลังทำอยู่ หลังจากนั้นอาจเป็นการดีที่สุดที่จะทำสิ่งต่อไปนี้:

  1. แปลงโมเดล FaceNet ที่กล่าวถึงในที่เก็บเป็นเวอร์ชัน tflite ( บล็อกนี้อาจช่วยได้)
  2. สำหรับแต่ละภาพที่ส่งโดยผู้ใช้ใช้ Face API เพื่อแยกใบหน้า
  3. ใช้โมเดลย่อเล็กสุดในแอปของคุณเพื่อให้ใบหน้าของงานแต่งงานที่แยกออกมา
  4. ประมวลผลภาพทั้งหมดในแกลเลอรี่ของผู้ใช้รับเวกเตอร์สำหรับใบหน้าในภาพถ่าย
  5. จากนั้นเปรียบเทียบแต่ละเวกเตอร์ที่พบในขั้นตอนที่ 4 กับแต่ละเวกเตอร์ที่พบในขั้นตอนที่ 3 เพื่อให้ได้ผลลัพธ์ที่ตรงกัน

คำตอบเดิม

คุณได้พบกับหนึ่งในความท้าทายที่แพร่หลายที่สุดของการเรียนรู้ของเครื่อง: การมีส่วนเกิน การตรวจจับใบหน้าและการจดจำเป็นพื้นที่ขนาดใหญ่ของการวิจัยด้วยตนเองและเกือบทุกรูปแบบที่ถูกต้องสมเหตุสมผลกำลังใช้การเรียนรู้แบบลึก โปรดทราบว่าแม้การตรวจจับใบหน้าอย่างแม่นยำนั้นไม่ง่ายอย่างที่คิดอย่างไรก็ตามในขณะที่คุณทำบน Android คุณสามารถใช้Face APIสำหรับงานนี้ได้ (เทคนิคขั้นสูงอื่น ๆ เพิ่มเติมเช่นMTCNNช้าเกินไป / ยากที่จะปรับใช้ในโทรศัพท์มือถือ) มันแสดงให้เห็นว่าเพียงแค่ให้อาหารนางแบบด้วยภาพถ่ายใบหน้าที่มีเสียงรบกวนพื้นหลังหรือคนหลายคนที่อยู่ภายในไม่ทำงาน ดังนั้นคุณไม่สามารถข้ามขั้นตอนนี้ได้

หลังจากได้รับการตัดแต่งใบหน้าที่ดีของเป้าหมายผู้สมัครจากพื้นหลังคุณต้องเอาชนะความท้าทายในการจดจำใบหน้าที่ตรวจพบ อีกครั้งแบบจำลองที่มีความสามารถทั้งหมดเพื่อความรู้ที่ดีที่สุดของฉันกำลังใช้เครือข่ายประสาทเทียม / การเรียนรู้เชิงลึก การใช้งานบนโทรศัพท์มือถือเป็นเรื่องที่ท้าทาย แต่ด้วยTensorflow Liteคุณสามารถย่อขนาดและเรียกใช้ภายในแอปของคุณ โครงการเกี่ยวกับการจดจำใบหน้าบนโทรศัพท์ Android ที่ฉันได้ทำงานอยู่ที่นี่คุณสามารถตรวจสอบได้ โปรดทราบว่าโมเดลที่ดีควรได้รับการฝึกฝนในหลาย ๆ กรณีของข้อมูลที่ติดป้ายกำกับอย่างไรก็ตามมีโมเดลมากมายที่ผ่านการฝึกอบรมแล้วในชุดข้อมูลขนาดใหญ่ของใบหน้าหรืองานจดจำภาพอื่น ๆ เพื่อปรับแต่งและใช้ความรู้ที่มีอยู่แล้วการเรียนรู้การถ่ายโอน , สำหรับการเริ่มต้นอย่างรวดเร็วในการตรวจหาวัตถุและการเรียนรู้การถ่ายโอนที่เกี่ยวข้องอย่างใกล้ชิดกับกรณีของคุณตรวจสอบนี้โพสต์บล็อก

โดยรวมคุณจะต้องได้รับอินสแตนซ์จำนวนมากของใบหน้าที่คุณต้องการตรวจจับรวมถึงรูปใบหน้าจำนวนมากของคนที่คุณไม่สนใจแล้วคุณต้องฝึกโมเดลตามทรัพยากรที่กล่าวถึงข้างต้นแล้วคุณต้อง ใช้ TensorFlow lite เพื่อลดขนาดและฝังไว้ในแอปของคุณ สำหรับแต่ละเฟรมจากนั้นคุณเรียก android Face API และฟีด (ใบหน้าที่ตรวจพบ) ลงในโมเดลและระบุบุคคล

ขึ้นอยู่กับระดับความอดทนต่อความล่าช้าและจำนวนชุดฝึกอบรมและจำนวนเป้าหมายคุณสามารถได้รับผลลัพธ์ต่าง ๆ อย่างไรก็ตามความแม่นยำ% 90 + นั้นสามารถทำได้ง่ายถ้าคุณมีคนเป้าหมายเพียงไม่กี่คน


ฉันไม่ต้องการใช้การเชื่อมต่อเครือข่ายในแอพของฉันดังนั้น Google คลาวด์วิชั่นจึงไม่เป็นปัญหา แต่ดูเหมือนว่าเทมเพลตไลต์เทนเซอร์นั้นน่าสนใจมากใช่ไหม และถ้าคุณสามารถให้ตัวอย่างการทำงานของมันฉันจะขอบคุณมัน! ขอบคุณ
R.Coder

คำตอบที่ยอดเยี่ยมโดยวิธี!
R.Coder

มันว่าง. ตรวจสอบสิ่งนี้เพื่อเป็นตัวอย่างการทำงาน เราสามารถระบุใบหน้าของคน 225 คนโดยไม่ต้องใช้การเชื่อมต่อเครือข่ายที่มีความแม่นยำสูงมากแม้ว่าจะมีข้อผิดพลาดบางอย่างในด้านประสบการณ์ของผู้ใช้ แต่นั่นควรเป็นการเริ่มต้นที่ดี
Farzad Vertigo

โอเคฉันจะลองดู
R.Coder

1
มันใช้งานได้ !!!! ในที่สุดฉันก็ดึงรูปแบบใบหน้าสุทธินั้นและมีความแม่นยำสูงกว่า 80% ในภาพที่ผ่านการฝึกอบรมเพียงครั้งเดียว แต่ความซับซ้อนของเวลานั้นใหญ่มากจริงๆ !! สำหรับการเปรียบเทียบภาพสองภาพต้องใช้เวลาอย่างน้อย 5 ถึง 6 วินาทีในการลดความคิดนั้น?
R.Coder

2

ถ้าฉันเข้าใจถูกต้องคุณกำลังฝึกตัวจําแนกด้วยภาพเดียว ในกรณีนั้นภาพหนึ่งรูปนี้คือทุกสิ่งที่ตัวจําแนกจะจำได้ คุณจะต้องมีชุดฝึกอบรมที่ใหญ่ขึ้นอย่างเห็นได้ชัดซึ่งแสดงภาพคนคนเดียวกันอย่างน้อย 5 หรือ 10 ภาพที่ต่างกันอย่างน้อยที่สุด


คุณมีตัวอย่างเกี่ยวกับวิธีการทำเช่นนั้นหรือไม่?
R.Coder

ใช่ฉันกำลังจดจำใบหน้าในรูปภาพนิ่งเดียว
R.Coder

ดูตัวอย่างวิธีการใช้ที่นี่ได้ที่train(): docs.opencv.org/3.4/dd/d65/…
Florian Echtler

คำตอบนี้ไม่ได้ช่วยถ้าคุณสามารถให้ตัวอย่างรหัสที่เกี่ยวข้องกับ Android มันจะดีกว่า!
R.Coder

0

1) เปลี่ยนค่าขีด จำกัด ขณะเริ่มต้น LBPHrecognizer เป็น -> LBPHFaceRecognizer (1, 8, 8, 8, 8, 100)

2) ฝึกฝนใบหน้าแต่ละหน้าด้วยภาพอย่างน้อย 2-3 ภาพเนื่องจากตัวจดจำเหล่านี้ทำงานบนการเปรียบเทียบเป็นหลัก

3) ตั้งค่าขีดจำกัดความแม่นยำขณะรับรู้ ทำสิ่งนี้:

//predicting result
// LoadData is a static class that contains trained recognizer
// _result is the gray frame image captured by the camera
LBPHFaceRecognizer.PredictionResult ER = LoadData.recog.Predict(_result);
int temp_result = ER.Label;

imageBox1.SizeMode = PictureBoxSizeMode.StretchImage;
imageBox1.Image = _result.Mat;

//Displaying predicted result on screen
// LBPH returns -1 if face is recognized
if ((temp_result != -1) && (ER.Distance < 55)){  
     //I get best accuracy at 55, you should try different values to determine best results
     // Do something with detected image
}

คุณสามารถแก้ไขรหัสปัจจุบันของฉันและแสดงตัวอย่างการทำงานใน java ได้หรือไม่
R.Coder
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.