exponenta event banner

Классифицировать пикселы с помощью нечетких систем

В этом примере показано, как классифицировать пикселы изображения с помощью нечеткой системы вывода (FIS). В этом примере требуется программное обеспечение Toolbox™ обработки изображений.

Классификация пикселей - это методика обработки изображений, которая сегментирует изображение путем классификации каждого пикселя в соответствии с конкретными атрибутами пикселей. Шум и другие источники неопределенности могут усложнить классификацию пикселей. Использование метода классификации на основе FIS может помочь устранить такую неопределенность.

Этот пример включает следующие этапы.

  1. Настройте FIS для классификации пикселей на основе цвета.

  2. Настройте FIS для классификации пикселей на основе текстуры.

  3. Объединение настроенных объектов FIS в иерархическую нечеткую систему для классификации пикселей.

Загрузите данные изображения, которые содержат три видимых сегмента: зеленую траву, белую кайму и футбольный мяч.

exData = load('fuzzpixclass');
cImg = exData.cImg;

figure
imshow(cImg)

Figure contains an axes. The axes contains an object of type image.

В этом примере используются нечеткие системы для разделения изображения на три категории путем классификации каждого пикселя как принадлежащего зеленой траве, белой границе или футбольному мячу.

Изображение сегмента с использованием цвета

Сегменты изображения включают следующие атрибуты цвета.

  • Зеленое поле: изменение пикселов зеленой и темной тени

  • Белая граница: белый, светло-зеленый и темно-теневые пикселы

  • Футбольный мяч: белый и темный цвет пикселей

Поскольку количество темных пикселей незначительно по сравнению с зелеными и белыми пикселями, можно создать один нечеткий классификатор для различения зеленых и белых пикселей. Можно обучить классификаторы образцу зеленого и белого пикселов, поскольку ни один из сегментов не содержит уникального атрибута цвета.

Извлеките репрезентативные субизображения из зеленого поля и сегментов белой границы в качестве учебных данных. Каждое субизображение включает в себя изменения цвета пикселя.

grnImg = exData.grnImg;
whtImg = exData.whtImg;

figure
subplot(1,2,1)
imshow(grnImg)
xlabel('Green subimage')
subplot(1,2,2)
imshow(whtImg)
xlabel('White subimage')

Figure contains 2 axes. Axes 1 contains an object of type image. Axes 2 contains an object of type image.

Построение FIS

Для сегментации цвета создайте FIS Sugeno с тремя входами и одним выходом без правил. Для каждой входной и выходной переменной включите две функции членства по умолчанию (MF).

colorFISIn = sugfis('NumInputs',3,'NumInputMFs',2, ...
    'NumOutputs',1,'NumOutputMFs',2,'AddRules','none');

Входные переменные соответствуют значениям RGB для каждого пикселя. Выходное значение является высоким, если цвет пикселя зеленый; в противном случае он низок.

Поезд FIS

Создайте обучающие данные из репрезентативных цветных субизображений. getColorInputData вспомогательная функция, показанная в конце примера, создает массив из трех столбцов значений RGB для каждого пикселя в указанном изображении.

[grnSubRow,grnSubCol,grnSubDepth] = size(grnImg);  % Green subimage size
[whtSubRow,whtSubCol,whtSubDepth] = size(whtImg);  % White subimage size
trnX = [...
    getColorInputData(grnImg); ...
    getColorInputData(whtImg) ...
    ];
trnY = [...
    ones(grnSubRow*grnSubCol,1); ... % Output is high (1) for green pixels
    zeros(whtSubRow*whtSubCol,1) ... % Output is low (1) for white pixels
    ];

Входные данные trnX имеет три столбца для значений пикселов RGB. Выходные данные trnY - вектор столбца, который содержит 1 для каждого зеленого пикселя и 0 для каждого белого пикселя.

Создание набора параметров для правил обучения для colorFISIn. Чтобы сократить продолжительность процесса оптимизации, используйте минимальные значения для параметров перекрестной проверки.

options = tunefisOptions('OptimizationType','learning','KFoldValue',2, ...
    'ValidationTolerance',0.0,'ValidationWindowSize',1);

При наличии программного обеспечения Parallel Computing Toolbox™ можно повысить скорость процесса настройки, задав options.UseParallel кому true. Если у вас нет программного обеспечения Parallel Computing Toolbox, установите options.UseParallel кому false.

Чтобы узнать правила и найти значения параметров FIS, в этом примере используется оптимизация генетических алгоритмов, которая является стохастическим процессом. Для получения воспроизводимых результатов инициализируйте генератор случайных чисел по умолчанию.

rng('default')

Изучение нечетких правил для colorFISIn использование данных и вариантов обучения. Правила обучения с использованием tunefis функция может занять несколько минут. В этом примере можно включить настройку с помощью параметра runtunefis кому true. Загрузка предварительно подготовленных результатов без выполнения tunefis, комплект runtunefis кому false.

runtunefis = false;

Чтобы узнать новые правила без настройки входных и выходных параметров MF, установите для параметров значение []. Дополнительные сведения см. в разделе tunefis.

if runtunefis
    colorFISOut1 = tunefis(colorFISIn,[],trnX,trnY,options); %#ok<UNRCH>
else
    colorFISOut1 = exData.colorFISOut1;
end

Вычислите среднеквадратичную ошибку (RMSE) для обученного FIS. calculateRMSE вспомогательная функция, которая показана в конце примера, классифицирует пиксели обучающих данных с использованием обученной FIS и сравнивает результаты с ожидаемыми классификациями пикселей.

fprintf('Training RMSE after learning rules = %.3f MPG\n',...
    calculateRMSE(colorFISOut1,trnX,trnY));
Training RMSE after learning rules = 0.283 MPG

Изучив новые правила, настройте входные и выходные параметры MF. Для получения настраиваемых настроек параметров FIS используйте getTunableSettings функция.

[in,out] = getTunableSettings(colorFISOut1);

Чтобы настроить существующие значения параметров FIS без изучения новых правил, установите OptimizationType кому 'tuning'.

options.OptimizationType = 'tuning';

Настройка параметров FIS с использованием заданных настраиваемых настроек, данных обучения и параметров настройки.

if runtunefis
    rng('default')
    colorFISOut = tunefis(colorFISOut1,[in;out],trnX,trnY,options);
    colorFISOut.Name = "colorFISOut";
else
    colorFISOut = exData.colorFISOut;
    
end

Вычислите RMSE для настроенного FIS.

fprintf('Training RMSE after tuning MF parameters = %.3f MPG\n',...
        calculateRMSE(colorFISOut,trnX,trnY));
Training RMSE after tuning MF parameters = 0.228 MPG

Изображение сегмента

Сегментируйте исходное изображение с помощью настроенного FIS. Для этого сначала извлеките значения красного, зеленого и синего пикселов.

[imgRow,imgCol,imgDepth] = size(cImg);
red = cImg(:,:,1);
green = cImg(:,:,2);
blue = cImg(:,:,3);
colorInput = [red(:) green(:) blue(:)];

Классифицируйте каждый пиксель с помощью настроенной FIS.

eoptions = evalfisOptions;
eoptions.EmptyOutputFuzzySetMessage = 'none';
eoptions.NoRuleFiredMessage = 'none';
eoptions.OutOfRangeInputValueMessage = 'none';

y = evalfis(colorFISOut,colorInput,eoptions);

Сегментировать изображение с помощью getSegmentedImage вспомогательная функция, которая показана в конце примера. Эта функция создает двоичную маску из выходных значений FIS.

greenSegment = getSegmentedImage(reshape(y,[imgRow,imgCol]),cImg);

Просмотр сегментированного изображения. Пикселы, классифицируемые FIS как белые, отображаются черным цветом. Остальные пикселы классифицируются как зеленые.

figure
imshow(greenSegment)

Figure contains an axes. The axes contains an object of type image.

Белые пикселы частично удаляются из граничного и шарового сегментов. Зеленый сегмент также неправильно включает пиксели из шарика. Следовательно, процесс классификации требует другого пиксельного атрибута, который может идентифицировать разницу между травяным полем и мячом.

Изображение сегмента с использованием текстуры

Для различения поля и шара используйте данные градиента серого изображения для идентификации текстур поля и шара.

Извлеките репрезентативное подчиненное изображение для шара и преобразуйте зеленые, белые и шариковые изображения в оттенки серого.

ballImg = exData.ballImg;
grayGrnImg = rgb2gray(grnImg);
grayWhtImg = rgb2gray(whtImg);
grayBallImg = rgb2gray(ballImg);

Вычислите градиент для каждого субизображения и нормализуйте величину градиента для каждого пикселя, используя normMat функция помощника.

[gX,gY] = imgradientxy(grayGrnImg);
grnGrsTexture = normMat(imgradient(gX,gY));

[gX,gY] = imgradientxy(grayWhtImg);
whtGrsTexture = normMat(imgradient(gX,gY));

[gX,gY] = imgradientxy(grayBallImg);
ballTexture = normMat(imgradient(gX,gY));

Просмотр градиентов для каждого субизображения.

figure,
subplot(2,3,1)
imshow(grnImg)
subplot(2,3,2)
imshow(whtImg)
subplot(2,3,3)
imshow(ballImg)
subplot(2,3,4)
imshow(grnGrsTexture)
subplot(2,3,5)
imshow(whtGrsTexture)
subplot(2,3,6)
imshow(ballTexture)

Figure contains 6 axes. Axes 1 contains an object of type image. Axes 2 contains an object of type image. Axes 3 contains an object of type image. Axes 4 contains an object of type image. Axes 5 contains an object of type image. Axes 6 contains an object of type image.

Как зеленый, так и белый сегменты травы имеют одинаковые значения градиента, которые отличаются от градиентов сегмента мяча. Поэтому используйте только данные градиента зеленого и шарового сегментов для обучения классификатора нечетких текстур.

Построение FIS

Нормализованные градиенты для мяча и травяного поля имеют разные закономерности. Чтобы узнать эти шаблоны, создайте FIS Sugeno с тремя входами и одним выходом без правил. Для каждой входной и выходной переменной включите две функции членства по умолчанию (MF).

textureFISIn = sugfis('NumInputs',3,'NumInputMFs',2, ...
    'NumOutputs',1,'NumOutputMFs',2,'AddRules','none');

Входные переменные задают значения градиента для трех последовательных пикселов. Выходное значение является высоким, если третий пиксель принадлежит травяному полю; в противном случае он низок.

Поезд FIS

Создайте учебные данные из градиентов зеленой и шаровой областей. getGradientInputData вспомогательная функция, которая показана в конце примера, создает массив из трех столбцов последовательных комбинаций значений пикселей.

[grsGradRow,grsGradCol] = size(grnGrsTexture);   % Grass texture size
[ballGradRow,ballGradCol] = size(ballTexture);   % Ball texture size
trnX = [...
    getGradientInputData(grnGrsTexture); ... % gradient values of 3 successive pixels
    getGradientInputData(ballTexture) ...    % gradient values of 3 successive pixels
    ];
trnY = [...
    ones(grsGradRow*grsGradCol,1); ...   % Output is high (1) for green texture
    zeros(ballGradRow*ballGradCol,1) ... % Output is low (1) for ball texture
    ];

Входные данные trnX имеет три столбца для значений градиента трех последовательных пикселей. Выходные данные trnY является вектором столбца, который содержит 1, если третий пиксель принадлежит текстуре поля, и 0 в противном случае.

Чтобы узнать нечеткие правила, установите OptimizationType кому 'learning'.

options.OptimizationType = 'learning';

Поезд textureFISIn для изучения правил с использованием данных обучения.

if runtunefis
    rng('default')
    textureFISOut1 = tunefis(textureFISIn,[],trnX,trnY,options); %#ok<UNRCH>
else
    textureFISOut1 = exData.textureFISOut1;
end
fprintf('Training RMSE after learning rules = %.3f MPG\n',...
    calculateRMSE(textureFISOut1,trnX,trnY));
Training RMSE after learning rules = 0.477 MPG

Изучив новые правила, настройте входные и выходные параметры MF. Для получения настраиваемых параметров FIS используйте getTunableSettings функция.

[in,out] = getTunableSettings(textureFISOut1);

Чтобы настроить существующие параметры FIS без изучения новых правил, установите OptimizationType кому 'tuning'.

options.OptimizationType = 'tuning';

Настройка параметров FIS с использованием заданных настраиваемых настроек, данных обучения и параметров настройки.

if runtunefis
    rng('default')
    textureFISOut = tunefis(textureFISOut1,[in;out],trnX,trnY,options);
    textureFISOut.Name = "textureFISOut";
else
    textureFISOut = exData.textureFISOut;
end
fprintf('Training RMSE after tuning MF parameters = %.3f MPG\n',...
    calculateRMSE(textureFISOut,trnX,trnY));
Training RMSE after tuning MF parameters = 0.442 MPG

Изображение сегмента

Сегментируйте исходное изображение с помощью настроенного FIS. Для этого сначала вычисляют градиент изображения и извлекают последовательные комбинации пикселей.

[gX,gY] = imgradientxy(rgb2gray(cImg));
imgTexture = normMat(imgradient(gX,gY));
gradInput = getGradientInputData(imgTexture);

Классифицируйте каждый пиксель с помощью настроенной FIS.

y = evalfis(textureFISOut,gradInput,eoptions);

Сегментировать изображение с помощью getSegmentedImage функция помощника.

grassField = getSegmentedImage(reshape(y,[imgRow,imgCol]),cImg);

Просмотр сегментированного изображения. Пикселы, классифицируемые FIS как принадлежащие мячу, отображаются черным цветом. Остальные пикселы классифицируются как пикселы поля.

figure
imshow(grassField)

Figure contains an axes. The axes contains an object of type image.

Обученный FIS сегментирует травяное поле и мяч с небольшим количеством неверных пикселей в сегментах.

Изображение сегмента с использованием цвета и текстуры

Для классификации пикселов по цвету и текстуре можно комбинировать colorFISOut и textureFISOut с использованием иерархической нечеткой системы, или дерева FIS.

Для этого сначала создайте сугеновскую FIS с двумя входами и тремя выходами. Первая входная переменная является выходом colorFISOut и вторая входная переменная является выходом textureFISOut. Выходные переменные - это степень, в которой пикселы принадлежат каждому сегменту изображения: зеленому полю, белой границе и футбольному мячу.

segFIS = sugfis('Name','segFIS','NumInputs',2,'NumInputMFs',2, ...
    'NumOutputs',3,'NumOutputMFs',2,'AddRules','none');

Назовите входные переменные, выходные переменные и MF.

segFIS.Inputs(1).Name = 'color';
segFIS.Inputs(1).MembershipFunctions(1).Name = 'white';
segFIS.Inputs(1).MembershipFunctions(2).Name = 'green';
segFIS.Inputs(2).Name = 'texture';
segFIS.Inputs(2).MembershipFunctions(1).Name = 'ball';
segFIS.Inputs(2).MembershipFunctions(2).Name = 'grass';
segFIS.Outputs(1).Name = 'greenField';
segFIS.Outputs(1).MembershipFunctions(1).Name = 'low';
segFIS.Outputs(1).MembershipFunctions(2).Name = 'high';
segFIS.Outputs(2).Name = 'whiteBorder';
segFIS.Outputs(2).MembershipFunctions(1).Name = 'low';
segFIS.Outputs(2).MembershipFunctions(2).Name = 'high';
segFIS.Outputs(3).Name = 'soccerBall';
segFIS.Outputs(3).MembershipFunctions(1).Name = 'low';
segFIS.Outputs(3).MembershipFunctions(2).Name = 'high';

Добавьте следующие правила в FIS.

  • Если пиксель имеет гладкую текстуру мяча, установите выход футбольного мяча на высокий.

  • Если пиксель белый и имеет травяную текстуру, установите белый выходной сигнал границы в высокое значение.

  • Если пиксель зеленый, имеет текстуру травы и является зеленым полем, выводимым на высокий уровень.

rules = ["texture==ball => greenField=low, whiteBorder=low, soccerBall=high";
         "color==white & texture==grass => greenField=low, whiteBorder=high, soccerBall=low";
         "color==green & texture==grass => greenField=high, whiteBorder=low, soccerBall=low"];
segFIS = addRule(segFIS,rules);

Создание дерева FIS путем подключения выходов colorFISOut и textureFISOut на входы segFIS.

fis = [colorFISOut textureFISOut segFIS];
con = [...
    "colorFISOut/output1" "segFIS/color"; ...
    "textureFISOut/output1" "segFIS/texture" ...
    ];
fisT = fistree(fis,con);

Классифицируйте пикселы изображения с помощью дерева FIS и сегментируйте изображение. Для каждого сегментированного изображения нечерные пиксели классифицируются как часть сегмента.

y = evalfis(fisT,[colorInput gradInput],eoptions);
greenField = getSegmentedImage(reshape(y(:,1),[imgRow,imgCol]),cImg);
whiteBorder = getSegmentedImage(reshape(y(:,2),[imgRow,imgCol]),cImg);
soccerBall = getSegmentedImage(reshape(y(:,3),[imgRow,imgCol]),cImg);

Просмотр пикселов зеленого поля.

figure
imshow(greenField)
xlabel('Green field')

Figure contains an axes. The axes contains an object of type image.

Просмотр пикселов белой границы.

figure
imshow(whiteBorder)
xlabel('White border')

Figure contains an axes. The axes contains an object of type image.

Просмотр пикселей футбольного мяча.

figure
imshow(soccerBall)
xlabel('Soccer ball')

Figure contains an axes. The axes contains an object of type image.

Заключение

Сегменты изображения содержат неправильные классификации. Можно удалить многие неправильно классифицированные пикселы путем последующей обработки результатов с помощью алгоритмов уменьшения шума, таких как морфологические операции (imdilate, imerode, imopen, imclose). Например, используйте операцию морфологического закрытия, чтобы уменьшить шум в сегментированном изображении зеленого поля.

greenFieldLowNoise = getSegmentedImageClose(reshape(y(:,1),[imgRow,imgCol]),cImg);
figure
imshow(greenFieldLowNoise)

Figure contains an axes. The axes contains an object of type image.

Для повышения производительности нечеткого классификатора можно:

  • Используйте дополнительные данные обучения.

  • Изучение цветовых шаблонов нескольких пикселей вместо изучения цвета отдельных пикселей.

  • Другими словами, увеличьте длину вектора градиентного элемента, используя значения градиента, превышающие три последовательных пикселя.

  • Добавьте дополнительные MF в FIS для классификации пикселей.

  • Используйте FIS типа 2.

  • Используйте допуск проверки, больший размер окна и более высокие k-кратные значения для перекрестной проверки.

  • Настройка параметров построенного дерева FIS segFIS.

Локальные функции

function data = getColorInputData(img)
% Create RGB input data from an image for training.

[row,col,depth] = size(img);
data = zeros(row*col,depth);
id = 0;
for i = 1:row
    for j = 1:col
        id = id + 1;
        for k = 1:depth
            data(id,k) = img(i,j,k);
        end
    end
end

end

function [rmse,actY] = calculateRMSE(fis,x,y)
% Calculate root mean squared error for FIS output.

% Specify options for FIS evaluation
persistent evalOptions
if isempty(evalOptions)
    evalOptions = evalfisOptions("EmptyOutputFuzzySetMessage","none", ...
        "NoRuleFiredMessage","none","OutOfRangeInputValueMessage","none");
end

% Evaluate FIS
actY = evalfis(fis,x,evalOptions);

% Calculate RMSE 
del = actY - y;
rmse = sqrt(mean(del.^2));

end

function cImg = getSegmentedImage(y,cImg)
% Segment an image using classifier output by creating a binary image
% using a 0.5 threshold.

id = y >= 0.5;
y(id) = 1;
y(~id) = 0;

cImg(:,:,1) = cImg(:,:,1).*y;
cImg(:,:,2) = cImg(:,:,2).*y;
cImg(:,:,3) = cImg(:,:,3).*y;

end

function y = normMat(x)
% Normalize array elements to the range [0 1].

tmp = x(:);
mn = min(tmp);
mx = max(tmp);
d = (mx-mn);
y = (x-mn);
if d>0
    y = y/d;
end

end

function data = getGradientInputData(x)
% Create gradient input data for training.

x = x(:);
n = 3; % Three successive gradient values.
data = zeros(length(x),n);

% Specify complete input vectors.
for i = n:length(x)
   data(i,:) = x(i-n+1:i)';
end

% Approximate missing elements in the incomplete input vector.
for i = n-1:-1:1
    right = x(1:i)';
    m = n - i;
    left = repmat(right(1),[1 m]);
    data(i,:) = [left right];
end

end

function cImg = getSegmentedImageClose(y,cImg)
% Segment an image using classifier output by creating a binary image
% using a 0.5 threshold.

id = y >= 0.5;
y(id) = 1;
y(~id) = 0;

se = strel('disk',1);
y = imclose(y,se);

cImg(:,:,1) = cImg(:,:,1).*y;
cImg(:,:,2) = cImg(:,:,2).*y;
cImg(:,:,3) = cImg(:,:,3).*y;

end

См. также

| | |

Связанные темы