C++实现Vgg19分类器(四)主函数

开始分类流程:

1。输入图像预处理(和训练环境匹配):

    。将RGB转换成BGR
    。将图片大小缩放成:224x224 (全连接层的参数是固定大小的)
    。图片中每一个点减去时训练的平均值

2。VGG19 前传 --> 1000个分类概率

3。在分类标签中查最大概率的前5名。

4。输出类型名

主函数:

void VGG19(char * savefilename,Vgg19模型 & sr)
{

	int wid=jpg.getwidth();
	int hei=jpg.getheight();
		cout<<"输入图像宽度:"<<wid<<endl;
		cout<<"        高度:"<<hei<<endl;
//
	卷积层 rgb(wid,hei,3);//即rgb通道
	rgb.data=new float[wid * hei *3]; 

	//jpg转换为RGB卷积层
	jpg2RGB(&jpg,&rgb);

	RGB2BGR(rgb) ;
			
	预处理VGG(rgb); //减平均值 123.680f , 116.779f, 103.939f



	//再用一个卷积 交替前传(源,目标)
	层数据 * 层=sr.Conv1;
		int num=层->输出维度;
		卷积层 convfea1(wid,hei,num);
		convfea1.data=new float[wid * hei * num ]; 
	卷积层 *源,*目标;
	源 = &rgb;目标 = &convfea1;
	int pad;

	//定义一个宏
	//用于各个层
	#define 卷积和池化(ConvX,层数) \
	\
	层=sr.ConvX;/* Conv2 层 */ \
	/*int 层数=2;*/\
	for(int i=0;i<层数;i++)\
	{cout<<i<<endl;\
		if(层->输出维度 != 目标->depth || 目标->width != wid || 目标->height != hei)\
			Resize卷积层(*目标,wid,hei,层->输出维度);\
		pad=层->核宽/2;\
		vl_nnconv(源,目标,层 ,1,1,pad,pad,pad,pad);\
		vl_nnrelu(目标);/*激励函数Prelu*/\
\
		std::swap (源,目标);\
		层++;\
	}\
	\
	/*池化*/\
	wid=wid/2;hei=hei/2;\
	Resize卷积层(*目标,wid,hei,目标->depth);\
	vl_nnpool(源,目标);/*最大池化*/\
			\
	std::swap (源,目标);\


	cout<<"Conv1..."<<endl;
	卷积和池化(Conv1,2) 
		//save_卷积层2jpg(源,"con1");

	cout<<"Conv2..."<<endl;
	卷积和池化(Conv2,2) 
		//save_卷积层2jpg(源,"con2");

	cout<<"Conv3..."<<endl;
	卷积和池化(Conv3,4) 
		//save_卷积层2jpg(源,"con3");

	cout<<"Conv4..."<<endl;
	卷积和池化(Conv4,4) 
		//save_卷积层2jpg(源,"con4");

	cout<<"Conv5..."<<endl;
	卷积和池化(Conv5,4) 
		//save_卷积层2jpg(源,"con5");

	/* 全连接 层 */
	// 不能和卷积相同 四边不用补0
	#define 全连接(FcX) \
	层=sr.FcX; \
	if(层->输出维度 != 目标->depth || 目标->width != wid || 目标->height != hei)\
		Resize卷积层(*目标,wid,hei,层->输出维度);\
	pad=0;\
	vl_nnconv(源,目标,层 ,1,1,pad,pad,pad,pad);\
	vl_nnrelu(目标);/*激励函数Prelu*/\
\
	std::swap (源,目标);\

	cout<<"fc6..."<<endl;
	wid=1;hei=1;
	全连接(fc6)
		//save_卷积层2txt ("fc6.txt",源) ;

	cout<<"fc7..."<<endl;
	全连接(fc7)
		//save_卷积层2txt ("fc7.txt",源) ;

	cout<<"fc8..."<<endl;
	全连接(fc8)
		//save_卷积层2txt ("fc8.txt",源) ;

	vl_softmax(源);//激励函数
		//save_卷积层2txt ("softmax_res.txt",源) ;

	显示分类(*源);

	del卷积层(*源);
	del卷积层(*目标);
}

显示分类:

void 显示分类(卷积层 & d)
{
	float p;
	float *di=d.data;
	float m0,m1,m2,m3,m4;//记录前5的值
	int   n0,n1,n2,n3,n4;//对应序号

	m0=m1=m2=m3=m4= 0.f;
	n0=n1=n2=n3=n4= -1;

	for (int i = 0; i < d.width * d.height * d.depth; i++)
	{

		p=*di++;
		if(p>m0)
		{
			//向后传
			m4=m3;m3=m2;m2=m1;m1=m0;m0=p;
			n4=n3;n3=n2;n2=n1;n1=n0;n0=i;

			
		}
	}
	n0++;n1++;n2++;n3++;n4++;//从1开始
	//cout<<"前5个值:"<<endl;
	//cout<<"1:"<<m4<<" 序号:"<<n4<<endl;
	//cout<<"2:"<<m3<<" 序号:"<<n3<<endl;
	//cout<<"3:"<<m2<<" 序号:"<<n2<<endl;
	//cout<<"4:"<<m1<<" 序号:"<<n1<<endl;
	//cout<<"5:"<<m0<<" 序号:"<<n0<<endl;

	vector<string> 前5名;
	vector<int> 前5序号;
	
	前5序号.push_back(n4);前5序号.push_back(n3);
	前5序号.push_back(n2);前5序号.push_back(n1);
	前5序号.push_back(n0);

	读取分类(前5名,前5序号);
	
	float * ism[5];
	ism[0]=&m4;ism[1]=&m3;
	ism[2]=&m2;ism[3]=&m1;
	ism[4]=&m0;
	
	//显示分类
	cout<<"序号    类型    概率:"<<endl;
	for (size_t i = 0; i < 前5名.size(); i++)
	{
		cout<<前5序号[i]<<":"<<前5名[i].c_str() <<"。 :"<<*ism[i]<<endl;
	}
	cout<<endl;

}

拿几张图来测试一下:

前5个值:
序号    类型    概率:
21: 水鸟, 河乌。 :0.00100907
25: 巨大的灰色猫头鹰, 乌林鸮。 :0.0153372
106: 考拉熊, 无尾熊, 袋鼠熊, 树袋熊, 灰树熊。 :0.0200906
282: 虎斑猫。 :0.138211
286: 埃及猫。 :0.233397

再来一张:

结果:

前5个值:
序号    类型    概率:
160: 罗得西亚脊背犬, 猎狮犬。 :0.00299444
165: bluetick犬。 :0.00358157
167: 沃克猎犬, 沃克猎狐犬。 :0.0720664
168: 英国猎狐犬。 :0.114417
179: 威玛(猎)狗 。 :0.454336

运行时间4秒 加上载入1-4秒,共5-8秒。

结束

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值