ShiqiYu / libfacedetection

An open source library for face detection in images. The face detection speed can reach 1000FPS.
Other
12.31k stars 3.05k forks source link

C++11多线程调用函数报错 #275

Open woshildh opened 4 years ago

woshildh commented 4 years ago

您好,尝试了使用多线程的方式来调用 facedetect_cnn 函数,但是在运行过程中会报错。能帮忙看看嘛?非常感谢您的帮助,代码如下

#include "facedetectcnn.h"
#include<iostream>
#include<opencv2/opencv.hpp>
#include<vector>
#include<thread>
#include<mutex>
#include<queue>
#include<filesystem>

using namespace std;
using namespace cv;
using namespace std::filesystem;

#define DETECT_BUFFER_SIZE 0x20000

// 定义文件名队列的锁
mutex mutext_queue;

// 存储所有文件名的队列
queue<string> images_queue;

// 检查一个路径是否是目录
bool checkIsDir(const string &dir) {
    if (!exists(dir)) {
        cout<<dir<<" not exists. Please check."<<endl;
        return false;
    }
    directory_entry entry(dir);
    if (entry.is_directory())
        return true;
    return false;
}

// 搜索一个目录下所有的图像文件,以 jpg,jpeg,png 结尾的文件
void getAllImageFiles(const string dir, queue<string> &files) {
    // 首先检查目录是否为空,以及是否是目录
    if (!checkIsDir(dir)) return;
    // 递归遍历所有的文件
    directory_iterator iters(dir);
    for(auto &iter: iters) {
        string file_path(dir);
        file_path += "/"; file_path += iter.path().filename();
        // 如果是目录则循环递归
        if (checkIsDir(file_path)) {
            getAllImageFiles(file_path, files);
        } else { //不是目录则检查后缀是否是图像
            string extension = iter.path().extension();
            if (extension == ".jpg" || extension == ".png" || extension == ".jpeg") {
                files.push(file_path);
            }
        }
    }
}

// 进行处理检测人脸并且提取特征
void threadOfDetectAndExtract(int thread_num) {
    cout<<"This is "<<thread_num<<" thread"<<endl;
    // 申请一块内存用于存放检测结果
    int * pResults = NULL;
    unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
    if(!pBuffer) {
        cout<<"Can not alloc buffer!"<<endl;
        return;
    }
    // 定义数组用于存放提前的特征
    vector<float> features(512);
    //定时器
    TickMeter timer;
    // 开始检测和提取特征向量
    while(true) {
        // 定时器清0
        timer.reset(); timer.start();
        // 取图像
        mutext_queue.lock();
        if (images_queue.size() <= 0)
            break;
        string image_path = images_queue.front();
        images_queue.pop();
        mutext_queue.unlock();
        Mat image = imread(image_path);
        // 检测
        pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step);
        int face_num = (pResults ? *pResults : 0);
        cout<<"There are "<<face_num<<" faces in "<<image_path<<endl;
        // 裁剪人脸并且提取人脸的特征向量
        for(int i = 0; i < face_num; i++) {
            short *p = ((short *) (pResults + 1)) + 142 * i;
            int confidence = p[0];
            int x = p[1];
            int y = p[2];
            int w = p[3];
            int h = p[4];
            // 裁剪人脸
            Mat face = image(Rect(x, y, w, h));
            ...
        }
        timer.stop();
        cout<<"Thread "<<thread_num<<" process one image spend "<<timer.getTimeMilli()<<" ms"<<endl;
    }
    // 释放申请的内存空间,非常重要!!!!!
    if(pBuffer) free(pBuffer);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: %s <image_dir_name>\n", argv[0]);
        return -1;
    }

    // 读取所有的图像到队列中
    getAllImageFiles(argv[1], images_queue);
    cout<<"There are "<<images_queue.size()<<" images."<<endl;

    // 多线程实现
    thread t1(threadOfDetectAndExtract, 1);
    thread t2(threadOfDetectAndExtract, 2);

    // 启动两个线程
    t1.join();
    t2.join();
    cout<<"Process finished."<<endl;
    return 0;
}

报错的信息如下:

multi_thread(40355,0x700007c29000) malloc: *** error for object 0x7faf5685b600: pointer being freed was not allocated
multi_thread(40355,0x700007c29000) malloc: *** set a breakpoint in malloc_error_break to debug

经过我的调试,错误貌似在 void init_parameters()函数中,但是由于对项目不熟悉,无法定位到具体的原因。

cvtuge commented 3 years ago

您好,尝试了使用多线程的方式来调用 facedetect_cnn 函数,但是在运行过程中会报错。能帮忙看看嘛?非常感谢您的帮助,代码如下

#include "facedetectcnn.h"
#include<iostream>
#include<opencv2/opencv.hpp>
#include<vector>
#include<thread>
#include<mutex>
#include<queue>
#include<filesystem>

using namespace std;
using namespace cv;
using namespace std::filesystem;

#define DETECT_BUFFER_SIZE 0x20000

// 定义文件名队列的锁
mutex mutext_queue;

// 存储所有文件名的队列
queue<string> images_queue;

// 检查一个路径是否是目录
bool checkIsDir(const string &dir) {
    if (!exists(dir)) {
        cout<<dir<<" not exists. Please check."<<endl;
        return false;
    }
    directory_entry entry(dir);
    if (entry.is_directory())
        return true;
    return false;
}

// 搜索一个目录下所有的图像文件,以 jpg,jpeg,png 结尾的文件
void getAllImageFiles(const string dir, queue<string> &files) {
    // 首先检查目录是否为空,以及是否是目录
    if (!checkIsDir(dir)) return;
    // 递归遍历所有的文件
    directory_iterator iters(dir);
    for(auto &iter: iters) {
        string file_path(dir);
        file_path += "/"; file_path += iter.path().filename();
        // 如果是目录则循环递归
        if (checkIsDir(file_path)) {
            getAllImageFiles(file_path, files);
        } else { //不是目录则检查后缀是否是图像
            string extension = iter.path().extension();
            if (extension == ".jpg" || extension == ".png" || extension == ".jpeg") {
                files.push(file_path);
            }
        }
    }
}

// 进行处理检测人脸并且提取特征
void threadOfDetectAndExtract(int thread_num) {
    cout<<"This is "<<thread_num<<" thread"<<endl;
    // 申请一块内存用于存放检测结果
    int * pResults = NULL;
    unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
    if(!pBuffer) {
        cout<<"Can not alloc buffer!"<<endl;
        return;
    }
    // 定义数组用于存放提前的特征
    vector<float> features(512);
    //定时器
    TickMeter timer;
    // 开始检测和提取特征向量
    while(true) {
        // 定时器清0
        timer.reset(); timer.start();
        // 取图像
        mutext_queue.lock();
        if (images_queue.size() <= 0)
            break;
        string image_path = images_queue.front();
        images_queue.pop();
        mutext_queue.unlock();
        Mat image = imread(image_path);
        // 检测
        pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step);
        int face_num = (pResults ? *pResults : 0);
        cout<<"There are "<<face_num<<" faces in "<<image_path<<endl;
        // 裁剪人脸并且提取人脸的特征向量
        for(int i = 0; i < face_num; i++) {
            short *p = ((short *) (pResults + 1)) + 142 * i;
            int confidence = p[0];
            int x = p[1];
            int y = p[2];
            int w = p[3];
            int h = p[4];
            // 裁剪人脸
            Mat face = image(Rect(x, y, w, h));
            ...
        }
        timer.stop();
        cout<<"Thread "<<thread_num<<" process one image spend "<<timer.getTimeMilli()<<" ms"<<endl;
    }
    // 释放申请的内存空间,非常重要!!!!!
    if(pBuffer) free(pBuffer);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: %s <image_dir_name>\n", argv[0]);
        return -1;
    }

    // 读取所有的图像到队列中
    getAllImageFiles(argv[1], images_queue);
    cout<<"There are "<<images_queue.size()<<" images."<<endl;

    // 多线程实现
    thread t1(threadOfDetectAndExtract, 1);
    thread t2(threadOfDetectAndExtract, 2);

    // 启动两个线程
    t1.join();
    t2.join();
    cout<<"Process finished."<<endl;
    return 0;
}

报错的信息如下:

multi_thread(40355,0x700007c29000) malloc: *** error for object 0x7faf5685b600: pointer being freed was not allocated
multi_thread(40355,0x700007c29000) malloc: *** set a breakpoint in malloc_error_break to debug

经过我的调试,错误貌似在 void init_parameters()函数中,但是由于对项目不熟悉,无法定位到具体的原因。

碰到同样的问题,请问这个问题您解决了吗

woshildh commented 3 years ago

@cvtuge 没有解决,我换了一个开源项目来做的人脸检测 https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB, 速度更快,效果更好,建议尝试

ShiqiYu commented 3 years ago

您好,尝试了使用多线程的方式来调用 facedetect_cnn 函数,但是在运行过程中会报错。能帮忙看看嘛?非常感谢您的帮助,代码如下

#include "facedetectcnn.h"
#include<iostream>
#include<opencv2/opencv.hpp>
#include<vector>
#include<thread>
#include<mutex>
#include<queue>
#include<filesystem>

using namespace std;
using namespace cv;
using namespace std::filesystem;

#define DETECT_BUFFER_SIZE 0x20000

// 定义文件名队列的锁
mutex mutext_queue;

// 存储所有文件名的队列
queue<string> images_queue;

// 检查一个路径是否是目录
bool checkIsDir(const string &dir) {
    if (!exists(dir)) {
        cout<<dir<<" not exists. Please check."<<endl;
        return false;
    }
    directory_entry entry(dir);
    if (entry.is_directory())
        return true;
    return false;
}

// 搜索一个目录下所有的图像文件,以 jpg,jpeg,png 结尾的文件
void getAllImageFiles(const string dir, queue<string> &files) {
    // 首先检查目录是否为空,以及是否是目录
    if (!checkIsDir(dir)) return;
    // 递归遍历所有的文件
    directory_iterator iters(dir);
    for(auto &iter: iters) {
        string file_path(dir);
        file_path += "/"; file_path += iter.path().filename();
        // 如果是目录则循环递归
        if (checkIsDir(file_path)) {
            getAllImageFiles(file_path, files);
        } else { //不是目录则检查后缀是否是图像
            string extension = iter.path().extension();
            if (extension == ".jpg" || extension == ".png" || extension == ".jpeg") {
                files.push(file_path);
            }
        }
    }
}

// 进行处理检测人脸并且提取特征
void threadOfDetectAndExtract(int thread_num) {
    cout<<"This is "<<thread_num<<" thread"<<endl;
    // 申请一块内存用于存放检测结果
    int * pResults = NULL;
    unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
    if(!pBuffer) {
        cout<<"Can not alloc buffer!"<<endl;
        return;
    }
    // 定义数组用于存放提前的特征
    vector<float> features(512);
    //定时器
    TickMeter timer;
    // 开始检测和提取特征向量
    while(true) {
        // 定时器清0
        timer.reset(); timer.start();
        // 取图像
        mutext_queue.lock();
        if (images_queue.size() <= 0)
            break;
        string image_path = images_queue.front();
        images_queue.pop();
        mutext_queue.unlock();
        Mat image = imread(image_path);
        // 检测
        pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step);
        int face_num = (pResults ? *pResults : 0);
        cout<<"There are "<<face_num<<" faces in "<<image_path<<endl;
        // 裁剪人脸并且提取人脸的特征向量
        for(int i = 0; i < face_num; i++) {
            short *p = ((short *) (pResults + 1)) + 142 * i;
            int confidence = p[0];
            int x = p[1];
            int y = p[2];
            int w = p[3];
            int h = p[4];
            // 裁剪人脸
            Mat face = image(Rect(x, y, w, h));
            ...
        }
        timer.stop();
        cout<<"Thread "<<thread_num<<" process one image spend "<<timer.getTimeMilli()<<" ms"<<endl;
    }
    // 释放申请的内存空间,非常重要!!!!!
    if(pBuffer) free(pBuffer);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: %s <image_dir_name>\n", argv[0]);
        return -1;
    }

    // 读取所有的图像到队列中
    getAllImageFiles(argv[1], images_queue);
    cout<<"There are "<<images_queue.size()<<" images."<<endl;

    // 多线程实现
    thread t1(threadOfDetectAndExtract, 1);
    thread t2(threadOfDetectAndExtract, 2);

    // 启动两个线程
    t1.join();
    t2.join();
    cout<<"Process finished."<<endl;
    return 0;
}

报错的信息如下:

multi_thread(40355,0x700007c29000) malloc: *** error for object 0x7faf5685b600: pointer being freed was not allocated
multi_thread(40355,0x700007c29000) malloc: *** set a breakpoint in malloc_error_break to debug

经过我的调试,错误貌似在 void init_parameters()函数中,但是由于对项目不熟悉,无法定位到具体的原因。

碰到同样的问题,请问这个问题您解决了吗

初始化在第一次调用facedetect_cnn中,所以第一次调用facedetect_cnn不要在并行里调用,即调用完一次facedetect_cnn后再多线程,应该就问题了。