如何在ubuntu上的opencv和dlib上裁剪图像

时间:2016-09-06 03:48:00

标签: c++ opencv ubuntu dlib

我想在ubuntu上使用c ++在opencv和dlib上执行这些操作。

  1. 使用dlib检测人脸(我已经做过了。)
  2. 仅裁剪嘴部周围的图像。
  3. 这是我的代码。它基于dlib示例代码。

    #include <dlib/image_processing/frontal_face_detector.h>
    #include <dlib/image_processing/render_face_detections.h>
    #include <dlib/image_processing.h>
    #include <dlib/gui_widgets.h>
    #include <dlib/image_io.h>
    #include <iostream>
    #include <opencv2/opencv.hpp>
    #include <highgui.h>
    
    
    using namespace dlib;
    using namespace std;
    
    // ----------------------------------------------------------------------------------------
    
    int main(int argc, char** argv)
    {  
        try
        {
            // This example takes in a shape model file and then a list of images to
            // process.  We will take these filenames in as command line arguments.
            // Dlib comes with example images in the examples/faces folder so give
            // those as arguments to this program.
            if (argc == 1)
            {
                cout << "Call this program like this:" << endl;
                cout << "./face_landmark_detection_ex shape_predictor_68_face_landmarks.dat faces/*.jpg" << endl;
                cout << "\nYou can get the shape_predictor_68_face_landmarks.dat file from:\n";
                cout << "http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2" << endl;
                return 0;
            }
    
            // We need a face detector.  We will use this to get bounding boxes for
            // each face in an image.
            frontal_face_detector detector = get_frontal_face_detector();
            // And we also need a shape_predictor.  This is the tool that will predict face
            // landmark positions given an image and face bounding box.  Here we are just
            // loading the model from the shape_predictor_68_face_landmarks.dat file you gave
            // as a command line argument.
            shape_predictor sp;
            deserialize(argv[1]) >> sp;
        cv::Mat cimg = cv::imread(argv[1]);
    
    
            image_window win, win_faces;
            // Loop over all the images provided on the command line.
            for (int i = 2; i < argc; ++i)
            {
                cout << "processing image " << argv[i] << endl;
                array2d<rgb_pixel> img;
                load_image(img, argv[i]);
    /*
                // Make the image larger so we can detect small faces.
                pyramid_up(img);
    */
                // Now tell the face detector to give us a list of bounding boxes
                // around all the faces in the image.
                std::vector<rectangle> dets = detector(img);
                cout << "Number of faces detected: " << dets.size() << endl;
    
                // Now we will go ask the shape_predictor to tell us the pose of
                // each face we detected.
                std::vector<full_object_detection> shapes;
                for (unsigned long j = 0; j < dets.size(); ++j)
                {
                    full_object_detection shape = sp(img, dets[j]);
                    cout << "number of parts: "<< shape.num_parts() << endl;
                    cout << "pixel position of first part:  " << shape.part(0) << endl;
                    cout << "pixel position of second part: " << shape.part(1) << endl;
                    // You get the idea, you can get all the face part locations if
                    // you want them.  Here we just store them in shapes so we can
                    // put them on the screen.
                    shapes.push_back(shape);
                }
    
            // Crop the original image to the defined ROI */
            cv::Rect roi;
            roi.x = 0;
            roi.y = 0;
            roi.width = 200;
            roi.height = 200;
    
            cv::Mat crop = cimg(roi);
            cv::imshow("crop", crop);
    
                // Now let's view our face poses on the screen.
    /*
                win.clear_overlay();
                win.set_image(img);
                win.add_overlay(render_face_detections(shapes));
    
                // We can also extract copies of each face that are cropped, rotated upright,
                // and scaled to a standard size as shown here:
                //dlib::array<array2d<rgb_pixel> > face_chips;
                //extract_image_chips(img, get_face_chip_details(shapes), face_chips);
                //win_faces.set_image(tile_images(face_chips));
    */
    
                cout << "Hit enter to process the next image..." << endl;
                cin.get();
            }
        }
        catch (exception& e)
        {
            cout << "\nexception thrown!" << endl;
            cout << e.what() << endl;
        }
    }
    

    但它给了我这个错误。

    OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file /home/bigadmin/opencv-3.1.0/modules/core/src/matrix.cpp, line 508
    
    exception thrown!
    /home/bigadmin/opencv-3.1.0/modules/core/src/matrix.cpp:508: error: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function Mat
    

    请教我解决这个问题的解决方案。

    感谢。

1 个答案:

答案 0 :(得分:2)

您的代码中有很多错误:

  1. cv :: Mat cimg = cv :: imread(argv [1]); - argv [1]是探测器文件,而不是图像 - 你会得到空图像,这就是你的程序崩溃的原因
  2. 你没有迭代图像。尝试这样的事情:

    for (int i = 2; i < argc; ++i)
    {
        cout << "processing image " << argv[i] << endl;
        cv::Mat cvimg = cv::imgread(argv[i]);
        dlib::cv_image<rgb_pixel> img(cvimg);
    ...
    

    在这里,您只能阅读一次文件,并且能够检测到面孔

  3. 你应该根据人脸探测器功能指定裁剪区域(甚至更好 - 基于形状预测器)

  4. ...

    std::vector<rectangle> dets = detector(img);
    

    这里dets中的每个项目都是一个矩形,描述了面部,你可以像这样裁剪:

    dlib::rectangle r = dets[j];
    cv::Rect roi(r.left(), r.top(), r.width(), r.height());
    cv::Mat face = cvimg(roi);
    

    但它将是全脸形象。如果你想只裁剪嘴,你应该使用形状预测器的输出(没有测试 - 请检查是否编译好):

    full_object_detection shape = sp(img, dets[j]);
    auto mouth_left = shape.part(45);
    auto mouth_right = shape.part(54);
    unsigned long mouth_width = (mouth_right - mouth_left).length();
    double padding = 0.2;
    cv::Rect roi(mouth_left.x() - mouth_width * padding, mouth_left.y() - mouth_width*0.5, mouth_width * (1 + padding * 2), mouth_width);
    cv::Mat mouth = cvimg(roi);
    

    这会产生未对齐的嘴巴图像