demo04 of Im2mesh package
demo04 - What is inside im2mesh.
Note
I suggest familiarizing yourself with Im2mesh_GUI before learning Im2mesh package. With graphical user interface, Im2mesh_GUI will help you better understand the workflow and parameters of Im2mesh package.
If you are using Im2mesh package in MATLAB, you need to install MATLAB Image Processing Toolbox and Mapping Toolbox because Im2mesh package use a few functions in these toolboxes.
Setup
Before we start, please set folder "Im2mesh_Matlab" as your current folder of MATLAB.
Set default image size.
x = 250; y = 250; width = 250; height = 250;
set(groot, 'DefaultFigurePosition', [x,y,width,height])
% set(groot, 'DefaultFigurePosition', 'factory')
Function bounds2mesh use a mesh generator called MESH2D (developed by Darren Engwirda). We can use the following command to add the folder 'mesh2d-master' to the path of MATLAB. addpath(genpath('mesh2d-master'))
Shape
Let's start demo. Import image Shape.tif.
im = imread('Shape.tif');
if size(im,3) == 3; im = rgb2gray( im ); end
imshow( im,'InitialMagnification','fit' );
Inside function im2mesh
Function im2mesh has incorporated the workflow that you saw in im2mesh_GUI: extract polygonal boundaries from image, search & label control points, smooth boundary, simplify boundary, select phase, and generate mesh.
Extract boundaries
We use function im2Bounds to extract boundaries.
% image to polygon boundary
boundsRaw = im2Bounds( im );
% plot boundary using plotBounds
We can use function totalNumVertex to get total number of vertices in boundsRaw.
totalNumVertex(boundsRaw)
Find control points
We use function getCtrlPnts to find and label control points.
tf_avoid_sharp_corner = false;
boundsCtrlP = getCtrlPnts( boundsRaw, tf_avoid_sharp_corner, size(im) );
plotBounds(boundsCtrlP, true); % show starting and control points
We can use function totalNumCtrlPnt to get total number of control points.
totalNumCtrlPnt(boundsCtrlP)
Smooth boundary
We use function smoothBounds to smooth boundary.
threshold_num_turning = 0;
threshold_num_vert_Smo = 0;
boundsSmooth = smoothBounds( boundsCtrlP, lambda, mu, iters, ...
threshold_num_turning, threshold_num_vert_Smo );
plotBounds(boundsSmooth);
Simplify boundary
We use function simplifyBounds to simplify boundary. Other operation shown here is used to clear up redundant vertices.
% simplify polygon boundary
threshold_num_vert_Sim = 0;
boundsSimplified = simplifyBounds( boundsSmooth, tolerance, ...
threshold_num_vert_Sim );
boundsSimplified = delZeroAreaPoly( boundsSimplified );
% clear up redundant vertices
% only control points and turning points will remain
boundsClear = getCtrlPnts( boundsSimplified, false );
boundsClear = simplifyBounds( boundsClear, 0 );
We can use function totalNumVertex to get total number of vertices in boundsClear.
totalNumVertex(boundsClear)
A simpler operation
As shown in example3 of demo01, the above operations can be simplifed if we are only interested in boundary.
im = imread('Shape.tif');
if size(im,3) == 3; im = rgb2gray( im ); end
opt.tf_avoid_sharp_corner = false;
opt.threshold_num_turning = 0;
opt.threshold_num_vert_Smo = 0;
opt.threshold_num_vert_Sim = 0;
opt.mesh_kind = 'delaunay';
opt.tf_mesh = false; % do not generate mesh
% bounds is the simplified polygonal boundary
bounds = im2mesh( im, opt );
Area percentage
We can use the following code to calculate area perccentage.
% column vector for intensity
intensity = unique( im );
% calculate the area perccentage of grayscale in image
percent_pixel = getPixelPercent( im );
% calculate the area perccentage in simplified polygonal boundary
percent_polyarea = getPolyShapePercent( bounds );
T = table( intensity, percent_pixel, percent_polyarea );
T
T = 4×3 table
| intensity | percent_pixel | percent_polyarea |
---|
1 | 0 | 46.6576 | 46.8807 |
---|
2 | 100 | 17.9891 | 17.7978 |
---|
3 | 180 | 17.2554 | 17.2543 |
---|
4 | 255 | 18.0978 | 18.0672 |
---|
Function getPixelPercent is used to calculate the area perccentage of grayscale in an image.
Function getPolyShapePercent is used to calculate the area perccentage in simplified polygonal boundary.
We saw minor changes in area perccentage. That's good.
Generate mesh
We can use function bounds2mesh to generate mesh. Function bounds2mesh is using MESH2D as mesh generator.
[ vert,tria,tnum ] = bounds2mesh( bounds, hmax, grad_limit );
Refine triangulation...
-------------------------------------------------------
|ITER.| |CDT1(X)| |CDT2(X)|
-------------------------------------------------------
5 81 96
10 95 205
10 95 205
Refine triangulation...
-------------------------------------------------------
|ITER.| |CDT1(X)| |CDT2(X)|
-------------------------------------------------------
9 149 96
10 149 234
16 161 716
Smooth triangulation...
-------------------------------------------------------
|ITER.| |MOVE(X)| |DTRI(X)|
-------------------------------------------------------
% plot mesh using function plotMeshes
plotMeshes(vert,tria,tnum)
Zoom in
plotMeshes(vert,tria,tnum)
Refine mesh
We can refine the mesh near a specific polygon or polyline. We will show more about this in demo16 and demo17.
Insert nodes into a polygon
Suppose we are interested in polygon - bounds{1}{3}.
plot( poly(:,1), poly(:,2), 'ko-' ); axis equal
We can add more vertices to the interested polygon by repeatedly inserting midpoints to edges. We do this by function insertMidPnt.
polyNew = insertMidPnt( poly, iters );
plot( polyNew(:,1), polyNew(:,2), 'ko-' ); axis equal
We use function addPnt2Bound to insert polyNew into global boundaries. Please refer to demo16 about the usage of function addPnt2Bound.
tol_dist = 1e-2; % distance tolerance
boundsNew = addPnt2Bound( polyNew, bounds, tol_dist );
plotBounds( boundsNew, false, 'ko-' );
Generate mesh again
[ vert,tria,tnum ] = bounds2mesh( boundsNew, hmax, grad_limit );
Refine triangulation...
-------------------------------------------------------
|ITER.| |CDT1(X)| |CDT2(X)|
-------------------------------------------------------
5 102 138
10 118 281
14 121 323
Refine triangulation...
-------------------------------------------------------
|ITER.| |CDT1(X)| |CDT2(X)|
-------------------------------------------------------
9 179 138
10 179 294
20 191 1086
20 191 1086
Smooth triangulation...
-------------------------------------------------------
|ITER.| |MOVE(X)| |DTRI(X)|
-------------------------------------------------------
10 5 1076
plotMeshes(vert,tria,tnum);
Zoom in
plotMeshes(vert,tria,tnum)
Awesome!
set(groot, 'DefaultFigurePosition', 'factory')