+
+ +
+

GRAY_CNN(图片灰度化处理+图片识别)

+
+

应用概述

+
+

这里将以图片灰度化加图片识别来介绍AI+DSP应用开发的开发流程。 +其中图片灰度化可以使用DSP来完成,图片识别则使用AI来完成。 +灰度化处理使用灰度化公式来进行,图片识别使用CNN模型。

+
+
+
+

开发流程

+
+

1. 定义模型

+
+
    +
  • 图片灰度化处理过程。

  • +
+

这里实现图片灰度化,使用蓝、绿、红三个通道的值进行加权求和,计算出一个灰度值。 +这里使用的权重分别是0.114、0.587和0.299,这些数值是基于人眼对不同颜色的敏感度来选择的, +用于将彩色图像转换为灰度图像。公式为:

+
+\[Gray = B \times 0.114 + G \times 0.587 + R \times 0.299\]
+

以及定义一个Clip操作,确保灰度值在0到255之间。 +代码示例如下:

+
 1import mindspore as ms
+ 2from mindspore.train.serialization import export
+ 3import numpy as np
+ 4from mindspore import nn, ops
+ 5
+ 6class Gray(nn.Cell):
+ 7    def __init__(self):
+ 8        super(Gray, self).__init__()
+ 9        self.split = ops.Split(axis=2, output_num=3)
+10    def construct(self, x):
+11        x = self.split(x)
+12        b, g, r = x
+13        x = (
+14            b * 0.114 +
+15            g * 0.587 +
+16            r * 0.299
+17        ).squeeze(-1)
+18        x = ops.clip_by_value(x, 0, 255)
+19        return x
+
+
+
    +
  • 定义AI模型,用于图片识别。

  • +
+

这里的AI模型是卷积神经网络(CNN)。CNN主要由卷积,池化,激活等算子组成; +CNN模型架构如下表所示:

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

层级

操作类型

参数细节

输出维度

输入层

灰度图像输入

1通道,尺寸 H×W

H×W×1

卷积块1

Conv2d

输入通道:1 → 输出通道:32, 卷积核:3×3

H×W×32

ReLU激活

非线性变换

H×W×32

MaxPool2d

窗口:2×2, 步长:2

H/2×W/2×32

卷积块2

Conv2d

输入通道:32 → 输出通道:64, 卷积核:3×3

H/2×W/2×64

ReLU激活

非线性变换

H/2×W/2×64

MaxPool2d

窗口:2×2, 步长:2

H/4×W/4×64

卷积块3

Conv2d

输入通道:64 → 输出通道:128, 卷积核:3×3

H/4×W/4×128

ReLU激活

非线性变换

H/4×W/4×128

MaxPool2d

窗口:2×2, 步长:2

H/8×W/8×128

全连接层

Flatten

展平多维特征图

32768 (H/8×W/8×128)

Dense

输入:32768 → 输出:64, 激活:ReLU

64

Dense (输出层)

输入:64 → 输出:5, 无激活

5

输出层

分类结果

5类概率分布

5

+

CNN模型用于图片识别,不能直接导出模型,需要训练模型,该部分内容见: 2. 模型训练

+

定义CNN模型的代码示例如下:

+
 1import mindspore as ms
+ 2from mindspore import nn
+ 3class CNN(nn.Cell):
+ 4def __init__(self):
+ 5    super().__init__()
+ 6    self.conv1 = nn.Conv2d(1, 32, kernel_size=3, has_bias=True)
+ 7    self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
+ 8    self.conv2 = nn.Conv2d(32, 64, kernel_size=3, has_bias=True)
+ 9    self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
+10    self.conv3 = nn.Conv2d(64, 128, kernel_size=3, has_bias=True)
+11    self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
+12    self.flatten = nn.Flatten()
+13    self.dense1 = nn.Dense(32768, 64)
+14    self.dense2 = nn.Dense(64, 5)
+15    self.relu = nn.ReLU()
+16
+17def construct(self, x):
+18    x = self.relu(self.conv1(x))
+19    x = self.pool1(x)
+20    x = self.relu(self.conv2(x))
+21    x = self.pool2(x)
+22    x = self.relu(self.conv3(x))
+23    x = self.pool3(x)
+24    x = self.flatten(x)
+25    x = self.relu(self.dense1(x))
+26    x = self.dense2(x)
+27    return x
+
+
+
+
+
+

2. 模型训练

+
+

CNN模型需要进行训练才能正确识别,训练需要数据集,这里已经提前准备好数据集,放在Target文件夹下, +使用MindSpore框架进行模型训练,需要导入相关库和模块,定义数据预处理、模型结构、损失函数和优化器等。 +重新组网时,直接使用 nn.GraphCell() 接口会导致权重丢失, +可以在训练前时使用 ms.save_checkpoint() 接口保存成ckpt文件, +重新组网时,使用 ms.load_checkpoint() 接口加载ckpt文件即可。 +以下代码展示了如何加载数据集,进行10次模型训练,以及导出模型。 +训练以及导出模型代码如下:

+
 1import mindspore as ms
+ 2from mindspore.train.serialization import export
+ 3from mindspore import nn, context
+ 4import numpy as np
+ 5from PIL import Image
+ 6import mindspore.dataset as ds
+ 7from mindspore.dataset import py_transforms
+ 8import mindspore.dataset.vision as CV
+ 9from mindspore.train.callback import  LossMonitor
+10
+11batch_size = 32
+12img_size = (128, 128)
+13data_path = './Target'
+14
+15# 数据预处理
+16def rescale_to_0_1(image):
+17    return image / 255.0
+18
+19# 自定义函数,添加 color 通道维度
+20def add_channels(image):
+21    if len(image.shape) == 2:  # 单个图像,没有 cin_channel 维度
+22        image_four_channels = np.expand_dims(image, axis=0)
+23    else:
+24        pass
+25        return image
+26    return image_four_channels
+27
+28def export_cnn():
+29    context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU")
+30    resize_op = CV.Resize(img_size)
+31    rescale_transform = ms.dataset.transforms.Compose([rescale_to_0_1])
+32    f32_typecast = ms.dataset.transforms.TypeCast(ms.float32)
+33    # 将读取的 RGB 转为 GRAY 模式
+34    convert_gray = ms.dataset.vision.ConvertColor(ms.dataset.vision.ConvertMode.COLOR_RGB2GRAY)
+35
+36    transform = [convert_gray, resize_op, f32_typecast, rescale_transform, CV.HWC2CHW()]
+37    train_data = ds.ImageFolderDataset(dataset_dir=data_path, decode=True, extensions=[".JPEG", ".PNG", ".JPG"])
+38    train_data = train_data.map(input_columns="image", operations= transform)
+39    train_data = train_data.map(operations=lambda image: add_channels(image), \
+40                                    input_columns=["image"], \
+41                                    output_columns=["image"])
+42    train_data = train_data.batch(batch_size=batch_size)
+43    data_iter = train_data.create_dict_iterator()
+44    print("数据集加载完成")
+45
+46    my_model = CNN()
+47    loss = nn.CrossEntropyLoss(reduction='mean')
+48    optimizer = nn.Adam(my_model.trainable_params(), learning_rate=0.01)
+49    cnn_model = ms.Model(my_model, loss_fn=loss, optimizer=optimizer, metrics={'Accuracy': nn.Accuracy()})
+50    print("网络构建完成")
+51    num_epoch = 10
+52    cnn_model.train(num_epoch, train_data,callbacks=[LossMonitor()],dataset_sink_mode=False)
+53    inputs = ms.Tensor(np.random.randn(1, 1, 128, 128).astype(np.float32))
+54    ms.save_checkpoint(my_model, 'cnn.ckpt')
+55    export(my_model, inputs, file_name='cnn', file_format="MINDIR")
+
+
+
+
+
+

3. 重新组网

+
+

在前面章节中,我们已经完成了AI的模型的训练和导出。 +需要重新构建成一个新的网络结构,可以使用MindSpore框架的 nn.GraphCell() 接口来实现。 +该部分内容包括加载训练好的cnn模型,灰度化处理,重新构建网络结构,并导出新的模型。 +重新组网、导出模型以及测试的代码如下:

+
 1import cv2
+ 2import mindspore as ms
+ 3from mindspore.train.serialization import export
+ 4import numpy as np
+ 5from mindspore import nn, ops, context
+ 6from CNN import export_cnn
+ 7from GRAY import export_gray
+ 8from Connection import export_connection
+ 9
+10class_names = ['BRDM_2', 'BTR_60', 'SLICY', 'T62', 'ZSU_23_4']
+11class_labels = ["装甲侦察车", "装甲运输车", "不明", "坦克", "自行高炮"]
+12class GrayCNN(nn.Cell):
+13    def __init__(self):
+14        super(GrayCNN, self).__init__()
+15        self.split = ops.Split(axis=2, output_num=3)
+16        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, has_bias=True)
+17        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
+18        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, has_bias=True)
+19        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
+20        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, has_bias=True)
+21        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
+22        self.flatten = nn.Flatten()
+23        self.dense1 = nn.Dense(32768, 64)
+24        self.dense2 = nn.Dense(64, 5)
+25        self.relu = nn.ReLU()
+26        self.cnn = nn.GraphCell(ms.load(file_name="cnn.mindir"))
+27    def construct(self, x):
+28        x = self.split(x)
+29        b, g, r = x
+30        x = (
+31            b * 0.114 +
+32            g * 0.587 +
+33            r * 0.299
+34        ).squeeze(-1)
+35        x = ops.clip_by_value(x, 0, 255)
+36        x = x / 255.0   # 数据归一化
+37        x = x.reshape(1, 1, 128, 128)   # 灰度化处理后结果需要重塑成cnn输入形状
+38        x = self.cnn(x)
+39        return x
+40
+41if __name__ == "__main__":
+42    export_cnn()
+43    context.set_context(mode=context.GRAPH_MODE)
+44    # 1. 读取图片(保持原始uint8类型)
+45    color_image = cv2.imread("image_origin.jpg")  # 默认uint8
+46    resized_image = cv2.resize(
+47        color_image,
+48        (128, 128),  # 目标尺寸(width, height)
+49        interpolation=cv2.INTER_LINEAR
+50    )
+51    resized_image = resized_image.astype(np.float32)
+52    resized_image_tensor = ms.Tensor(resized_image)
+53
+54    my_model = GrayCNN()
+55    param_dict = ms.load_checkpoint("cnn.ckpt")
+56    param_not_load, _ = ms.load_param_into_net(my_model, param_dict, strict_load=True)
+57
+58    input_tensor = ms.Tensor(np.ones((128, 128, 3), dtype=np.float32))
+59    export(my_model, input_tensor, file_name='gray_cnn', file_format='MINDIR')
+60
+61    reload_cnn = nn.GraphCell(ms.load(file_name='gray_cnn.mindir'))
+62    reload_cnn = ms.Model(reload_cnn)
+63    m = reload_cnn.predict(resized_image_tensor)
+64    print(m)
+65    output_np = m.asnumpy()
+66    if len(output_np.shape) == 2:  # 对于分类任务,通常输出是[batch_size, num_classes]
+67        output_prob = np.exp(output_np) / np.exp(output_np).sum(axis=1, keepdims=True)
+68        predicted_class = np.argmax(output_prob, axis=1)
+69        print(f"预测结果: {class_labels[predicted_class[0]]}")
+
+
+

该代码首先定义了一个新的网络结构GrayCNN, +在 construct 方法中,首先通过gray模型处理输入图像,然后通过归一化和重塑张量,最后cnn模型进行识别。 +在主函数中,首先导出cnn模型。 +然后加载cnn模型参数,并使用MindSpore的 export 方法导出新的网络结构。 +最后,使用重新组网后的模型进行预测,并输出结果。

+
+
+
+

4. 转换模型

+
+

在前面的代码中,我们已经使用了 export 方法导出了gray_cnn.mindir模型。 +要将该模型部署到FT78NE平台,需要将MINDIR格式转换成mindspore lite的ms格式模型。 +要将该模型转换为ms格式,可以使用MindSpore的转换工具(converter_lite)。 +该工具已经集成在我们的 YHFT-IDE 中,可以直接在IDE中使用。或者也可以使用命令行工具进行转换。

+

转换命令如下:

+
./converter_lite --fmk=MINDIR --modelFile=gray_cnn.mindir --outputFile=gray_cnn
+
+
+

转换完成后,会在当前目录下生成gray_cnn.ms模型文件。该模型可以使用可视化工具(netron)可以打开该文件,查看模型结构。 +该工具可以直接在 YHFT-IDE 中使用,可以从官网下载使用,也可以在线使用。在线地址为:https://netron.app/

+

该模型文件可视化如图所示:

+gray_cnn模型结构图 +
+
+
+

5. 部署和运行程序

+
+
    +
  • 在IDE中新建一个Python项目,将下面的 python完整代码示例 代码拷贝到项目中,并运行。 +运行成功后,会在当前目录下生成一个名为 gray_cnn.midir 的模型文件,以及输出图片的预测结果。 +结果如图所示:

    +python运行结果 +

    将该文件转换为ms格式,并将ms格式模型和测试图片拷贝到FT78NE平台中。

    +
  • +
  • 打开 YHFT-IDE ,新建工程。输入工程名、路径,工程类型选择 Heterogeneous , +输入交叉编译工具路径,然后点确定。会生成一个异构模板工程。通过修改 data_handler.cc 文件中的函数来调整输入输出数据, +输入改成读取的图片路径;输出改成相应的后处理。在 main 函数设置运行后端;修改 CMakeLists.txt 文件, +添加openCV库的lib和include路径, 最后编译该工程,编译成功后将build文件夹下的 main 拷贝到FT78NE平台中, +要和gray_cnn.ms模型同一个文件夹下。

    +

    输入的c++代码示例如下:

    +
  • +
+
 1#include <opencv2/opencv.hpp>
+ 2int readImage(float *reslut, std::string imagePath) {
+ 3    cv::Mat color_image = cv::imread(imagePath.c_str(), cv::IMREAD_COLOR);
+ 4    if (color_image.empty()) {
+ 5        fprintf(stderr, "read image failed\n");
+ 6        return -1;
+ 7    }
+ 8
+ 9    int width = 128;
+10    int height = 128;
+11    cv::Mat resized_image;
+12    cv::resize(color_image, resized_image, cv::Size(width, height), 0, 0, cv::INTER_LINEAR);
+13    resized_image.convertTo(resized_image, CV_32F);
+14    const int channels = resized_image.channels();
+15    const int element_count = width * height * channels;
+16
+17    for (int i = 0; i < height; ++i) {
+18        const float *src_ptr = resized_image.ptr<float>(i);
+19        float *dst_ptr = reslut + i * width * channels;
+20        std::memcpy(dst_ptr, src_ptr, width * channels * sizeof(float));
+21    }
+22    return 0;
+23}
+
+
+

设置后端代码如下:

+
1auto context = std::make_shared<mindspore::Context>();
+2auto &device_list = context->MutableDeviceInfo();
+3context->SetBuiltInDelegate(mindspore::DelegateMode::kPNNA);
+4auto cpu_info = std::make_shared<mindspore::CPUDeviceInfo>();
+5auto dsp_info = std::make_shared<mindspore::FT78NEDeviceInfo>();
+6device_list.push_back(dsp_info);
+7device_list.push_back(cpu_info);
+
+
+

输出结果后处理代码如下:

+
 1std::vector<float> floatArrayToVector(const float *array, size_t size) {
+ 2    std::vector<float> vec(array, array + size);
+ 3    return vec;
+ 4}
+ 5
+ 6std::vector<float> numpy_exp(const std::vector<float> &x) {
+ 7    std::vector<float> result;
+ 8    result.reserve(x.size());
+ 9    for (float num : x) {
+10        result.push_back(exp(num));
+11    }
+12    return result;
+13}
+14
+15float sum_rows(const std::vector<float> &vec, int axis) {
+16    float sum = std::accumulate(vec.begin(), vec.end(), 0.0);
+17    return sum;
+18}
+19
+20std::vector<std::vector<float>> convertTo2D(const std::vector<float> &vec, int rows) {
+21    std::vector<std::vector<float>> result;
+22    if (vec.empty() || rows <= 0) {
+23        return result;
+24    }
+25    int cols = (vec.size() + rows - 1) / rows;  // 计算列数
+26    for (int i = 0; i < rows; ++i) {
+27        std::vector<float> row;
+28        for (int j = 0; j < cols; ++j) {
+29        size_t index = i * cols + j;  // 计算索引
+30        if (index < vec.size()) {
+31            row.push_back(vec[index]);
+32        } else {
+33            row.push_back(0);  // 填充剩余空间,或者你可以选择不填充
+34        }
+35        }
+36        result.push_back(row);
+37    }
+38    return result;
+39}
+40
+41void GetOutputData(std::vector<MSTensor> &outputs) {
+42    for (auto tensor : outputs) {
+43        std::cout << "tensor name is:" << tensor.Name() << " tensor size is:" << tensor.DataSize()
+44                << " tensor elements num is:" << tensor.ElementNum() << std::endl;
+45        auto out_data = reinterpret_cast<const float *>(tensor.Data().get());
+46        std::cout << "output data is:";
+47        for (int i = 0; i < tensor.ElementNum() && i <= 50; i++) {
+48        std::cout << out_data[i] << " ";
+49        }
+50        std::cout << std::endl;
+51        std::vector<float> out = floatArrayToVector(out_data, tensor.ElementNum());
+52        std::vector<float> exp_x = numpy_exp(out);
+53        float sums = sum_rows(exp_x, 1);
+54        std::vector<float> x1;
+55        for (float num : exp_x) {
+56            x1.push_back(num / sums);
+57        }
+58        std::vector<std::vector<float>> twoD = convertTo2D(x1, 1);
+59        std::vector<int> argmax_indices = argmax(twoD);
+60        std::vector<std::string> Predicted_class = {"装甲侦察车", "装甲运输车", "不明", "坦克", "自行高炮"};
+61        std::cout << "预测结果: " << Predicted_class[argmax_indices[0]] << std::endl;
+62    }
+63}
+
+
+
    +
  • 在FT78NE上运行可执行文件 main ,观察输出结果。与预期结果对比,验证模型推理的正确性。 +执行命令如下:

    +
    1./main gray_cnn.ms image_origin.jpg
    +
    +
    +
  • +
+

执行结果如下图:

+FT78NE运行结果 +
+
+
+
+

python完整代码示例

+
+
 1# CNN.py
+ 2import mindspore as ms
+ 3from mindspore.train.serialization import export
+ 4from mindspore import nn, context
+ 5import numpy as np
+ 6from PIL import Image
+ 7import mindspore.dataset as ds
+ 8from mindspore.dataset import py_transforms
+ 9import mindspore.dataset.vision as CV
+10from mindspore.train.callback import  LossMonitor
+11
+12# # Define directories and parameters
+13batch_size = 32
+14img_size = (128, 128)
+15data_path = '../cnn-sar/Target'
+16
+17# 数据预处理
+18def rescale_to_0_1(image):
+19    return image / 255.0
+20
+21# 自定义函数,添加 color 通道维度
+22def add_channels(image):
+23    if len(image.shape) == 2:  # 单个图像,没有 cin_channel 维度
+24        # print("before ===> ", image.shape)
+25        # 添加 color 通道维度,(128x128) => (1, 128, 128)
+26        image_four_channels = np.expand_dims(image, axis=0)
+27        # print("after  ===> ", image_four_channels.shape)
+28    else:
+29        pass
+30        return image
+31    return image_four_channels
+32
+33class CNN(ms.nn.Cell):
+34    def __init__(self):
+35        super().__init__()
+36        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, has_bias=True)
+37        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
+38        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, has_bias=True)
+39        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
+40        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, has_bias=True)
+41        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
+42        self.flatten = nn.Flatten()
+43        self.dense1 = nn.Dense(32768, 64)
+44        self.dense2 = nn.Dense(64, 5)
+45        self.relu = nn.ReLU()
+46
+47    def construct(self, x):
+48        x = self.relu(self.conv1(x))
+49        x = self.pool1(x)
+50        x = self.relu(self.conv2(x))
+51        x = self.pool2(x)
+52        x = self.relu(self.conv3(x))
+53        x = self.pool3(x)
+54        x = self.flatten(x)
+55        x = self.relu(self.dense1(x))
+56        x = self.dense2(x)
+57        return x
+58
+59def export_cnn():
+60    context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU")
+61    resize_op = CV.Resize(img_size)
+62    rescale_transform = ms.dataset.transforms.Compose([rescale_to_0_1])
+63    f32_typecast = ms.dataset.transforms.TypeCast(ms.float32)
+64    # 将读取的 RGB 转为 GRAY 模式
+65    convert_gray = ms.dataset.vision.ConvertColor(ms.dataset.vision.ConvertMode.COLOR_RGB2GRAY)
+66
+67    transform = [convert_gray, resize_op, f32_typecast, rescale_transform, CV.HWC2CHW()]
+68    train_data = ds.ImageFolderDataset(dataset_dir=data_path, decode=True, extensions=[".JPEG", ".PNG", ".JPG"])
+69    train_data = train_data.map(input_columns="image", operations= transform)
+70    train_data = train_data.map(operations=lambda image: add_channels(image), \
+71                                    input_columns=["image"], \
+72                                    output_columns=["image"])
+73    train_data = train_data.batch(batch_size=batch_size)
+74    data_iter = train_data.create_dict_iterator()
+75    print("数据集加载完成")
+76    my_model = CNN()
+77    loss = nn.CrossEntropyLoss(reduction='mean')
+78    optimizer = nn.Adam(my_model.trainable_params(), learning_rate=0.01)
+79    cnn_model = ms.Model(my_model, loss_fn=loss, optimizer=optimizer, metrics={'Accuracy': nn.Accuracy()})
+80    print("网络构建完成")
+81    num_epoch = 10
+82    cnn_model.train(num_epoch, train_data,callbacks=[LossMonitor()],dataset_sink_mode=False)
+83    inputs = ms.Tensor(np.random.randn(1, 1, 128, 128).astype(np.float32))
+84    ms.save_checkpoint(my_model, 'cnn.ckpt')
+85    export(my_model, inputs, file_name='cnn', file_format="MINDIR")
+
+
+
 1# GRAY_CNN.py
+ 2import cv2
+ 3import mindspore as ms
+ 4from mindspore.train.serialization import export
+ 5import numpy as np
+ 6from mindspore import nn, ops, context
+ 7from CNN import export_cnn
+ 8
+ 9class_names = ['BRDM_2', 'BTR_60', 'SLICY', 'T62', 'ZSU_23_4']
+10class_labels = ["装甲侦察车", "装甲运输车", "不明", "坦克", "自行高炮"]
+11
+12class GrayCNN(nn.Cell):
+13    def __init__(self):
+14        super(GrayCNN, self).__init__()
+15        self.split = ops.Split(axis=2, output_num=3)
+16        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, has_bias=True)
+17        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
+18        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, has_bias=True)
+19        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
+20        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, has_bias=True)
+21        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
+22        self.flatten = nn.Flatten()
+23        self.dense1 = nn.Dense(32768, 64)
+24        self.dense2 = nn.Dense(64, 5)
+25        self.relu = nn.ReLU()
+26        self.cnn = nn.GraphCell(ms.load(file_name="cnn.mindir"))
+27
+28    def construct(self, x):
+29        x = self.split(x)
+30        b, g, r = x
+31        x = (
+32            b * 0.114 +
+33            g * 0.587 +
+34            r * 0.299
+35        ).squeeze(-1)
+36        x = ops.clip_by_value(x, 0, 255)
+37        x = x / 255.0   # 数据归一化
+38        x = x.reshape(1, 1, 128, 128)   # 灰度化处理后结果需要重塑成cnn输入形状
+39        x = self.cnn(x)
+40        return x
+41
+42if __name__ == "__main__":
+43    export_gray()
+44    export_connection()
+45    export_cnn()
+46    context.set_context(mode=context.GRAPH_MODE)
+47    # 1. 读取图片(保持原始uint8类型)
+48    color_image = cv2.imread("image_origin.jpg")  # 默认uint8
+49    resized_image = cv2.resize(
+50        color_image,
+51        (128, 128),  # 目标尺寸(width, height)
+52        interpolation=cv2.INTER_LINEAR
+53    )
+54    resized_image = resized_image.astype(np.float32)
+55    resized_image_tensor = ms.Tensor(resized_image)
+56    my_model = GrayCNN()
+57    param_dict = ms.load_checkpoint("cnn.ckpt")
+58    param_not_load, _ = ms.load_param_into_net(my_model, param_dict, strict_load=True)
+59    input_tensor = ms.Tensor(np.ones((128, 128, 3), dtype=np.float32))
+60    export(my_model, input_tensor, file_name='gray_cnn', file_format='MINDIR')
+61    reload_cnn = nn.GraphCell(ms.load(file_name='gray_cnn.mindir'))
+62    reload_cnn = ms.Model(reload_cnn)
+63    m = reload_cnn.predict(resized_image_tensor)
+64    print(m)
+65    output_np = m.asnumpy()
+66    if len(output_np.shape) == 2:  # 对于分类任务,通常输出是[batch_size, num_classes]
+67        output_prob = np.exp(output_np) / np.exp(output_np).sum(axis=1, keepdims=True)
+68        predicted_class = np.argmax(output_prob, axis=1)
+69        print(f"预测结果: {class_labels[predicted_class[0]]}")
+
+
+
+
+
+ + +
+