在使用dlib开发人脸对齐功能时,出现了”生成的目标文件包含了过多的段,超出了编译器或链接器允许的最大数量的错误“。
主要功能代码如下:
#include <QApplication>
#include <QImage>
#include <QDebug>
#include <dlib/opencv.h>
#include <opencv2/highgui/highgui.hpp>
#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 <dlib/matrix.h>
#include <opencv2/opencv.hpp>
#include <opencv2/opencv_modules.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <dlib/dnn.h>
#define FACE_DOWNSAMPLE_RATIO 4
#define SKIP_FRAMES 2
#define DLIB_PNG_SUPPORT
#define DLIB_JPEG_SUPPORT
using namespace cv;
using namespace std;
using namespace dlib;
template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual = add_prev1<block<N,BN,1,tag1<SUBNET>>>;
template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual_down = add_prev2<avg_pool<2,2,2,2,skip1<tag2<block<N,BN,2,tag1<SUBNET>>>>>>;
template <int N, template <typename> class BN, int stride, typename SUBNET>
using block = BN<con<N,3,3,1,1,relu<BN<con<N,3,3,stride,stride,SUBNET>>>>>;
template <int N, typename SUBNET> using ares = relu<residual<block,N,affine,SUBNET>>;
template <int N, typename SUBNET> using ares_down = relu<residual_down<block,N,affine,SUBNET>>;
template <typename SUBNET> using alevel0 = ares_down<256,SUBNET>;
template <typename SUBNET> using alevel1 = ares<256,ares<256,ares_down<256,SUBNET>>>;
template <typename SUBNET> using alevel2 = ares<128,ares<128,ares_down<128,SUBNET>>>;
template <typename SUBNET> using alevel3 = ares<64,ares<64,ares<64,ares_down<64,SUBNET>>>>;
template <typename SUBNET> using alevel4 = ares<32,ares<32,ares<32,SUBNET>>>;
using anet_type = loss_metric<fc_no_bias<128,avg_pool_everything<
alevel0<
alevel1<
alevel2<
alevel3<
alevel4<
max_pool<3,3,2,2,relu<affine<con<32,7,7,2,2,
input_rgb_image_sized<150>
>>>>>>>>>>>>;
// 计算两个人脸的相似度
double compare_faces(const array2d<rgb_pixel>& img1, const array2d<rgb_pixel>& img2, shape_predictor& sp, anet_type& net) {
// 检测人脸
frontal_face_detector detector = get_frontal_face_detector();
std::vector<dlib::rectangle> dets1 = detector(img1);
std::vector<dlib::rectangle> dets2 = detector(img2);
if (dets1.empty() || dets2.empty()) {
throw std::runtime_error("No faces detected in one of the images.");
}
// 提取人脸特征
full_object_detection shape1 = sp(img1, dets1[0]);
full_object_detection shape2 = sp(img2, dets2[0]);
// 计算人脸特征向量
matrix<rgb_pixel> face_chip1;
extract_image_chip(img1, get_face_chip_details(shape1, 150, 0.25), face_chip1);
matrix<rgb_pixel> face_chip2;
extract_image_chip(img2, get_face_chip_details(shape2, 150, 0.25), face_chip2);
// 获取128维特征向量
auto face_descriptor1 = net(face_chip1);
auto face_descriptor2 = net(face_chip2);
// 计算距离
double distance = length(face_descriptor1 - face_descriptor2);
return distance;
}
int main(int argc, char** argv)
{
QApplication app(argc, argv);
// 加载模型
shape_predictor sp;
deserialize("shape_predictor_68_face_landmarks.dat") >> sp;
anet_type net;
deserialize("dlib_face_recognition_resnet_model_v1.dat") >> net;
// 加载图像
array2d<rgb_pixel> img1, img2;
load_image(img1, "path/to/your/image1.jpg");
load_image(img2, "path/to/your/image2.jpg");
// 进行人脸比对
try {
double distance = compare_faces(img1, img2, sp, net);
qDebug()<<QString::number(distance);
QString result = (distance < 0.6) ? "Faces match!" : "Faces do not match!";
qDebug()<<result;
} catch (const std::exception& e) {
qDebug()<<e.what();
}
return app.exec();
}
错误控制台显示:
这个错误信息表明在编译过程中,生成的目标文件main.o包含了过多的段(sections),超出了编译器或链接器允许的最大数量。在某些嵌入式系统或使用特定工具链的情况下,目标文件的段数量会有严格的限制。
解决方法:
-
优化代码结构:检查代码,尝试减少不必要的函数和全局变量,以此减少段的数量。
-
使用更小的数据类型:如果可能,使用更小的数据类型,如int替换为short,long替换为short或int,以减少内存占用和段的数量。
-
减少链接器的内存占用:调整链接器的内存配置,例如在某些链接器中可以通过设置内存段的大小来减少段的数量。
-
使用更高级的编译器或链接器:升级到更高版本的编译器或链接器,新版本可能增加了对更多段的支持,或者提供了优化选项来减少段的数量。
-
配置编译器:有些编译器允许通过特定选项来调整段的生成策略,比如GNU编译器中的-ffunction-sections和-fdata-sections选项可以将函数和数据分别放入独立的段中。
-
分割代码:如果可能,将代码分割成多个小的源文件和库,以减少每个目标文件的段数量。
-
检查编译器和链接器文档:查看编译器和链接器的文档,看是否有特定的选项或配置可以帮助减少段的数量。
-
联系工具链提供商:如果上述方法都无法解决问题,可以考虑联系你正在使用的编译器或链接器的技术支持。
-
在实施以上任何一个解决方案之前,请确保了解这些更改可能对代码的其他方面产生的影响,并在必要时对代码进行适当的测试。
快速简单的解决方案:是由Debug模式切换成Release模式。