Problem with undefine reference to cv::CascadeClassifier



  • This is the first time I try to practice others' project (which is shared free on the Stanford education website). My versions is Qt 5.5.0 and mingw 4.92
    The .pro code

    #-------------------------------------------------
    #
    # Project created by QtCreator 2015-08-18T20:12:30
    #
    #-------------------------------------------------
    
    QT       += core
    
    QT       -= gui
    
    TARGET = HomoPyramidBlend
    CONFIG   += console
    CONFIG   -= app_bundle
    
    TEMPLATE = app
    
    
    SOURCES += main.cpp
    
    
    
    # them duong dan openCV
    win32{
    INCLUDEPATH += "C:/ti/opencv/include/"
    INCLUDEPATH += "C:/ti/opencv/include/opencv/"
    LIBS += -LC:/ti/opencv/x86/mingw/lib \
        -lopencv_core300.dll \
        -lopencv_features2d300.dll \
        -lopencv_flann300.dll \
        -lopencv_hal300 \
        -lopencv_highgui300.dll \
        -lopencv_imgcodecs300.dll \
        -lopencv_imgproc300.dll \
        -lopencv_ml300.dll \
        -lopencv_calib3d300.dll \
        -lopencv_video300.dll \
        -lopencv_videoio300.dll \
        -lopencv_photo300.dll
    }
    
    DISTFILES += \
        lbpcascade_frontalface.xml \
        photo 1.JPG \
        photo 2.JPG \
        photo 3.JPG
    

    The .cpp code (rather long)

    #include <QCoreApplication>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include "opencv2/opencv.hpp"
    using namespace cv;
    using namespace std;
    
    
    //function to find all faces using open CV's Haar cascade library
    Mat findAllFaces(Mat img, CascadeClassifier face_cascade, vector<int>& faceWidth, vector<int>& faceCenters_x, vector<int>& faceCenters_y);
    //function to get image number based on where we drag the cursor on the bar to select a photo for a face
    void myCallbackForImageNumChange(int pos, void* userdata);
    int iImgNum;
    
    int main(){
        vector<string> inputImagePaths;//Stores all the image paths
        //Here give the new image names that you want to combine
        inputImagePaths.push_back("g3.jpg");
        inputImagePaths.push_back("g2.jpg");
        inputImagePaths.push_back("g1.jpg");
        inputImagePaths.push_back("g4.jpg");
        inputImagePaths.push_back("g5.jpg");
        string outputImagePath="faces_final.jpg";//Stores final result path
        vector<Mat> images;
    
        //Reads the images
        for(int i=0;i<inputImagePaths.size();i++){
                    Mat I=imread(inputImagePaths[i],CV_LOAD_IMAGE_COLOR);
                    resize(I,I,Size(816,612),0,0,1);
                    images.push_back(I);
                }
    
        int num_of_photos=images.size();//Stores number of images taken
        int reference_image_num=0;//Stores the image number that is taken as the reference image, in which the faces are replaced
    
    
        string face_cascade_name = "lbpcascade_frontalface.xml";
        CascadeClassifier face_cascade;
        //-- 1. Load the cascades
        //Returns error if loading Haar cascade library fails
        if( !face_cascade.load( face_cascade_name ) ) {
            cout<<"--(!)Error loading\n";
            return -1;
        }
    
        //stores the width and center coordinates of the detected face region for all faces in any one image
        vector<int> faceWidth,faceCenters_x,faceCenters_y;
        //stores the width and center coordinates of the detected face region for all faces in all images
        vector<vector<int> >faceWidth_all_photos,faceCenters_x_all_photos,faceCenters_y_all_photos;
        vector<Mat> images_with_faces;
        for(int num_photos=0;num_photos<num_of_photos;num_photos++){
            Mat refImg = images.at(num_photos);
            //function to find all faces using open CV's Haar cascade library
            Mat img_display=findAllFaces(refImg, face_cascade, faceWidth, faceCenters_x,faceCenters_y);
            images_with_faces.push_back(img_display);
            faceWidth_all_photos.push_back(faceWidth);
            faceCenters_x_all_photos.push_back(faceCenters_x);
            faceCenters_y_all_photos.push_back(faceCenters_y);
        }
    
        int num_of_faces=faceWidth_all_photos[reference_image_num].size();//Stores number of faces in each photo
    
        vector<int> image_number;//Image number for chosen face of each person
    
        for(int num_faces=0;num_faces<num_of_faces;num_faces++){
            //For each face crop each photo to get the detected face
            Rect roi(faceCenters_x_all_photos[0].at(num_faces)-100, faceCenters_y_all_photos[0].at(num_faces)-100,200,200);
            Mat faces_cropped_all_photos=images[0](roi);
            for(int num_photos=1;num_photos<num_of_photos;num_photos++){
                Rect roi(faceCenters_x_all_photos[num_photos].at(num_faces)-100, faceCenters_y_all_photos[num_photos].at(num_faces)-100,200,200);
                //Horizontally concatenate each faces's all photos
                hconcat(faces_cropped_all_photos,images[num_photos](roi),faces_cropped_all_photos);
            }
            //Interface for the user to choose the faces
            imshow("Select one of these faces by dragging the bar and then press any key",faces_cropped_all_photos);
            createTrackbar("Image Num", "Select one of these faces by dragging the bar and then press any key", &iImgNum, num_of_photos-1, myCallbackForImageNumChange);
            waitKey(0);
            image_number.push_back(iImgNum);
        }
    
        //stores the width and center coordinates of the chosen faces for all people in all images
        vector<int>faceWidth_final,faceCenters_x_final,faceCenters_y_final;
        for(int num_faces=0;num_faces<num_of_faces;num_faces++){
                faceWidth_final.push_back(faceWidth_all_photos[image_number[num_faces]].at(num_faces));
                faceCenters_x_final.push_back(faceCenters_x_all_photos[image_number[num_faces]].at(num_faces));
                faceCenters_y_final.push_back(faceCenters_y_all_photos[image_number[num_faces]].at(num_faces));
        }
    
        vector<int> center_x,center_y;
        vector<int> side;
        center_x=faceCenters_x_final;//x coordinate of center of chosen faces
        center_y=faceCenters_y_final;//y coordinate of center of chosen faces
        side=faceWidth_final;//bounding box edge length of chosen faces
    
        //From the center coordinates and width of the detected face bounding box, calculate
        //its top left corner coordinates
        vector<int> corner_x,corner_y;
        for(int num_faces=0;num_faces<num_of_faces;num_faces++){
            corner_x.push_back(center_x[num_faces]-(side[num_faces]/2));
            corner_y.push_back(center_y[num_faces]-(side[num_faces]/2));
        }
        vector<int> width;
        width=side;//bounding box width of chosen faces
        vector<int> height;
        height=side;//bounding box height of chosen faces
    
        vector<Mat> im2_cropped;//Stores all cropped chosen faces
        for(int num_faces=0;num_faces<num_of_faces;num_faces++){
            Mat im2_Gray;
            Rect roi(corner_x[num_faces], corner_y[num_faces],width[num_faces],height[num_faces]);
            im2_cropped.push_back(images[image_number[num_faces]](roi));
        }
    
        int row,col;
        for(int num_faces=0;num_faces<num_of_faces;num_faces++){
            //For each chosen face we loop through -40 to 40  in x and y direction
            double d2=1000000000000;
            for (int i=-40;i<=40;i++){
                for (int j=-40;j<=40;j++){
                    double d1,d1_1,d1_2,d1_3,d1_4;
                    //We take 20 pixels left boundary column in each chosen face's bounding box region on the reference image shifted by i
                    //and j in the x and y direction respectively
                    Mat im3 = images[reference_image_num](Rect(corner_x[num_faces]-i,corner_y[num_faces]-j,20,height[num_faces]));
                    //We take left 20 pixels column in each chosen face's bounding box region
                    Mat im4 = im2_cropped[num_faces](Rect(0,0,20,height[num_faces]));
                    //calculate the difference between the two
                    Mat diff=abs(im3-im4);
                    //Calculate the norm of difference
                    d1_1=norm(diff, NORM_L2);
                    //Repeat the above process for the 20 pixel right boundary column
                    im3 = images[reference_image_num](Rect(corner_x[num_faces]-i+width[num_faces]-20,corner_y[num_faces]-j,20,height[num_faces]));
                    im4 = im2_cropped[num_faces](Rect(width[num_faces]-20,0,20,height[num_faces]));
                    diff=abs(im3-im4);
                    d1_2=norm(diff, NORM_L2);
                    //Repeat the process for the 20 pixel top boundary column
                    im3 = images[reference_image_num](Rect(corner_x[num_faces]-i,corner_y[num_faces]-j,width[num_faces],20));
                    im4 = im2_cropped[num_faces](Rect(0,0,width[num_faces],20));
                    diff=abs(im3-im4);
                    d1_3=norm(diff, NORM_L2);
                    //Repeat the process for the 20 pixel bottom boundary column
                    im3 = images[reference_image_num](Rect(corner_x[num_faces]-i,corner_y[num_faces]-j+height[num_faces]-20,width[num_faces],20));
                    im4 = im2_cropped[num_faces](Rect(0,height[num_faces]-20,width[num_faces],20));
                    diff=abs(im3-im4);
                    d1_4=norm(diff, NORM_L2);
                    d1=d1_1+d1_2+d1_3+d1_4;//Add up all the norms
                    //Find i and j that minimises the sum of norms and store them in col and row respectively
                    if(d1<d2){
                        d2=d1;
                        row=j;
                        col=i;
                    }
                }
            }
            //Paste the cropped face into the reference image at a position shifted by the row and column in the y and x direction
            //from the cropped face's original position in the image from which it was cropped
            im2_cropped[num_faces].copyTo(images[reference_image_num](Rect(corner_x[num_faces]-col,corner_y[num_faces]-row,width[num_faces],height[num_faces])));
    
        }
        //Display final image and also write it into output file path
        imshow("final_result",images[reference_image_num]);
        imwrite(outputImagePath,images[reference_image_num]);
    
        waitKey(0);
        return 0;
    }
    
    //function to get image number based on where we drag the cursor on the bar to select a photo for a face
    void myCallbackForImageNumChange(int pos, void* userdata) {
        iImgNum = pos;
    }
    
    //function to find all faces using open CV's Haar cascade library
    Mat findAllFaces(Mat img, CascadeClassifier face_cascade, vector<int>& faceWidth, vector<int>& faceCenters_x, vector<int>& faceCenters_y) {
        vector<Rect> faces;
        Mat img_gray;
    
        cvtColor( img, img_gray, CV_BGR2GRAY );
        equalizeHist( img_gray, img_gray );
    
        //-- Detect faces
        face_cascade.detectMultiScale( img_gray, faces, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(40, 40) );
    
        int face_width;//Stores width of detected face's bounding box
        int faceCenter_x,faceCenter_y;//Stores center coordinates of detected face's bounding box
        Mat img_display;
        img.copyTo(img_display);
        for (size_t nFace = 0; nFace < faces.size(); nFace++) {
            face_width = faces[nFace].width*2;
            faceCenter_x = (faces[nFace].x-50 + face_width*0.5);
            faceCenter_y =(faces[nFace].y-50 + face_width*0.5);
            rectangle(img_display, Point(faces[nFace].x-50,faces[nFace].y-50), Point(faces[nFace].x-50 + faces[nFace].width*2,faces[nFace].y-50 + faces[nFace].width*2), Scalar(255,0,255), 2);
            faceWidth.push_back(face_width);
            faceCenters_x.push_back(faceCenter_x);
            faceCenters_y.push_back(faceCenter_y);
        }
        imwrite("Detected_faces.jpg",img_display);
        return img_display;//Return image with detected faces
    }
    

    The .xml file is just front face's traning resource with Haar like features obtained from Opencv itself
    And here's the issues list
    In function `main':

    undefined reference to `cv::CascadeClassifier::CascadeClassifier()'
    undefined reference to `cv::CascadeClassifier::load(cv::String const&)'
    undefined reference to `cv::CascadeClassifier::~CascadeClassifier()'
    undefined reference to `cv::CascadeClassifier::~CascadeClassifier()'
    undefined reference to `cv::CascadeClassifier::~CascadeClassifier()'
    undefined reference to `cv::CascadeClassifier::~CascadeClassifier()'
    In function `Z12findAllFacesN2cv3MatENS_17CascadeClassifierERSt6vectorIiSaIiEES5_S5_':
    error: undefined reference to `cv::CascadeClassifier::detectMultiScale(cv::_InputArray const&,std::vector<cv::
    	Rect_<int>, std::allocator<cv::Rect_<int> > >&, double, int, int, cv::Size_<int>, cv::Size_<int>)'
    collect2.exe:-1: error: error: ld returned 1 exit status
    

    Also I received the warning message which I have little idea of what's going on:
    Warnings while parsing QML type information of C:/Qt/Qt5.5.0/5.5/mingw492_32/qml:
    <dump of C:\Qt\Qt5.5.0\5.5\mingw492_32\qml>:1:24: Reading only version 1.1 parts.
    <dump of C:\Qt\Qt5.5.0\5.5\mingw492_32\qml>:10:5: Expected only Component and ModuleApi object definitions.

    Thank you sincerely.

    [edit: fixed missing coding tags SGaist]


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Your LIBS statement is wrong. You don't link to dlls, you link to .lib files. Just remove the .dll from all these lines and you should be good to go.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.