Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
aish2betu committed Mar 16, 2021
0 parents commit 2f3116a
Show file tree
Hide file tree
Showing 18 changed files with 422 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.mat filter=lfs diff=lfs merge=lfs -text
74 changes: 74 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Wood Species Classification Using Vibration Signature

Acquire live data from NI data acquisition hardware in MATLAB using the Data Acquisition Toolbox and use the Deep Learning Toolbox to classify 3 different wood species (Mexican Ebony, Hard Maple and Bloodwood) based on vibrational characteristics.
This demo also uses the Wavelet Toolbox to compute continuous wavelet transform (CWT) images of the live acquired data samples. The CWT images were used to train our CNN model.

![](images/classificationGui.png)

## Wood Species

The convolution neural network (CNN) was trained on vibrational data samples acquired from 3 different varieties of wood species known as:

* Mexican Ebony
* Hard Maple
* Bloodwood

![](images/woodSpecies.PNG)

## Hardware Setup

Configure the hardware - Connect NI 9234 data acquisition module with the impact hammer and accelerometers as follows:

* Channel 0 - PCB 086C03 Impact Hammer
* Channel 1 - PCB 352C65 Accelerometer
* Channel 2 - PCB 352C65 Accelerometer
* Channel 3 - PCB 352C65 Accelerometer

Mount the 3 accelerometers on separate wood species blocks (Mexican Ebony, Hard Maple and Bloodwood).

![](images/hardwareSetup.png)

## Data Acquisition

Data Acquisition Toolbox was used to acquire vibrational signals from NI 9234 DAQ module. Data Acquisition Toolbox provides functions for configuring data acquisition hardware and reading data into MATLAB for analysis.
The toolbox supports a variety of DAQ hardware, including USB, PCI, PCI Express®, PXI®, and PXI-Express devices, from National Instruments™ and other vendors.

![](images/overviewDiag.PNG)

Thse following link provides more information about the Data Acquisition Toolbox:

https://www.mathworks.com/products/data-acquisition.html

## Signal Processing

Vibrational data from the accelerometers mounted on wood blocks was acquired using NI 9234 DAQ module in MATLAB. Signal samples were analyzed and preprocessed in MATLAB. Continuous Wavelet Transforms (CWT) were used
to generate the 2-D time-frequency maps of time series data. These time-frequency maps were used as inputs for the deep convolutional neural network (CNN). The ability of the CWT to simultaneously capture steady-state
and transient signal behavior in time series data makes the wavelet-based time-frequency representation particularly robust when paired with deep CNNs.

![](/images/waveletImage.PNG)

For more information about Wavelet Transforms and time-frequency analysis, visit the following link:

https://www.mathworks.com/help/wavelet/time-frequency-analysis.html

## Goal

* Configure Hardware
* Strike wood block with the impact hammer
* Accelerometer captures wood specific vibrational data
* Classification model predicts the type of wood based on impact

## Demo Video

This demo was showcased in MathWorks/NI virtual event. The name of the session was - Data Acquisition and Machine Learning Using MathWorks and NI Tools.
The session provides insights into a typical machine learning workflow and how one can use machine learning to classify materials followed by a live demo showcase.
Link for the virtual session:

https://gateway.on24.com/wcc/eh/2429684/lp/2748276/data-acquisition-and-machine-learning-using-mathworks-and-ni-tools

## Demo Setup

* From a list of MATLAB files in the 'wood classification demo' folder, open and run the demoSetup.m script in MATLAB. This script clears everything in MATLAB editor and sets it up for running the demo.
* To start the demo, please run the startDaq.m script.

Copyright 2021 The MathWorks, Inc.
6 changes: 6 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Reporting Security Vulnerabilities

If you believe you have discovered a security vulnerability, please report it to
[[email protected]](mailto:[email protected]). Please see
[MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html)
for additional information.
Binary file added images/classificationGui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/hardwareSetup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/overviewDiag.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/waveletImage.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/woodSpecies.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions license.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Copyright (c) 2021, The MathWorks, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file added wood classification demo/bloodWood.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions wood classification demo/classifyMaterial.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
function [classProb, A] = classifyMaterial(inputSignal)
%classifyMaterial loads the trained network, computes real time
%cwt transform, converts it to an image and predicts the classified output.

% Copyright 2021 The MathWorks, Inc.

persistent hh;
inputSignal = inputSignal';
persistent trainedNet;

% Check if trainedNet is empty
if isempty(trainedNet)
trainedNet = load('trainedNet.mat');
hh = 0;
end

if ~isfolder('liveImages')
mkdir('liveImages')
end

% Compute the signalLength
signalLength = numel(inputSignal);

% Save the input image size in variable "imgSize"
imgSize = [227 227];
imageRoot = fullfile(pwd, 'liveImages');

% Compute the cwt transform
fb = cwtfilterbank('SignalLength', signalLength, 'SamplingFrequency', 51200, 'VoicesPerOctave', 48);
[wt, ~] = fb.wt(inputSignal);

% Convert the complex wavelet transform to an uint8 RGB image
wtAbs = abs(wt);
im = ind2rgb(im2uint8(rescale(wtAbs)), jet(256));
imFileName = "Image"+ "_" + hh + ".jpg";
imwrite(imresize(im, [224 224]), char(fullfile(imageRoot,imFileName)));
A = imread(char(fullfile(imageRoot,imFileName)));
imR = imresize(A, imgSize);
hh = hh + 1;

% Run the classify function of the network on the resized image
classProb = classify(trainedNet.woodNet, imR);
end
25 changes: 25 additions & 0 deletions wood classification demo/demoSetup.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
%demoSetup function clears and set everything up for the wood classification
%demo in MATLAB

% Copyright 2021 The MathWorks, Inc.

filePath = mfilename("fullpath");
changeDir = fileparts(filePath);

% Change to current directory
cd(changeDir)

% Turn all warnings off
warning('off')
clc
% Close all currently open scripts in the editor
allscripts = matlab.desktop.editor.getAll;
close(allscripts)

% Open demo scripts
edit('materialClassificationGui.m')
edit('plotDataAvailable.m')
edit('classifyMaterial.m')
edit('startDaq.m')
makeActive(matlab.desktop.editor.findOpenDocument('startDaq.m'))

Binary file added wood classification demo/hardMaple.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions wood classification demo/materialClassificationGui.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
function hGui = materialClassificationGui(s)
%materialClassificationGui Creates a graphical user interface to display data capture.
%hGui = materialClassificationGui(s) and creates a graphical user interface, by
%programmatically creating a figure and adding required graphics
%components for visualization of data acquired from a data acquisition
%object (s).

% Copyright 2021 The MathWorks, Inc.

% Create a figure and configure a callback function (executes on window close)
hGui.Fig = figure('Name','Material Classification', ...
'NumberTitle', 'off', 'Resize', 'off', ...
'Toolbar', 'None', 'Menu', 'None',...
'Position', [100 50 870 600]);
hGui.Fig.DeleteFcn = {@endDAQ, s};
uiBackgroundColor = hGui.Fig.Color;

% Initialize the subplots
pos1 = [0.050 0.5 0.42 0.42];
hGui.Axes1 = subplot('Position',pos1);
title("Predicted Class: N/A");

pos2 = [0.53 0.5 0.42 0.42];
hGui.Axes2 = subplot('Position',pos2);
title("N/A");

pos3 = [0.1 0.1 0.3 0.3];
hGui.Axes3 = subplot('Position',pos3);

pos4 = [0.58 0.1 0.3 0.3];
hGui.Axes4 = subplot('Position',pos4);

% Create a stop acquisition button and configure a callback function
hGui.DAQButton = uicontrol('style', 'pushbutton', 'string', 'Stop DAQ',...
'units', 'pixels', 'position', [780 5 81 38]);
hGui.DAQButton.Callback = {@endDAQ, s};

hGui.txtTrigLevel = uicontrol('Style', 'text', 'String', 'Trigger Level (N)', ...
'Position', [5 5 90 19], 'HorizontalAlignment', 'left', ...
'BackgroundColor', uiBackgroundColor);
hGui.TrigLevel = uicontrol('style', 'edit', 'string', '5',...
'units', 'pixels', 'position', [105 5 56 24]);
set(hGui.txtTrigLevel,'Visible','Off')
set(hGui.TrigLevel,'Visible','Off')

% Stop DAQ callback
function endDAQ(~, ~, s)
if isvalid(s)
if s.Running
stop(s);
end
end
clear classifyMaterial;
end

end
Binary file added wood classification demo/mexicanEbony.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
137 changes: 137 additions & 0 deletions wood classification demo/plotDataAvailable.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
function plotDataAvailable(src, ~, hGui)
%plotDataAvailable function reads in data from NI 9234, extracts pre-
%defined samples, calls classification function and plots the GUI

% Copyright 2021 The MathWorks, Inc.

global sigBuffer1 sigBuffer2 nxtBufferCnt finalTrigIndex trigData1 trigData2 triggerThreshold mEbony hMaple bWood;

% Declaring variables for analyzing modalfrf(optional)
%global fs frf f

% Read data from NI DAQ 9234
[x, eventTimestamps] = read(src, src.ScansAvailableFcnCount, "OutputFormat", "Matrix");

% Impact hammer(channel 1) data
x1 = x(:,1);

%% Find the max value in each column of the channels

% Accelerometers are connected to ch2, ch3 and ch4 of NI USB 9234
dataChannels = x(:,2:4);
actChannel = max(dataChannels,[],1);
[~,idx] = max(actChannel);
x2 = x(:,idx+1);
%%
if eventTimestamps(1)==0
%frf = 0;
%f = 0;
nxtBufferCnt = 0;
trigData1 = zeros(1024,1);
trigData2 = zeros(1024,1);
mEbony = imread('mexicanEbony.jpg');
hMaple = imread('hardMaple.jpg');
bWood = imread('bloodWood.jpg');
triggerThreshold = 25;
end

% FIFO for channel 1
sigBuffer1(1:end-numel(x1)) = sigBuffer1(numel(x1)+1:end);
sigBuffer1(end-numel(x1)+1:end) = x1;

% FIFO for channel 2
sigBuffer2(1:end-numel(x2)) = sigBuffer2(numel(x2)+1:end);
sigBuffer2(end-numel(x2)+1:end) = x2;

if(nxtBufferCnt == 1)
%disp('Inside next buffer cntr condition as the prev buffer was in the last 1000 data samples');
finalTrigIndex = finalTrigIndex - numel(x1);

% Extract 1024 samples
trigData1 = sigBuffer1(finalTrigIndex - 100: finalTrigIndex + 923);
trigData2 = sigBuffer2(finalTrigIndex - 100: finalTrigIndex + 923);

% Set nxtBufferCnt as zero
nxtBufferCnt = 0;
end

% Get the trigger configuration parameters from UI text input(trigconfig level is fixed to 5N and hidden)
trigConfig.Level = sscanf(hGui.TrigLevel.String, '%f');

% Check for trigger threshold
if( any(x1 > trigConfig.Level) )
%disp("Inside trigger Condition!")
if(any(x1 > triggerThreshold))
errordlg('Impact cannot be greater than 25 Newton','Error Occured');
return
end

% Find first index of channel 1 which is above the threshold
trigIndex = find((x1 > trigConfig.Level),1,'first');

% Final trigger index is the trigIndex in x1 plus length of sigBuffer - length of x1
finalTrigIndex = trigIndex + numel(sigBuffer1) - numel(x1);

if( finalTrigIndex + 923 > numel(sigBuffer1) )
%disp("Trigger index is in last 1000 data samples");
nxtBufferCnt = 1;

else
% Capture channel 1 and channel 2 samples before and after trigger
% If 1024 samples required
trigData1 = sigBuffer1(finalTrigIndex - 100: finalTrigIndex + 923);
trigData2 = sigBuffer2(finalTrigIndex - 100: finalTrigIndex + 923);

% Modal frf (optional)
%winlen = size(trigData2,1);
%[frf, f] = modalfrf(trigData1(:), trigData2(:), fs, hann(winlen), 'Sensor', 'acc');
end
% Call classifyMaterial function to predict wood type
[classProb, A] = classifyMaterial(trigData2);

% Plot classified wood image
if (classProb == "Mexican Ebony")
pos1 = [0.050 0.5 0.42 0.42];
hGui.Axes1 = subplot('Position',pos1);
imagesc(hGui.Axes1, mEbony);
axis off;
title("Predicted Class: Mexican Ebony");
elseif (classProb == "Hard Maple")
pos1 = [0.050 0.5 0.42 0.42];
hGui.Axes1 = subplot('Position',pos1);
imagesc(hGui.Axes1, hMaple);
axis off;
title("Predicted Class: Hard Maple");
elseif (classProb == "Bloodwood")
pos1 = [0.050 0.5 0.42 0.42];
hGui.Axes1 = subplot('Position',pos1);
imagesc(hGui.Axes1, bWood);
axis off;
title("Predicted Class: Bloodwood");
end

% Plot CWT image
pos2 = [0.53 0.5 0.42 0.42];
hGui.Axes2 = subplot('Position',pos2);
imagesc(hGui.Axes2, A);
axis off;
title("Continuous Wavelet Transform Image");
end

% Plot impact hammer data
pos3 = [0.1 0.1 0.3 0.3];
hGui.Axes3 = subplot('Position',pos3);
plot(hGui.Axes3, trigData1)
title(hGui.Axes3,'Impact Hammer Data','HandleVisibility','off');
ylabel('Force (Newton)','HandleVisibility','off');
xlabel('Data samples','HandleVisibility','off');

% Plot accelerometer data
pos4 = [0.58 0.1 0.3 0.3];
hGui.Axes4 = subplot('Position',pos4);
plot(hGui.Axes4, trigData2)
title(hGui.Axes4,'Accelerometer Data','HandleVisibility','off');
ylabel('Acceleration (g)','HandleVisibility','off');
xlabel('Data samples','HandleVisibility','off');

end
Loading

0 comments on commit 2f3116a

Please sign in to comment.