基于TNN的c++分类网络代码,输入是随便大小图片
时间: 2024-02-24 17:56:27 浏览: 155
C++显示网络图片
5星 · 资源好评率100%
对于输入大小不确定的图片,我们可以在分类网络中使用自适应池化层(adaptive pooling layer)来动态调整输入图片的大小,以满足分类网络的输入大小要求。具体实现方式如下:
1. 在网络定义中添加自适应池化层,例如:
```c++
tnn::Net net;
net.AddLayer(tnn::CreateLayer("Input", "", input_dims));
net.AddLayer(tnn::CreateLayer("Conv", "Conv", conv_params));
net.AddLayer(tnn::CreateLayer("ReLU", "ReLU", relu_params));
net.AddLayer(tnn::CreateLayer("AdaptivePooling", "AdaptivePooling", adaptive_pooling_params));
net.AddLayer(tnn::CreateLayer("Flatten", "Flatten", flatten_params));
net.AddLayer(tnn::CreateLayer("InnerProduct", "InnerProduct", inner_product_params));
net.AddLayer(tnn::CreateLayer("Softmax", "Softmax", softmax_params));
```
其中,adaptive_pooling_params是自适应池化层的参数,可以通过以下代码设置:
```c++
tnn::LayerParam adaptive_pooling_params;
adaptive_pooling_params.name = "AdaptivePooling";
adaptive_pooling_params.type = TNN_LAYER_ADAPTIVE_POOLING;
tnn::AdaptivePoolingLayerParam* adaptive_pooling_param = new tnn::AdaptivePoolingLayerParam();
adaptive_pooling_param->pool_type = tnn::POOLING_TYPE_AVE;
adaptive_pooling_param->output_shape.push_back(7); // 自适应池化层输出高度
adaptive_pooling_param->output_shape.push_back(7); // 自适应池化层输出宽度
adaptive_pooling_params.param = std::shared_ptr<tnn::LayerParam>(adaptive_pooling_param);
```
2. 在图像预处理中进行裁剪,以保证输入图片的长宽比与自适应池化层输出的长宽比一致,例如:
```c++
cv::Mat input_image = cv::imread("input_image.jpg");
cv::Mat resized_image;
cv::Size input_size(256, 256); // 先将图片缩放到较大的尺寸
cv::resize(input_image, resized_image, input_size);
float input_scale = 1.0 / 255; // 图像数据缩放比例
float input_mean[] = {0.485, 0.456, 0.406}; // 图像数据均值
float input_std[] = {0.229, 0.224, 0.225}; // 图像数据标准差
int input_height = resized_image.rows;
int input_width = resized_image.cols;
float input_ratio = (float)input_width / (float)input_height;
float output_ratio = (float)7 / (float)7; // 自适应池化层输出的长宽比为1:1
int crop_width, crop_height;
if (input_ratio > output_ratio) {
crop_width = input_height * output_ratio;
crop_height = input_height;
} else {
crop_width = input_width;
crop_height = input_width / output_ratio;
}
int x = (input_width - crop_width) / 2;
int y = (input_height - crop_height) / 2;
cv::Rect crop_region(x, y, crop_width, crop_height);
cv::Mat cropped_image = resized_image(crop_region);
// 将裁剪后的图片转换为TNNTensor格式
std::vector<int> input_dims = {1, 3, 7, 7}; // 输入维度为1x3x7x7
tnn::Mat input_mat(TNN_CPU, tnn::N8UC3, input_dims, cropped_image.data);
input_mat.ScaleMat(0, input_scale); // 缩放图像数据
input_mat.MeanMat(0, input_mean); // 减去均值
input_mat.DivMat(0, input_std); // 除以标准差
std::shared_ptr<tnn::Mat> input_mat_ptr = std::make_shared<tnn::Mat>(input_mat);
```
以上代码中,我们先将输入图片缩放到较大的尺寸,再根据自适应池化层的输出大小计算出需要裁剪的区域,并将图片裁剪成正确的大小。然后,我们将裁剪后的图片转换为TNNTensor格式,并进行图像预处理(缩放、减均值、除标准差),最后将TNNTensor作为输入传入分类网络即可。
阅读全文