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

本文详细介绍了使用VGG19模型进行图像分类的过程,包括图像预处理、模型前向传播、分类结果输出等关键步骤。通过实际案例展示了如何获取图像的前五类预测结果及其概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开始分类流程:

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秒。

结束

### VGG19 分类器简介 VGG19 是一种基于卷积神经网络 (CNN) 的深度学习模型,最初由牛津大学视觉几何组 (Visual Geometry Group, VGG) 提出并发表在论文《Very Deep Convolutional Networks for Large-Scale Visual Recognition》中[^1]。该模型以其简单而有效的架构设计著称,在多个计算机视觉任务中表现出优异性能。 VGG19 特别适合用于图像分类任务,其核心特点在于通过堆叠多层小型卷积核(通常为 \(3 \times 3\)),逐步提取输入图像的空间特征和语义信息。相比其他复杂结构的模型,VGG19 更易于理解和实现。 --- ### PyTorch 中 VGG19 模型的使用方法 以下是利用 PyTorch 实现 VGG19 并将其作为分类器的具体参数配置与代码示例: #### 安装依赖库 确保已安装 `torch` 和 `torchvision` 库: ```bash pip install torch torchvision ``` #### 构建 VGG19 模型实例 可以通过调用 `torchvision.models.vgg19(pretrained=True)` 来快速获取预训练好的 VGG19 模型。如果需要自定义修改,则可以继承 `nn.Module` 类来自定义模型结构。 ```python import torch from torchvision import models # 初始化预训练的 VGG19 模型 model = models.vgg19(pretrained=True) # 如果不希望微调整个网络,冻结所有参数 for param in model.parameters(): param.requires_grad = False # 修改最后一层全连接层以适配新的分类任务 num_features = model.classifier[-1].in_features output_classes = 10 # 假设目标数据集有 10 类 model.classifier[-1] = torch.nn.Linear(num_features, output_classes) ``` 上述代码片段展示了如何加载预训练模型,并调整最后的全连接层以适应特定的任务需求[^2]。 #### 数据预处理 为了使输入数据能够被 VGG19 正确接收,需对其进行标准化处理。以下是一个典型的图像预处理管道: ```python from torchvision import transforms transform = transforms.Compose([ transforms.Resize((224, 224)), # 调整图片大小至 224x224 transforms.ToTensor(), # 将 PIL 图像转换成张量 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 归一化 ]) ``` 这些均值 (`mean`) 和标准差 (`std`) 参数来源于 ImageNet 数据集统计结果,适用于大多数迁移学习场景。 #### 预测函数定义 完成模型初始化后,可编写如下预测逻辑: ```python def predict(image_path, model, transform, device): image = Image.open(image_path).convert('RGB') input_tensor = transform(image).unsqueeze(0).to(device) # 添加批次维度并将数据移至 GPU/CPU with torch.no_grad(): # 关闭梯度计算以节省内存 outputs = model(input_tensor) probabilities = torch.softmax(outputs, dim=1)[0] topk_probabilities, indices = torch.topk(probabilities, k=5) # 获取前五高概率类别及其索引 return [(i.item(), p.item()) for i, p in zip(indices, topk_probabilities)] # 设置运行环境 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) model.eval() # 测试单张图片 result = predict("test_image.jpg", model, transform, device) print(result) ``` 此部分实现了从读取测试图片到返回预测结果的整体流程。 --- ### 注意事项 - **硬件资源**:由于 VGG19 层次较深且参数较多,建议在具备 CUDA 支持的 GPU 上执行推理操作。 - **超参数调节**:实际应用过程中可能还需要进一步优化批量大小、学习率等超参数设置。 - **数据增强**:对于小规模数据集而言,适当引入随机裁剪、翻转等方式有助于提升泛化能力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值