MTCNN(八)openCV依赖库

  • Post author:
  • Post category:其他



背景:

已经将openBLAS依赖库去除,我们需要将MTCNN编译到arm单片机上运行,依然依赖OpenCV库。


目的:

解决openCV库的问题。


目录


openCV依赖情况:


一、根据备选框进行check


1.1 输出人头的个数


1.2 析构函数


二、图像的读取


2.1 openCV中关于图像的读取


2.2 写入图像数据进入bin文件


2.1.1 原始写入程序


2.1.2 线性写入文件


三、虚拟机上安装openCV


openCV依赖情况:

图像读取为 Mat的imread

  • mat2matrix中函数需要mat格式
  • resize函数
  • 针对Mat的取框等

图像处理方面脱离openCV寸步难行,去除openCV库之后进行编译,打印信息如下:均为与openCV相关的函数,从底层再编起工程量过大。我们在后续交叉编译openCV时候也说明了我们将openCV一起交叉编译是正确的,因为程序脱离openCV之后工程量过大。

CMakeFiles/main.dir/src/mtcnn.cpp.o: In function `mtcnn::findFace(cv::Mat&)':
mtcnn.cpp:(.text+0x3b33): undefined reference to `cv::_OutputArray::_OutputArray(cv::Mat&)'
mtcnn.cpp:(.text+0x3b4c): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
mtcnn.cpp:(.text+0x3b76): undefined reference to `cv::resize(cv::_InputArray const&, cv::_OutputArray const&, cv::Size_<int>, double, double, int)'
mtcnn.cpp:(.text+0x40a0): undefined reference to `cv::_OutputArray::_OutputArray(cv::Mat&)'
mtcnn.cpp:(.text+0x40d9): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
mtcnn.cpp:(.text+0x4103): undefined reference to `cv::resize(cv::_InputArray const&, cv::_OutputArray const&, cv::Size_<int>, double, double, int)'
mtcnn.cpp:(.text+0x450c): undefined reference to `cv::_OutputArray::_OutputArray(cv::Mat&)'
mtcnn.cpp:(.text+0x4545): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
mtcnn.cpp:(.text+0x456f): undefined reference to `cv::resize(cv::_InputArray const&, cv::_OutputArray const&, cv::Size_<int>, double, double, int)'
mtcnn.cpp:(.text+0x4b29): undefined reference to `cv::rectangle(cv::Mat&, cv::Point_<int>, cv::Point_<int>, cv::Scalar_<double> const&, int, int, int)'
mtcnn.cpp:(.text+0x4c1c): undefined reference to `cv::circle(cv::Mat&, cv::Point_<int>, int, cv::Scalar_<double> const&, int, int, int)'
CMakeFiles/main.dir/src/mtcnn.cpp.o: In function `cv::Mat::~Mat()':
mtcnn.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x39): undefined reference to `cv::fastFree(void*)'
CMakeFiles/main.dir/src/mtcnn.cpp.o: In function `cv::Mat::release()':
mtcnn.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x47): undefined reference to `cv::Mat::deallocate()'
CMakeFiles/main.dir/src/mtcnn.cpp.o: In function `cv::Mat::operator()(cv::Rect_<int> const&) const':
mtcnn.cpp:(.text._ZNK2cv3MatclERKNS_5Rect_IiEE[_ZNK2cv3MatclERKNS_5Rect_IiEE]+0x27): undefined reference to `cv::Mat::Mat(cv::Mat const&, cv::Rect_<int> const&)'
CMakeFiles/main.dir/src/pikaqiu.cpp.o: In function `main':
pikaqiu.cpp:(.text+0x7b): undefined reference to `cv::imread(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
pikaqiu.cpp:(.text+0x1b4): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
pikaqiu.cpp:(.text+0x1f7): undefined reference to `cv::imshow(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cv::_InputArray const&)'
pikaqiu.cpp:(.text+0x252): undefined reference to `cv::waitKey(int)'

一、根据备选框进行check

1.1 输出人头的个数

此步用于保证程序正确运行。在没有了openCV的imshow和imwrite之后,我们需要用最终生成框的个数以用于检测程序是否正确运行。

mtcnn find(image.rows, image.cols);

start = clock();
int FaceNum=find.findFace(image);
total_time = (double)(clock() -start)/CLOCKS_PER_SEC*1000;
cout<<"All find time is  "<<total_time<<" milli second"<<endl;

if(FaceNum==right_faceNum)
	printf("SUCCESS!\n");
else
	printf("Program ERROR!\n");
// mtcnn.cpp  in function  int findFace(Mat &image);
refineAndSquareBbox(thirdBbox_, image.rows, image.cols);
nms(thirdBbox_, thirdBboxScore_, nms_threshold[2], "Min");
int final_outBboxNum=0;
for(vector<struct Bbox>::iterator it=thirdBbox_.begin(); it!=thirdBbox_.end();it++){
	if((*it).exist){
		rectangle(image, Point((*it).y1, (*it).x1), Point((*it).y2, (*it).x2), Scalar(0,0,255), 2,8,0);
		final_outBboxNum++;
		for(int num=0;num<5;num++)circle(image,Point((int)*(it->ppoint+num), (int)*(it->ppoint+num+5)),3,Scalar(0,255,255), -1);
	}
}
return final_outBboxNum;

直接将输出的人头的个数与实际个数比对,得出最终的个数结果。

经历了此步之后,我们可以保证程序正确运行

1.2 析构函数


https://baike.baidu.com/item/%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0/9483718?fr=aladdin

mtcnn::~mtcnn(){
	printf("Free mtcnn,delete simpleFace\n");
    delete []simpleFace_;
}

当对象结束其

生命周期

,如对象所在的函数已调用完毕时,系统自动执行析构函数。这就是为什么在主程序之中没有看到此函数的调用,因为系统是自动执行此函数的。

Run nms
Rnet run
Rnet run
Rnet run
Run nms
Run Onet
Run Onet
Run Onet
Run nms
------Done find Face function
All find time is  421.214 milli second
SUCCESS!
Free mtcnn,delete simpleFace
Free Pnet
Free Pnet
Free Pnet
Free Onet
Free Rnet

二、图像的读取

2.1 openCV中关于图像的读取

直接运用imread函数对图像进行读取。Mat image = imread(photoName2);  mtcnn find(image.rows, image.cols);

我们输出相应的图片的行与列。直接printf 图片的image.rows与image.cols。

注意,linux中我们alt+enter显示图像属性的时候,图像为640*480,对应的openCV读取的row为480,col为640.

2.2 写入图像数据进入bin文件

2.1.1 原始写入程序

openCV读出的图片为Mat格式,我们需要将图像存为.bin文件,然后读取。

//network.cpp
void image2Matrix(const Mat &image, const struct pBox *pbox){
    if ((image.data == NULL) || (image.type() != CV_8UC3)){
        cout << "image's type is wrong!!Please set CV_8UC3" << endl;
        return;
    }
    if (pbox->pdata == NULL){
        return;
    }
    mydataFmt *p = pbox->pdata;
    for (int rowI = 0; rowI < image.rows; rowI++){
        for (int colK = 0; colK < image.cols; colK++){
            *p = (image.at<Vec3b>(rowI, colK)[0] - 127.5)*0.0078125;//
            *(p + image.rows*image.cols) = (image.at<Vec3b>(rowI, colK)[1] - 127.5)*0.0078125;
            *(p + 2*image.rows*image.cols) = (image.at<Vec3b>(rowI, colK)[2] - 127.5)*0.0078125;
            p++;
        }
    }
}

此处注意openCV读取的图像格式与MTCNN之间的数值的转化。(x-127.5)/128.将0-255的图像映射到[-1,1]之间?

2.1.2 线性写入文件

//in void image2Matrix(const Mat &image, const struct pBox *pbox)
//write pBox format image data into the bin file 
printf("----------start write into .bin-----\n");
char fileName[]="image1.bin";
FILE * binFILE_ptr;
if((binFILE_ptr=fopen(fileName,"wb"))==NULL){
	printf("can't open weight file");
	exit(0);
}
fwrite(pbox->pdata, sizeof(float),3*image.rows*image.cols,binFILE_ptr);
fclose(binFILE_ptr);
printf("----------done write  .bin-----\n");

经历此步骤写入文件,但是发现不止初始情况下的图片进行了image2Matrix,而是在网络运行过程中对所有的备选框均生成了Mat格式的框然后进行了此步骤。

Rnet run
----------start write into .bin-----
----------done write  .bin-----
Run nms
Run Onet
----------start write into .bin-----
----------done write  .bin-----
Run Onet
----------start write into .bin-----
----------done write  .bin-----
Run Onet
----------start write into .bin-----
----------done write  .bin-----
Run nms

可以看出,根据输入图像的Mat,根据备选框取样为输入其他net的Mat在此有运用。此步到此,必须去除程序对openCV相关函数的依赖。才能回到此步。

三、虚拟机上安装openCV

基于对ARM与FPGA对程序分工的考量,可以将ARM单片机与FPGA分开,ARM实现网络加载等等信息,只把卷积和prelu给FPGA运算加速,因此如果单片机可以编译openCV,我们可以将此转到FPGA上进行运算。


虚拟机上安装openCV


https://blog.csdn.net/weixin_36474809/article/details/83373908


ARM单片机编译与运行程序MTCNN


https://blog.csdn.net/weixin_36474809/article/details/83342549



版权声明:本文为weixin_36474809原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。