Jiro‘s Pick this week is Plot Gui 2d by Silas Henderson.

This entry is one of many interactive apps that Silas has created, and I had been quite intrigued by many of his entries. I chose to highlight “Plot GUI 2d” because of its simple, but useful application for teaching mathematical concepts. Visualization helps students understand concepts, and animation increases that understanding.

Silas includes a YouTube video showing the app in action, so I will simply reference it here.

A few highlights regarding the code:

- Silas uses local functions in his
**script**. This is a relatively new feature introduced in R2016b, so I’m happy to see that being used. - He uses “KeyPressFcn” property of the figure to capture key presses, which control the zooming and panning of the graph.
- He animates the lines by changing the
`XData`and`YData`properties of the line objects, instead of re-plotting the lines. This is the recommended way of doing efficient animation.`animatedline`is another feature that could be useful.

I have one suggestion for Silas. He wrote this using a script, with a global variable to be shared amongst some of his local functions. For such purpose, I prefer using a function, with nested functions. When you do that, the life cycle of the app is with the figure, so it will continue to work so long as the figure is open, even if you do a ” `clear all` ” in the command line.

**Comments**

Give it a try and let us know what you think here or leave a comment for Silas.

Get
the MATLAB code

Published with MATLAB® R2019b

Greg’s pick this week is Generate JavaScript Using MATLAB Coder by Geoff McVittie.

You are building a game where you want to model Einsteinian relativistic physics as part of an online learning tool. The interface is designed in HTML, CSS, and Javascript, but you prototyped the computational algorithms in MATLAB.

You know you can generate C-code from MATLAB….but you can’t deploy that as part of a web application as it won’t run in the web browser.

Do you have to rewrite the entire algorithm in Javascript? Or run the computational algorithm as a remote service?

Enter Emscripten, a transpiler that compiles C/C++ code as WebAssembly with a Javascript interface.

Geoff took this one step further, and created a code generation target for MATLAB Coder that automates the process of converting the algorithm to C-code, compiling it to Web Assembly, and creating the Javascript interface.

That’s a fair question. Technically there’s nothing preventing you from doing that.

I argue its easier to create, manage, and process arrays of data and equations in MATLAB. So writing the algorithm may be simpler.

However, data synthesis is the part I find most valuable. It is very easy to synthesize data in MATLAB for the purposes of testing our algorithms and ideas. I can very easily create different synthetic datasets, import data from different files, and create test cases for exciting our MATLAB algorithms.

When I’ve had to do this for various reasons in other languages like C, C#, and Javascript, I find myself struggling to generate suites of input data, and quickly being able to assess the results. My favorite debugging tool in MATLAB is PLOT, where I can quickly take a look at my data as a graph to see how my algorithm is behaving.

The kind of features needed to create datasets, read datafiles, or review output results need to be created in these other lower-level languages, which makes testing complex computational algorithms trickier.

Geoff has created a complete package that includes:

- Documentation
- Examples
- Easy setup instructions

In addition he has added some features that enable you to target different types of code entrypoints that you would find in web applications, like mouse event callbacks.

He also included some functions that enable basic debugging once the code is deployed to the browser, like the ability to print messages in the developer console of your web browser.

Let us know here.

]]>Sean‘s pick this week is Minimal Bounding Box by Johannes Korsawe. I was recently asked by a customer “How can I replicate the flatness measurements from a CMM... read more >>

]]>Sean‘s pick this week is Minimal Bounding Box by Johannes Korsawe.

I was recently asked by a customer “How can I replicate the flatness measurements from a CMM machine?” A coordinate measuring machine measures geometric properties of an object.

A quick internet search, took me to this site which introduced two methods. The customer wanted the “Minimum Zone” method, sometimes also referred to as parallel planes. This essentially boils down to “fit a minimum bounding box and calculate the distance between the top and bottom of the box”.

I knew it must be possible to to formulate this as an optimization routine whether something linear that `linprog` could handle or nonlinear with linear constraints enforcing for `fmincon`. A quick search of the File Exchange yielded Johannes’ file which does exactly what was needed. It also provides a plotting routine to help validate and understand the output.

Here’s an example of what worked, using random numbers in place of the CMM measurements.

npts = 10; % Number of points from CMM machine. x = randi(100, npts, 1)+randn(npts, 1); y = randi(100, npts, 1)+randn(npts, 1); z = rand(npts, 1); [~, cornerpts] = minboundbox(x, y, z); scatter3(x, y, z); hold on plotminbox(cornerpts, 'r');

To calculate flatness, I just need to calculate the distance between a top and bottom point. I wasn’t sure if the point order was deterministic so it’s easier to just calculate the closest point on the opposite plane from a chosen one.

bottompt = cornerpts(1,:); [~, topidx] = min(hypot(cornerpts(2:end,1)-bottompt(1), cornerpts(2:end,2)-bottompt(2))); toppt = cornerpts(topidx+1,:); hold on scatter3(bottompt(1), bottompt(2), bottompt(3), 'b*') scatter3(toppt(1), toppt(2), toppt(3), 'g*')

Computing the distance can be done with a couple calls to `hypot`.

```
planesep = hypot(hypot(toppt(1)-bottompt(1), toppt(2)-bottompt(2)), toppt(3)-bottompt(3));
disp("Plane separation is: " + planesep)
```

Plane separation is: 0.55053

Give it a try and let us know what you think here or leave a comment for Johannes.

Published with MATLAB® R2019b

]]>Jiro‘s Pick this week is spider_plot by Moses.There are quite a few “spider plots” on the File Exchange, but this one by Moses caught my attention for a few reasons.Moses... read more >>

]]>Jiro‘s Pick this week is `spider_plot` by Moses.

There are quite a few “spider plots” on the File Exchange, but this one by Moses caught my attention for a few reasons.

- Moses includes a detailed help inside the function.

```
help spider_plot
```

spider_plot Create a spider or radar plot with individual axes. Syntax: spider_plot(P) spider_plot(___, Name, Value) Input Arguments: (Required) P - The data points used to plot the spider chart. The rows are the groups of data and the columns are the data points. The axes labels and axes limits are automatically generated if not specified. [vector | matrix] Name-Value Pair Arguments: (Optional) AxesLabels - Used to specify the label each of the axes. [auto-generated (default) | cell of strings | 'none'] AxesInterval - Used to change the number of intervals displayed between the webs. [3 (default) | integer] AxesPrecision - Used to change the precision level on the value displayed on the axes. Enter in 'none' to remove axes text. [1 (default) | integer | 'none'] AxesLimits - Used to manually set the axes limits. A matrix of 2 x size(P, 2). The top row is the minimum axes limits and the bottow row is the maximum axes limits. [auto-scaled (default) | matrix] FillOption - Used to toggle color fill option. ['off' (default) | 'on'] FillTransparency - Used to set color fill transparency. [0.1 (default) | scalar in range (0, 1)] Color - Used to specify the line color, specified as an RGB triplet. The intensities must be in the range (0, 1). [MATLAB colors (default) | RGB triplet] LineStyle - Used to change the line style of the plots. ['-' (default) | '--' | ':' | '-.' | 'none'] LineWidth - Used to change the line width, where 1 point is 1/72 of an inch. [0.5 (default) | positive value] Marker - Used to change the marker symbol of the plots. ['o' (default) | 'none' | '*' | 's' | 'd' | ...] MarkerSize - Used to change the marker size, where 1 point is 1/72 of an inch. [8 (default) | positive value] FontSize - Used to change the font size of the labels and values displayed on the axes. [10 (default) | scalar value greater than zero] Examples: % Example 1: Minimal number of arguments. All non-specified, optional arguments are set to their default values. Axes labels and limits are automatically generated and set. D1 = [5 3 9 1 2]; % Initialize data points D2 = [5 8 7 2 9]; D3 = [8 2 1 4 6]; P = [D1; D2; D3]; spider_plot(P); legend('D1', 'D2', 'D3', 'Location', 'southoutside'); % Example 2: Manually setting the axes limits. All non-specified, optional arguments are set to their default values. axes_limits = [1, 2, 1, 1, 1; 10, 8, 9, 5, 10]; % Axes limits [min axes limits; max axes limits] spider_plot(P,... 'AxesLimits', axes_limits); % Example 3: Set fill option on. The fill transparency can be adjusted. axes_labels = {'S1', 'S2', 'S3', 'S4', 'S5'}; % Axes properties axes_interval = 2; fill_option = 'on'; fill_transparency = 0.1; spider_plot(P,... 'AxesLabels', axes_labels,... 'AxesInterval', axes_interval,... 'FillOption', fill_option,... 'FillTransparency', fill_transparency); % Example 4: Maximum number of arguments. axes_labels = {'S1', 'S2', 'S3', 'S4', 'S5'}; % Axes properties axes_interval = 4; axes_precision = 'none'; axes_limits = [1, 2, 1, 1, 1; 10, 8, 9, 5, 10]; fill_option = 'on'; fill_transparency = 0.2; colors = [1, 0, 0; 0, 1, 0; 0, 0, 1]; line_style = '--'; line_width = 3; marker_type = 'd'; marker_size = 10; font_size = 12; spider_plot(P,... 'AxesLabels', axes_labels,... 'AxesInterval', axes_interval,... 'AxesPrecision', axes_precision,... 'AxesLimits', axes_limits,... 'FillOption', fill_option,... 'FillTransparency', fill_transparency,... 'Color', colors,... 'LineStyle', line_style,... 'LineWidth', line_width,... 'Marker', marker_type,... 'MarkerSize', marker_size,... 'FontSize', font_size); Author: Moses Yoo, (jyoo at hatci dot com) 2019-10-16: Minor revision to add name-value pairs for customizing color, marker, and line settings. 2019-10-08: Another major revision to convert to name-value pairs and add color fill option. 2019-09-17: Major revision to improve speed, clarity, and functionality Special Thanks: Special thanks to Gabriela Andrade & Andrﾃｩs Garcia for their feature recommendations and suggested bug fixes.

- He includes a Live Script example that showcases various use cases

- He is very active in his communications with his users in the comments section and is also very diligent about updating the entry.

- And finally, his function is another example where the new Function Argument Validation feature would be handy.

I’m thrilled to see a nice piece of code with robust error-checking. He has roughly 100 lines of code just for error checking the inputs to his function. He also sets default values for the optional arguments.

Here is the input argument processing/error checking piece of the code.

%%% Data Properties %%% % Point properties [num_data_groups, num_data_points] = size(P); % Number of optional arguments numvarargs = length(varargin); % Check for even number of name-value pair argments if mod(numvarargs, 2) == 1 error('Error: Please check name-value pair arguments'); end % Create default labels axes_labels = cell(1, num_data_points); % Iterate through number of data points for ii = 1:num_data_points % Default axes labels axes_labels{ii} = sprintf('Label %i', ii); end % Default arguments axes_interval = 3; axes_precision = 1; axes_limits = []; fill_option = 'off'; fill_transparency = 0.2; colors = [0, 0.4470, 0.7410;... 0.8500, 0.3250, 0.0980;... 0.9290, 0.6940, 0.1250;... 0.4940, 0.1840, 0.5560;... 0.4660, 0.6740, 0.1880;... 0.3010, 0.7450, 0.9330;... 0.6350, 0.0780, 0.1840]; line_style = '-'; line_width = 2; marker_type = 'o'; marker_size = 8; font_size = 10; % Check if optional arguments were specified if numvarargs > 1 % Initialze name-value arguments name_arguments = varargin(1:2:end); value_arguments = varargin(2:2:end); % Iterate through name-value arguments for ii = 1:length(name_arguments) % Set value arguments depending on name switch lower(name_arguments{ii}) case 'axeslabels' axes_labels = value_arguments{ii}; case 'axesinterval' axes_interval = value_arguments{ii}; case 'axesprecision' axes_precision = value_arguments{ii}; case 'axeslimits' axes_limits = value_arguments{ii}; case 'filloption' fill_option = value_arguments{ii}; case 'filltransparency' fill_transparency = value_arguments{ii}; case 'color' colors = value_arguments{ii}; case 'linestyle' line_style = value_arguments{ii}; case 'linewidth' line_width = value_arguments{ii}; case 'marker' marker_type = value_arguments{ii}; case 'markersize' marker_size = value_arguments{ii}; case 'fontsize' font_size = value_arguments{ii}; otherwise error('Error: Please enter in a valid name-value pair.'); end end end %%% Error Check %%% % Check if axes labels is a cell if iscell(axes_labels) % Check if the axes labels are the same number as the number of points if length(axes_labels) ~= num_data_points error('Error: Please make sure the number of labels is the same as the number of points.'); end else % Check if valid string entry if ~strcmp(axes_labels, 'none') error('Error: Please enter in valid labels or "none" to remove labels.'); end end % Check if axes limits is not empty if ~isempty(axes_limits) % Check if the axes limits same length as the number of points if size(axes_limits, 1) ~= 2 || size(axes_limits, 2) ~= num_data_points error('Error: Please make sure the min and max axes limits match the number of data points.'); end end % Check if axes precision is string if ~ischar(axes_precision) % Check if axes properties are an integer if floor(axes_interval) ~= axes_interval || floor(axes_precision) ~= axes_precision error('Error: Please enter in an integer for the axes properties.'); end % Check if axes properties are positive if axes_interval < 1 || axes_precision < 1 error('Error: Please enter value greater than one for the axes properties.'); end else % Check if axes precision is valid string entry if ~strcmp(axes_precision, 'none') error('Error: Invalid axes precision entry. Please enter in "none" to remove axes text.'); end end % Check if not a valid fill option arguement if ~ismember(fill_option, {'off', 'on'}) error('Error: Please enter either "off" or "on" for fill option.'); end % Check if fill transparency is valid if fill_transparency < 0 || fill_transparency > 1 error('Error: Please enter a transparency value between [0, 1].'); end % Check if font size is greater than zero if font_size <= 0 error('Error: Please enter a font size greater than zero.'); end

This can be converted into an arguments block.

arguments P (:,:) double options.AxesLabels {validateAxesLabels(options.AxesLabels,P)} = cellstr("Label " + (1:size(P,2))) options.AxesInterval (1,1) double {mustBeInteger} = 3 options.AxesPrecision {validateAxesPrecision(options.AxesPrecision)} = 1 options.AxesLimits double {validateAxesLimits(options.AxesLimits,P)} = [] options.FillOption char {mustBeMember(options.FillOption,{'off','on'})} = 'off' options.FillTransparency (1,1) double {mustBeGreaterThanOrEqual(options.FillTransparency,0),mustBeLessThanOrEqual(options.FillTransparency,1)} = 0.1 options.Color (:,3) double {mustBeGreaterThanOrEqual(options.Color,0),mustBeLessThanOrEqual(options.Color,1)} = get(groot,'defaultAxesColorOrder') options.LineStyle char {mustBeMember(options.LineStyle,{'-','--',':','-.','none'})} = '-' options.LineWidth (1,1) double {mustBePositive} = 2 options.Marker char {mustBeMember(options.Marker,{'+','o','*','.','x','square','s','diamond','d','v','^','>','<','pentagram','p','hexagram','h','none'})} = 'o' options.MarkerSize (1,1) double {mustBePositive} = 8 options.FontSize (1,1) double {mustBePositive} = 10 end

I also created custom validation functions for few of the arguments.

function validateAxesPrecision(x) if isnumeric(x) validateattributes(x,{'double'},{'scalar','integer'},mfilename,'AxesPrecision') else if ~isequal(x,'none') error('AxesPrecision must be a scalar integer or ''none''') end end end function validateAxesLimits(axLim,P) if ~isempty(axLim) validateattributes(axLim,{'double'},{'size',[2 size(P,2)]},mfilename,'AxesLimits') end end function validateAxesLabels(axLabels,P) if ~isequal(axLabels,'none') validateattributes(axLabels,{'cell'},{'size',[1 size(P,2)]},mfilename,'AxesLabels') end end

These changes reduced the number of lines in the code from 500 to 400. Pretty neat!

**Comments**

Give it a try and let us know what you think here or leave a comment for Moses.

Get
the MATLAB code

Published with MATLAB® R2019b

Richard is Consulting Engineer at MathWorks focused on the Embedded Coder product for code generation, primarily in the Aerospace industry.Richard’s pick this week is add_Data_Tips by Massimo... read more >>

]]>*Richard is Consulting Engineer at MathWorks focused on the Embedded Coder product for code generation, primarily in the Aerospace industry.*

Richard’s pick this week is add_Data_Tips by Massimo Ciacci.

My pick this week is the utility function add_Data_Tips for programmatically adding data tips to multiple lines in a plot.

If you write custom scripts/functions to plot data it is often beneficial to highlight specific points in the plot such as minimums/maximums. Datatips allow you to show the values of the data at selected locations in the figure.

While you can add data tips to a plot manually, it is difficult to add data tips to multiple lines at the same location on the X-axis. **add_Data_Tips** solves this problem. Using add_Data_Tips, you can insert data tips on multiple lines in a plot at a specified X-axis locations. For instance, if you want to call out the maximum value of a plot, you can use the max function to find the index of the maximum value of the Y-Axis data and specify the corresponding X-Axis data in the call to **add_Data_Tips** to insert a data tip in the figure at the maximum point.

n = 0:50; y = cos(.5*(n)).^3 + sin(.3*(n)).^2; figure yh = plot(n, y); [~,indx] = max(y); add_DataTips( n(indx) , yh, 7)

If you have a figure with multiple plots, you can add data tips to any or all of the lines at the same X-Axis location by passing in the handles to the desired lines.

```
n = 0:50;
y = cos(.5*(n)).^3 + sin(.3*(n)).^2;
figure
yh(1) = plot(n, y);
hold on
y2 = sin(1.5*(n)).^3 - cos(1.3*(n)).^2;
yh(2) = plot(n,y2);
[~,indx] = max(y);
add_DataTips( n(indx) , yh, 7)
```

If you already have a plot, you can get the handles to the lines by accessing the Children of the axes

CurrentAxes = gca; LinesHandles = CurrentAxes.Children; x_location = 10; add_DataTips(x_location , LinesHandles, 7)

You can use the examples above or the File Exchange submission includes a demo script, ‘test_add_DataTips.m’, that provides an example.

If you have access to the most recent release, R2019b, you can now programmatically create datatips using the new `datatip` function.

```
figure
yh = plot(n, y);
[~,indx] = max(y);
datatip(yh,'DataIndex', indx);
```

Give it a try and let us know what you think here or leave a comment for Massimo.

Get
the MATLAB code

Published with MATLAB® R2019b

Sean‘s pick this week is `leafpile` by Nathaniel Barlow.

As we’re *finally* starting to see cooler temperatures in New England, the leaves are starting to turn. This fun submission allows MATLAB to make a pile of leaves for you to rake or have your virtual dog play in.

To play with this, I’m going to make a simple one line live script with controls to make it so I can play with the settings. I’ll then hide the code so we can just play with the controls and make leaf piles.

Now let’s do a quick code review of the input parsing step that is used in `leafpile`. This is the relevant part:

function leafpile(N,type) %leafpile(leaves,type) makes a random pile of N leaves % of type 'oak' or 'maple'. N. Barlow 9/28/19 %leafpile(N) makes a mixed pile of N leves. %leafpile makes a pile of 70 mixed leaves. %The mathematical functions describing the leaf shapes were created by Hamid Naderi %Yeganeh and given at https://blogs.scientificamerican.com/guest-blog/how-to-draw-with-math/ if nargin==0,N=70; type='mixed'; end; if nargin==1, type='mixed'; end; ⋮

Using the new arguments construct that Jiro wrote about last week (my personal favorite R2019b feature) this could be rewritten with the following which would also validate the inputs:

function leafpile(N,type) ⋮ arguments N(1,1) double {mustBeInteger, mustBePositive} = 70; type {mustBeMember(type, {'mixed', 'maple', 'oak'})} = 'mixed'; end ⋮

Now what makes arguments better? Well, in theory the parsing should be easier to understand and read like an English sentence. But there’s more – Check out the Easter Egg at 26s in the video above. Autocomplete knew the options because they were constrained by `mustBeMember`. Pretty cool, eh?!

Give it a try and let us know what you think here or leave a comment for Nathaniel.

Published with MATLAB® R2019b

]]>Jiro‘s Pick this week is Function Argument Validation, which is a new R2019b feature that I’m really excited about.If you search for “function argument validation” or... read more >>

]]>Jiro‘s Pick this week is Function Argument Validation, which is a new R2019b feature that I’m really excited about.

If you search for “function argument validation” or “input validation” in File Exchange, you will see quite a few entries on it. Some are actual utilities for doing validation, while others are regular entries with validation functions within them. There are also argument parsing entries for parsing optional arguments.

Input validation can be a tedious task and may require thorough consideration of logic to ensure robust code. Let’s look at an example.

Let’s say that I want to create a function that takes an arbitrary number of data sets and creates an overlapping histogram. In addition, I’d like the function to take optional param-value pair inputs to customize some properties of the plot. So the input argument looks something like this:

myhistogram(DATA1, DATA2, ..., PARAM1, VALUE1, PARAM2, VALUE2, ...)

You can imagine how tricky this may be to implement. Doable, but tedious. I would need to do some parsing to first see how many data sets are passed in. I may do that by checking from the first input to see if it is not a parameter name I’m looking for. After that, I repeatedly inspect the parameter-value pairs and assign the values to the appropriate parameters. Again, doable, but tedious.

With the new function argument validation, the parsing and the validation can be expressed in a compact, easy-to-understand way. Here is the whole code:

Let’s see how it works.

data1 = randn(2000,1); data2 = 1 + randn(5000,1); data3 = 3 + randn(4000,1); myhistogram(data1,data2,data3)

I can call it with some parameters

myhistogram(data1,data2,data3,'nbins',25,'showlegend',true)

If I mistype my parameters, the validation functions catch the error.

try myhistogram(data1,data2,data3,'nbins',5.5,'showlegend',true) catch ME disp(ME.message) end

Invalid name-value argument 'nbins'. Value must be integer.

**Comments**

Give it a try and let us know what you think here.

Get
the MATLAB code

Published with MATLAB® R2019b

Sean‘s pick this week is tiledlayout by MathWorks’s development team. R2019b shipped on September 12th and is now available for download! Check the Release Notes for all of... read more >>

]]>Sean‘s pick this week is `tiledlayout` by MathWorks’s development team.

R2019b shipped on September 12th and is now available for download!

Check the Release Notes for all of the updates.

I imagine most of you have probably used `subplot` at some point.

Subplot alternatives or extensions are very popular on the File Exchange. In fact, I think it may be the most popular topic of contributions to the FEX. A quick search reveals many of the pains associated with subplots:

- Too much spacing between them
- Too much padding on the edges
- Difficulty in arranging the axes based on figure size
- Scaling issues

Enter R2019b, and `tiledlayout`. Tiled layouts give us all of the above. Let’s look at two examples: minimizing whitespace, and resizing/rescaling.

Create a `tiledlayout`, and use `nexttile` to traverse it.

```
figure
tlt = tiledlayout(2, 2);
nexttile
plot(sin(1:100));
nexttile
surf(peaks)
nexttile([1 2]) % Spanned
ribbon(sin(1:100), cos(1:100))
```

And let’s get rid of that whitespace!

tlt.Padding = "none"; tlt.TileSpacing = "none";

The above example used a fixed grid of 2×2 like you might use with subplot. There’s also an option to “flow” which will rearrange the plots based on the figure size.

```
figure
tlt = tiledlayout("flow");
nexttile
plot(sin(1:100));
nexttile
surf(peaks)
nexttile
ribbon(sin(1:100), cos(1:100))
```

Additionally, if you’re using sub plots or tiles to show many variables against the same x-axis, you may want to look at `stackedplot` which does this for you.

figure stackedplot((1:100).', rand(100, 4));

Give it a try and let us know what you think here.

Published with MATLAB® R2019b

]]>Jiro‘s Pick this week is Deep Learning Hackathon with Transfer Learning by Paola Jaramillo.

Deep learning is becoming more accessible to casual programmers, especially with many pretrained deep neural networks that people can download from the Add-On Explorer. These pretrained networks are trained on some specific set of images, and they can be a great starting point for new tasks. Adapting a pretrained network for a new task is called transfer learning.

This entry by Paola is an example of transfer learning that won her **first place** at a Hackathon on Deep Learning for Agriculture by Itility. The challenge was to classify the species of plants from the images.

She wrote about it in the Deep Learning Blog, so I’ll let you read the details there.

**Comments**

Let us know what you think here or leave a comment for Paola.

Get
the MATLAB code

Published with MATLAB® R2019a

Brett‘s Pick this week is Age and Gender Estimation from Face, by Masayuki Tanaka. Back in 2014, I “co-selected” one of Masayuki’s files as a Pick of the Week when I was... read more >>

]]>Brett‘s Pick this week is `Age and Gender Estimation from Face`, by Masayuki Tanaka.

Back in 2014, I “co-selected” one of Masayuki’s files as a Pick of the Week when I was looking for ways to quantify blur–I was (rightly) taken to task for calling it “noise”– in single images. Today, I return to his oeuvre to highlight a fun new submission that estimates age and gender from a photo.

Downloading and installing Masayuki’s code will lead you to another of his submissions that detects face parts–eyes, nose, mouth–in images. (That code primarily modifies the defaults of the “face-parts detector” in vision.CascadeObjectDetector, purportedly with better results.) Then his code will automatically install a pre-trained vgg-based neural network that does the classification (gender) and regression (age).

I really like that Masayuki provided sample code for training a network, even though he provided pre-trained models. And I like that his code predicts both age *and* gender. But mostly I just like how much fun I had playing around with it!

Here I was a few years ago; the age-gender predictor got it pretty right:

Apparently, I look a year older if I flip the image left-to-right:

Try it on some of your own images–it’s fun! Just be sure to shield it from your partner if it turns out to predict that she is a he, and that “he” is a few years older than she really is!

Oh, and you’ll need the Deep Learning Toolbox to run Masayuki’s code.

As always, I welcome your thoughts and comments.

Published with MATLAB® R2019a

]]>