davisking / dlib

A toolkit for making real world machine learning and data analysis applications in C++
http://dlib.net
Boost Software License 1.0
13.59k stars 3.38k forks source link

Compile with cmake face_landmark_detection to see landmark numbers #1585

Closed ManuelTS closed 5 years ago

ManuelTS commented 5 years ago

I changed your face_landmark_detection.cpp file to a bare minimum for better overview and I only want to have an output of the first image where not lines or circles are the overlay landmarks but rather the numbers of the landmarks themself. I trained successfully with the 194 features the shape predictor with the helen dataset which works perfectly on my changed version of your webcam_face_pose_ex.cpp. But I'm unable to compile the face_landmark_detection.cpp with this additional dependency:

#include <opencv2/imgproc.hpp>

needed to print numbers instead of lines or circles. My changed face_landmark_detection.cpp:

// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt

#include <iostream>
#include <opencv2/imgproc.hpp> // <------------ Makes linker problems
#include "dlib/opencv.h"
#include "dlib/image_processing/frontal_face_detector.h"
#include "dlib/image_processing.h"
#include "dlib/gui_widgets.h"
#include "dlib/image_io.h"

using namespace dlib;

int main(int argc, char** argv)
{
    try
    { // ../faces/helen/100032540_1.jpg
        frontal_face_detector detector = get_frontal_face_detector();
        shape_predictor sp;
        deserialize("../faces/helen/helen_shape_predictor_194_face_landmarks.dat") >> sp;

        image_window win;
        for (int i = 0; i < argc; ++i)
        {
            std::cout << "processing image " << argv[i] << std::endl;
            array2d<rgb_pixel> img;
            load_image(img, argv[i]);
            pyramid_up(img);

            std::vector<rectangle> dets = detector(img);
            std::cout << "Number of faces detected: " << dets.size() << std::endl;
            std::vector<full_object_detection> shapes;

            for (unsigned long j = 0; j < dets.size(); ++j)
            {
                full_object_detection shape = sp(img, dets[j]);
                std::cout << "number of parts: "<< shape.num_parts() << std::endl;
                std::cout << "pixel position of first part:  " << shape.part(0) << std::endl;
                std::cout << "pixel position of second part: " << shape.part(1) << std::endl;
                shapes.push_back(shape);

//----------------------Code i need #include <opencv2/imgproc.hpp> for with source:-----------------------------------------------------
                cv::Mat buff_img = dlib::toMat(img); // https://stackoverflow.com/questions/36711905/dlib-train-shape-predictor-ex-cpp/37880450#comment94164497_37880450

                for (int k = 0; k < 194; ++k) {
                  cv::putText(buff_img, std::to_string(k), cv::Point(shape.part(k).x(), shape.part(k).y()), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.5, cv::Scalar(255, 255, 0), 1, cv::LINE_AA);
                }

                save_png(img, "outImage.png");
            }
        }
    }
    catch (std::exception& e)
    {
        std::cout << "\nexception thrown!" << std::endl;
        std::cout << e.what() << std::endl;
    }
}

The compiler output for cmake .. && cmake --build . --config Release is:

Scanning dependencies of target face_landmark_detection_ex
[ 92%] Building CXX object CMakeFiles/face_landmark_detection_ex.dir/face_landmark_detection_ex.cpp.o
[ 93%] Linking CXX executable face_landmark_detection_ex
CMakeFiles/face_landmark_detection_ex.dir/face_landmark_detection_ex.cpp.o: In function `cv::Mat::~Mat()':
face_landmark_detection_ex.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x81): undefined reference to `cv::Mat::deallocate()'
face_landmark_detection_ex.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x70): undefined reference to `cv::fastFree(void*)'
CMakeFiles/face_landmark_detection_ex.dir/face_landmark_detection_ex.cpp.o: In function `main':
face_landmark_detection_ex.cpp:(.text.startup+0x26db): undefined reference to `cv::putText(cv::_InputOutputArray const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cv::Point_<int>, int, double, cv::Scalar_<double>, int, int, bool)'
face_landmark_detection_ex.cpp:(.text.startup+0x29d6): undefined reference to `cv::fastFree(void*)'
face_landmark_detection_ex.cpp:(.text.startup+0x2c13): undefined reference to `cv::Mat::updateContinuityFlag()'
face_landmark_detection_ex.cpp:(.text.startup+0x2f17): undefined reference to `cv::Mat::deallocate()'
face_landmark_detection_ex.cpp:(.text.startup+0x35f8): undefined reference to `cv::error(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, char const*, int)'
collect2: error: ld returned 1 exit status
CMakeFiles/face_landmark_detection_ex.dir/build.make:104: recipe for target 'face_landmark_detection_ex' failed
make[2]: *** [face_landmark_detection_ex] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/face_landmark_detection_ex.dir/all' failed
make[1]: *** [CMakeFiles/face_landmark_detection_ex.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

I know this is a standard problem and I googled a lot to figure this out but I cannot resolve it on my own :(

goldbattle commented 5 years ago

It looks like you are not properly linking the opencv shared library. You need to make sure you add the library .so files in addition to the header files. https://docs.opencv.org/3.1.0/db/df5/tutorial_linux_gcc_cmake.html

I would recommend just using the native functions in dlib for visualization: https://stackoverflow.com/a/37563733 http://dlib.net/imaging.html

ManuelTS commented 5 years ago

Your first link made me realize that instead of

  add_ex_link(face_landmark_detection_ex ${EXTRA_LIBS} ${OpenCV_LIBS})

I had

  add_ex_link(face_landmark_detection_ex ${EXTRA_LIBS})

in my CMakeLists.txt. I'm almost embarrassed how trivial this error was. Thank you very much!