MTCNN(五)c代码概览及权重的更改

版权声明:转载注明出处:邢翔瑞的技术博客https://blog.csdn.net/weixin_36474809/article/list/1 https://blog.csdn.net/weixin_36474809/article/details/82991552

背景:将MTCNN部署在FPGA上需要将其代码设计为C代码,所以训练时的python代码需要转为c代码。

参考资料:https://github.com/AlphaQi/MTCNN-light

一、代码概览

1.1 各函数作用

pikaqiu.cpp为主函数,通过find.findFace(image);对图片运行目标检测操作

mtcnn.h定义Pnet,Rnet,Onet,mtcnn四个的class,其中有private与public

mtcnn.cpp定义函数

  • mtcnn::findFace,
  • Pnet()创建Pnet,
  • ~Pnet()释放Pnet内存,
  • run运行相应网络,
  • Pnet::generateBbox生成相应备选框,
  • RnetImage2MatrixInit图像变为矩阵操作

network.h 相关函数声明

network.cpp 相关函数定义,如addbias,featurePad,feature2Matrix,convolution等

pBox.h 定义了pBox,bBox, weight等结构体

pBox.cpp 定义了free上面那些结构体的函数以及show函数,用于输出上面结构体,可能在调试时有作用。

1.2 需要改动地方

网络结构的更改,我们的网络结构与原结构不相同

权重的读取,FPGA的读取最好为bin文件,节省内存空间,代码中为txt文件,共6.9MB

FPGA无法处理三指针的问题,需要将代码中的class转为namespace

二、权重的读取

权重文件为txt文件,每行一个数据  [data] \n [data] \n  ...权重文件有大量荣誉,比如括号符号。

读取权重的语句,其中根据相应的filename之中读取出权重,然后存入pointTeam的

    mydataFmt *pointTeam[13] = {this->conv1_wb->pdata, this->conv1_wb->pbias,         this->prelu_gmma1->pdata, \
                            this->conv2_wb->pdata, this->conv2_wb->pbias, this->prelu_gmma2->pdata, \
                            this->conv3_wb->pdata, this->conv3_wb->pbias, this->prelu_gmma3->pdata, \
                            this->conv4c1_wb->pdata, this->conv4c1_wb->pbias, \
                            this->conv4c2_wb->pdata, this->conv4c2_wb->pbias \
                            };
    string filename = "Pnet.txt";
    readData(filename, dataNumber, pointTeam);

读取函数:

void readData(string filename, long dataNumber[], mydataFmt *pTeam[]){
    
    ifstream in(filename.data());
    string line;
    if(in)
    {  
        int i = 0;
        int count = 0;
        int pos = 0;
        while (getline (in, line))  
        {   
            try{
                if(i<dataNumber[count]){
                    line.erase(0,1);
                    pos = line.find(']');
                    line.erase(pos,1);
                    *(pTeam[count])++ = atof(line.data());
                }
                else{
                    count++;
                    dataNumber[count] += dataNumber[count-1];

                    line.erase(0,1);
                    pos = line.find(']');
                    line.erase(pos,1);
                    *(pTeam[count])++ = atof(line.data());
                }
                i++;
            }
            catch (exception& e){
                cout<<" yichang "<<i<<endl;
                return;
            }
        } 
    }  
    else 
    {  
        cout <<"no such file"<< filename << endl;  
    }
}

2.1 函数解析

将权重文件从txt文件中读出,存入pointTeam的二维指针之中。

逐行将txt中的权重写入相应指针文件之中。

2.2 相关语句

ifstream in(filename.data)读取文件

ifstream 从文件读入到缓冲区

https://blog.csdn.net/kingstar158/article/details/6859379

https://www.cnblogs.com/batman425/p/3179520.html

getline (in,line)获取每行

存储一行数据

https://baike.baidu.com/item/getline%E5%87%BD%E6%95%B0/3932106?fr=aladdin

line.erase相关位置删除n字节

string.erase(pos,n)          //删除从pos开始的n个字符    string.erase(0,1);   删除第一个字符

文件中为删除数据两端的中括号

atof(line.data()) 字符串转为浮点

try与catch

https://blog.csdn.net/qq_15037231/article/details/79980604

try语句中出现异常的时候就会执行catch中的语句

*(pTeam[count])++ = atof(line.data());

pTeam为二维数组,pTeam[count]为一维数组的指针,先取址,将数据写入,后++,指针指向下一个位置。

return

从被调函数返回到主调函数继续执行

三、更改权重为bin文件

3.1 txt文件改为bin文件

原始文件为字节文件,较为耗费存储,我们将其存储为二进制文档,就节省很多内存空间。

#weight_txt2bin.py  transfer weightfile
for line in lines:
    numString=line[1:-2]
    # add this if because the last line is "]"
    # lines not the last line is "]\n"
    if idx==(np.size(lines)-1):
        numString=line[1:-1]  
    numFloat=float(numString)
    numBuffer=struct.pack('f',numFloat)
    binfile.write(numBuffer)
    idx=idx+1

更改前文件为txt格式,有6.9MB,更改后为2.0MB

3.3 c程序中代码的读取

调用函数中,mtcnn.cpp中将三个网络读取的.txt改为.bin,readData函数改为下面:

// network.cpp   in   function  readData
	int count = 0;
	//while(!feof(weightFILE_ptr)){
	while(count<prtNum){
		fread(pTeam[count],sizeof(mydataFmt),dataNumber[count],weightFILE_ptr);
		printf("count=%d dataNumber[count]=%ld \n",count,dataNumber[count]);
		count++;
	}
Read Rnet.bin ,16 pointers
count=0 dataNumber[count]=756
count=1 dataNumber[count]=28
count=2 dataNumber[count]=28
count=3 dataNumber[count]=12096
count=4 dataNumber[count]=48
count=5 dataNumber[count]=48
count=6 dataNumber[count]=12288
count=7 dataNumber[count]=64
count=8 dataNumber[count]=64
count=9 dataNumber[count]=73728
count=10 dataNumber[count]=128
count=11 dataNumber[count]=128
count=12 dataNumber[count]=256
count=13 dataNumber[count]=2
count=14 dataNumber[count]=512
count=15 dataNumber[count]=4
Read Onet.bin ,21 pointers
count=0 dataNumber[count]=864
count=1 dataNumber[count]=32
count=2 dataNumber[count]=32
count=3 dataNumber[count]=18432
count=4 dataNumber[count]=64
count=5 dataNumber[count]=64
count=6 dataNumber[count]=36864
count=7 dataNumber[count]=64
count=8 dataNumber[count]=64
count=9 dataNumber[count]=32768
count=10 dataNumber[count]=128
count=11 dataNumber[count]=128
count=12 dataNumber[count]=294912
count=13 dataNumber[count]=256
count=14 dataNumber[count]=256
count=15 dataNumber[count]=512
count=16 dataNumber[count]=2
count=17 dataNumber[count]=1024
count=18 dataNumber[count]=4
count=19 dataNumber[count]=2560
count=20 dataNumber[count]=10
Read Pnet.bin ,13 pointers
count=0 dataNumber[count]=270
count=1 dataNumber[count]=10
count=2 dataNumber[count]=10
count=3 dataNumber[count]=1440
count=4 dataNumber[count]=16
count=5 dataNumber[count]=16
count=6 dataNumber[count]=4608
count=7 dataNumber[count]=32
count=8 dataNumber[count]=32
count=9 dataNumber[count]=64
count=10 dataNumber[count]=2
count=11 dataNumber[count]=128
count=12 dataNumber[count]=4
Read Pnet.bin ,13 pointers
...
time is  18772.8 milli second

读取Pnet的权值重复了六次。我们需要将此读取过程简化。

四、程序运行

4.1 嵌套顺序

我们将程序之中加入printf信息,输出相应的位置信息。

Create Rnet,Read Rnet.bin ,16 pointers
Create Onet,Read Onet.bin ,21 pointers
Create mtcnn,simple face
Create Pnet,Read Pnet.bin ,13 pointers
Create Pnet,Read Pnet.bin ,13 pointers
...
Create Pnet,Read Pnet.bin ,13 pointers
Start find Face function
Start run Pnet
Start Pnet generate Bbox
Done Pnet generate Bbox
Done run Pnet
Run nms
Start run Pnet
Start Pnet generate Bbox
Done Pnet generate Bbox
Done run Pnet
Run nms
Start run Pnet
......
Start run Pnet
Start Pnet generate Bbox
Done Pnet generate Bbox
Done run Pnet
Run nms
Run nms
Rnet run
Rnet run
......
Rnet run
Run nms
Run Onet
Run Onet
......
Run Onet
Run nms
Done find Face function
time is  19789 milli second
Free mtcnn,delete simpleFace
Free Pnet
Free Pnet
Free Pnet
Free Pnet
Free Pnet
Free Pnet
Free Pnet
Free Onet
Free Rnet

更改运行小的头像

Create Rnet,Read Rnet.bin ,16 pointers
Create Onet,Read Onet.bin ,21 pointers
Create mtcnn,simple face
Create Pnet,Read Pnet.bin ,13 pointers
Create Pnet,Read Pnet.bin ,13 pointers
Create Pnet,Read Pnet.bin ,13 pointers
Start find Face function
Start run Pnet
Start Pnet generate Bbox
Done Pnet generate Bbox
Done run Pnet
Run nms
Start run Pnet
Start Pnet generate Bbox
Done Pnet generate Bbox
Done run Pnet
Run nms
Start run Pnet
Start Pnet generate Bbox
Done Pnet generate Bbox
Done run Pnet
Run nms
Run nms
Rnet run
Rnet run
Rnet run
Rnet run
Rnet run
Rnet run
Rnet run
Rnet run
Rnet run
Rnet run
Run nms
Run Onet
Run Onet
Run Onet
Run nms
Done find Face function
time is  8016.19 milli second
Free mtcnn,delete simpleFace
Free Pnet
Free Pnet
Free Pnet
Free Onet
Free Rnet

猜你喜欢

转载自blog.csdn.net/weixin_36474809/article/details/82991552
今日推荐