Open videoconcentricity.m in the Editor
Run in the Command Window

# Concentricity Inspection

This demo inspects the concentricity of both the core and the cladding in a cross-section of optical fiber. Concentricity is a measure of how centered the core is within the cladding.

## Contents

- Introduction
- Initialization
- Stream Processing Loop
- Release
- Summary

## Introduction

First, the demo uses the `BlobAnalysis` System object to determine the centroid of the cladding. It uses this centroid to find a point on the cladding's outer boundary. Using this as a starting point, the `BoundaryTracer` System object defines the cladding's outer boundary. Then the demo uses these boundary points to compute the cladding's center and radius using a least-square, circle-fitting algorithm. If the distance between the cladding's centroid and the center of its outer boundary is within a certain tolerance, the fiber optic cable is in acceptable condition.

## Initialization

Use these next sections of code to initialize the required variables and System objects.

    NumPts = 250;   % Maximum number of boundary pixels.
    tolerance = 1;  % tolerance for distance.
    NumTimes = 8;

Create a `VideoFileReader` System object to read a video file.

    hmfr = vision.VideoFileReader('vipconcentricity.avi', ...
                                  'PlayCount', NumTimes);

Create a `ColorSpaceConverter` System object to convert the RGB image to intensity format.

    hcsc = vision.ColorSpaceConverter('Conversion', 'RGB to intensity');

Create a `BlobAnalysis` System object to find the centroid of the circular blobs in the video.

    hblob = vision.BlobAnalysis( ...
                            'AreaOutputPort', false, ...
                            'BoundingBoxOutputPort', false, ...
                            'OutputDataType', 'single', ...
                            'MaximumCount', 1);

Create a `BoundaryTracer` System object to find the outer boundary of the cladding.

    htracebound = vision.BoundaryTracer( ...
        'MaximumPixelCount', NumPts, ...
        'NoBoundaryAction', 'Fill with last point found');

Create two `MarkerInserter` System objects to plot the centroids of external and internal circles.

    hdrawmarkers1 = vision.MarkerInserter( ...
                        'Shape', 'Plus', ...
                        'BorderColor', 'Custom', ...
                        'CustomBorderColor', [255 0 0]);

    hdrawmarkers2 = vision.MarkerInserter( ...
                        'Shape', 'Star', ...
                        'BorderColor', 'Custom', ...
                        'CustomBorderColor', [0 255 0]);

Create a `ShapeInserter` System object to draw circles around the cladding.

    hdrawshapes = vision.ShapeInserter( ...
                        'Shape', 'Circles', ...
                        'BorderColor', 'Custom', ...
                        'CustomBorderColor', [0 1 1]);

Create two `TextInserter` System objects to display the concentricity metric on the input video.

    hinserttext1 = vision.TextInserter( ...
        'Text', {'Concentricity: Bad  ','Concentricity: Good'}, ...
        'FontSize', 14);

    hinserttext2 = vision.TextInserter( ...
        'Text', 'Distance in pixels: %2d', ...
        'Location',  [1 20], ...
        'FontSize', 14);

Create two `VideoPlayer` System objects to display the input and output videos.

    hVideo1 = vision.VideoPlayer('Name', 'Original');

    hVideo2 = vision.VideoPlayer('Name', 'Results');
    hVideo2.Position(1) = hVideo1.Position(1)+450;

## Stream Processing Loop

Create a processing loop to perform concentricity inspection in the input video. This loop uses the System objects you instantiated above.

    count = 1;
    while (count < NumTimes)
        if isDone(hmfr)
            count = count+1;
        end
        I = step(hmfr);
        image = step(hcsc, I);          % Convert Image to Intensity format.

        BW = image < 0.5;              % Convert image to binary.
        centroid = step(hblob, BW);     % Compute centroid of the blobs.

        Idx = floor(centroid(1));
        max_idx = find(BW(:, Idx), 1);
        StartPts = [Idx, single(max_idx)]; % Compute the starting points.

        % Find the boundary pixels of the outer cladding.
        Pts = step(htracebound, BW, StartPts);

        Row_bound = Pts(:, 1);
        Col_bound = Pts(:, 2);
        t = [Row_bound Col_bound ones(size(Pts, 1), 1)];
        X = pinv(t);
        X1 = Row_bound.^2 + Col_bound.^2;
        x2 = X*(-X1);
        % Calculate the radius and center of the circle fitting the outer
        % cladding.
        radius = sqrt((-0.5*x2(1)).^2 + (-0.5*x2(2)).^2 - x2(3));
        center = [(-0.5*x2(1)), (-0.5*x2(2))];

        % Compare the distance between the center of the circle and the
        % centroid against a tolerance value.
        dist = sqrt(sum(centroid - center).^2);

        % Draw the circle, and mark the center and centroid on the image.
        y1 = step(hdrawmarkers1, I, centroid);
        y2 = step(hdrawshapes, y1, [center, radius]);
        y3 = step(hdrawmarkers2, y2, center);
        y4 = step(hinserttext1, y3, (dist <= tolerance) + 1);
        image_out = step(hinserttext2, y4, uint8(dist));

        % Display the results.
        step(hVideo2, image_out);
        step(hVideo1, I);
    end

## Release

Call the release method on the System objects to close any open files and devices.

    release(hmfr);

## Summary

In the Results window, you can see the cladding's centroid marked with a red '+'. The center of the cladding's outer boundary is marked with a green '*'. When the distance between these two markers is within an acceptable tolerance, the cross-section of the fiber optic cable is labeled "Concentricity: Good". Otherwise, it is labeled "Concentricity: Bad". We also display the distance, in pixels, between the cladding's centroid and the center of the cladding's outer boundary.