【机器学习】使用Matlab和CNN完成回归任务


前言

今天我们完成一个需求:给不同图片打上一个量化的标签,将图像作为输入,量化标签(浮点数)作为输出。我们的例子为:一个柔性视觉力度传感器:随着力的大小变化,弹性体发生形变,输出即为力的大小。

本文只提供部分技术的解决方案。


一、数据集的制作

使用通常的应变力传感器来完成标定,给图片打上标签。
数据集

二、网络构建与训练

1. 图像预处理

我们相机拍摄的图片为1280x760。我们这里需要裁剪并缩小为56x56,并将其变为灰阶和二值化。

function preprocessed = preprocess(img)
    tmp = img(0:720, 240:960);
    tmp = imresize(tmp, [56, 56]);
    tmp = im2gray(tmp);
    preprocessed = imbinarize(tmp);
end

2. 训练数据生成

按照80%和20%的分组将数据集分为训练集和测试集。

function [XTrain, YTrain, XValidation, YValidation] = generateTrainData(sourcePath)
    imds = imageDatastore(sourcePath, 'IncludeSubfolders', true, 'LabelSource', 'foldernames');
    [dsTrain, dsVal] = splitEachLabel(imds, 0.8, 0.2, 'randomized');
    [XTrain, YTrain] = imds2array(dsTrain);
    [XValidation, YValidation] = imds2array(dsVal);
end

由于Matlab的回归任务需要将四维数组作为输入,我们还需要一个函数将图片集转换为4-D double数组。

function [X, T] = imds2array(imds)
    % imds2array   Convert an image datastore into a 4-D array
    %
    %   X       - Input data as an H-by-W-by-C-by-N array, where H is the
    %             height and W is the width of the images, C is the number of
    %             channels, and N is the number of images.
    %   T       - Categorical vector containing the labels for each
    %             observation.

    imagesCellArray = imds.readall();
    numImages = numel(imagesCellArray);
    [h, w, c] = size(imagesCellArray{1});

    X = zeros(h, w, c, numImages);

    for i = 1:numImages
        X(:, :, :, i) = im2double(imagesCellArray{i});
    end

    T = double(string(imds.Labels));
end

3. 网络构建

根据图片的特征,构建深度网络:
网络拓扑结构

layers = [
    imageInputLayer([56 56 1])
    convolution2dLayer(3,8,'Padding','same')
    batchNormalizationLayer
    reluLayer
    averagePooling2dLayer(2,'Stride',2)
    convolution2dLayer(3,16,'Padding','same')
    batchNormalizationLayer
    reluLayer
    averagePooling2dLayer(2,'Stride',2)
    convolution2dLayer(3,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    convolution2dLayer(3,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    dropoutLayer(0.2)
    fullyConnectedLayer(1)
    regressionLayer];

4. 指定参数并训练

miniBatchSize = 128;
validationFrequency = floor(numel(YTrain) / miniBatchSize);
options = trainingOptions('sgdm', ...
    'MiniBatchSize', miniBatchSize, ...
    'MaxEpochs', 100, ...
    'InitialLearnRate', 1e-4, ...
    'LearnRateSchedule', 'piecewise', ...
    'LearnRateDropFactor', 0.1, ...
    'LearnRateDropPeriod', 20, ...
    'Shuffle', 'every-epoch', ...
    'ValidationData', {XValidation, YValidation}, ...
    'ValidationFrequency', 10, ...
    'Plots', 'training-progress', ...
    'Verbose', false);

net = trainNetwork(XTrain, YTrain, layers, options);

三、试用网络

这里我们使用摄像头实时获取图片,需要Matlab的Image Acquisition Toolbox。
首先查询摄像机Adapter:imaqInfo = imaqhwinfo,输出:

InstalledAdaptors: {'winvideo'}
MATLABVersion: '9.11 (R2021b)'
ToolboxName: 'Image Acquisition Toolbox'
ToolboxVersion: '6.5 (R2021b)'

可以看到,存在的Adaptor只有winvideo,继续查看winvideo的信息:winvideoinfo = imaqhwinfo('winvideo'),找到DeviceInfo,并找到USB Camera的ID。我这里为1。
DeviceInfo
接下来调用相机:

vid = videoinput('winvideo', 1, 'MJPG_1280x720');
vid.TriggerRepeat = 100;
vid.FrameGrabInterval = 5;
% 加载训练好的网络
load("network.mat");
figure
hold on
i = 0;
start(vid)
while i < 2000
    if vid.FramesAvailable >= 1
        i = i + 1;
        img = getdata(vid, 1); 
        img = preprocess2(img);
        inp = img2array(img);
        out = predict(net, inp);
        plot(i, double(out)/10, 'o');
        double(out) / 10
    end
end
stop(vid)

随着按下的力度变化,采集到的力度数据变化曲线如图所示:

力度曲线
虽然值不是很准确,但是趋势是正确的。后续还需要继续调整网络结构和参数。

  • 1
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值