В этом примере показов, как классифицировать текстуры, используя вейвлет рассеяния изображений. В сложение к Wavelet Toolbox™ этот пример также требует Parallel Computing Toolbox™ и Image Processing Toolbox™.
В цифровом изображении текстура предоставляет информацию о пространственном расположении интенсивности цвета или пикселя. Конкретные пространственные расположения интенсивности цвета или пикселей соответствуют различным внешним видам и консистенциям отображаемого физического материала. Классификация текстур и сегментация изображений имеет ряд важных областей применения. Особенно важным примером является биомедицинский анализ изображений, где нормальные и патологические состояния часто характеризуются морфологическими и гистологическими характеристиками, которые проявляются как различия в текстуре [4].
Для задач классификации часто полезно сопоставить данные с некоторым альтернативным представлением, которое отбрасывает нерелевантную информацию с сохранением дискриминационных свойств каждого класса. Вейвлет изображений создает низкодисперсные представления изображений, которые нечувствительны к перемещениям и малым деформациям. Поскольку переводы и небольшие деформации на изображении не влияют на принадлежность к классу, коэффициенты преобразования рассеяния обеспечивают функции, из которых можно создавать устойчивые классификационные модели.
Вейвлет рассеяние работает путем каскадирования изображения через ряд вейвлета преобразований, нелинейностей и усреднения [1] [3] [5]. Результатом этой глубокой редукции данных является то, что изображения в одном и том же классе перемещаются ближе друг к другу в представлении преобразования рассеяния, в то время как изображения, принадлежащие к различным классам, перемещаются дальше друг от друга.
Этот пример использует общедоступную базу данных текстур, базу данных изображений KTH-TIPS (текстуры под различной подсветкой, положение и шкала) [6]. Набор данных KTH-TIPS, используемый в этом примере, является версией в полутоновом цвете. Всего на текстуру приходится 810 изображений с 10 текстурами и 81 изображение. Большинство изображений имеют размер 200 на 200. В этом примере предполагается, что вы загрузили набор данных в полутоновом виде KTH-TIPS и распаковали его так, чтобы 10 классов текстуры содержались в отдельных подпапках общей папки. Каждая подпапка называется для класса текстур, содержащихся в ней. Удаление загруженных kth_tips_grey_200x200.tar
достаточно файла, чтобы предоставить папку верхнего уровня и необходимую KTH_TIPS подпапки.
Используйте imageDatastore
для чтения данных. Установите location
свойство imageDatastore
в папку, содержащую базу данных KTH-TIPS, к которой вы имеете доступ.
location = fullfile(tempdir,'kth_tips_grey_200x200','KTH_TIPS'); Imds = imageDatastore(location,'IncludeSubFolders',true,'FileExtensions','.png','LabelSource','foldernames');
Случайным образом выберите и визуализируйте 20 изображений из набора данных.
numImages = 810; perm = randperm(numImages,20); for np = 1:20 subplot(4,5,np) im = imread(Imds.Files{perm(np)}); imagesc(im); colormap gray; axis off; end
Этот пример использует MATLAB™ возможности параллельной обработки через tall
интерфейс массива. Запустите параллельный пул, если он не работает в данный момент.
if isempty(gcp) parpool; end
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6).
Для повторяемости установите генератор случайных чисел. Перетащите файлы набора данных KTH-TIPS и разделите 810 изображений на два случайным образом выбранных набора, один для обучения и один удерживаемый набор для проверки. Используйте приблизительно 80% изображений для создания прогнозирующей модели из преобразования рассеяния и используйте оставшуюся часть для проверки модели.
rng(100) Imds = imageDatastore(location,'IncludeSubFolders',true,'FileExtensions','.png','LabelSource','foldernames'); Imds = shuffle(Imds); [trainImds,testImds] = splitEachLabel(Imds,0.8);
Теперь у нас есть два набора данных. Набор обучающих данных состоит из 650 изображений, с 65 изображениями на текстуру. Тестовый набор состоит из 160 изображений с 16 изображениями на текстуру. Чтобы проверить, подсчитайте метки в каждом наборе данных.
countEachLabel(trainImds)
ans=10×2 table
Label Count
______________ _____
aluminium_foil 65
brown_bread 65
corduroy 65
cotton 65
cracker 65
linen 65
orange_peel 65
sandpaper 65
sponge 65
styrofoam 65
countEachLabel(testImds)
ans=10×2 table
Label Count
______________ _____
aluminium_foil 16
brown_bread 16
corduroy 16
cotton 16
cracker 16
linen 16
orange_peel 16
sandpaper 16
sponge 16
styrofoam 16
Создание tall
массивы для измененных размеров изображений.
Ttrain = tall(trainImds); Ttest = tall(testImds);
Создайте среду рассеяния для входа изображения 200 на 200 с InvarianceScale
из 150. Гиперпараметр инвариационной шкалы является единственным, который мы задаем в этом примере. Для других гиперпараметров преобразования рассеяния используйте значения по умолчанию.
sn = waveletScattering2('ImageSize',[200 200],'InvarianceScale',150);
Чтобы извлечь функции для классификации для каждого обучающего и тестового наборов, используйте helperScatImages_mean
функция. Код для helperScatImages_mean
находится в конце этого примера. helperScatImages_mean
изменяет размер изображений на общий размер 200 на 200 и использует среду рассеяния, sn
, для получения матрицы функций. В этом случае каждая матрица функции составляет 391 на 7 на 7. Существует 391 пути рассеяния и каждое изображение коэффициента рассеяния 7 на 7. Наконец, helperScatImages_mean
получает среднее значение по 2-ым и 3-ьим размерностям, чтобы получить вектор функции 391 элемента для каждого изображения. Это значительное сокращение данных с 40 000 элементов до 391.
trainfeatures = cellfun(@(x)helperScatImages_mean(sn,x),Ttrain,'Uni',0); testfeatures = cellfun(@(x)helperScatImages_mean(sn,x),Ttest,'Uni',0);
Использование tall
<reservedrangesplaceholder0>
возможность, собрать все векторы обучающих и тестовых функций и объединить их в матрицы.
Trainf = gather(trainfeatures);
Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 1: Completed in 1 min 39 sec Evaluation completed in 1 min 39 sec
trainfeatures = cat(2,Trainf{:}); Testf = gather(testfeatures);
Evaluating tall expression using the Parallel Pool 'local': - Pass 1 of 1: Completed in 23 sec Evaluation completed in 23 sec
testfeatures = cat(2,Testf{:});
Предыдущий код приводит к двум матрицам с размерностями строк 391 и размерностью столбца, равными количеству изображений в наборах обучения и тестов, соответственно. Таким образом, каждый столбец является вектором функции.
Этот пример создает простой классификатор, основанный на основных компонентах векторов функций рассеяния для каждого класса. Классификатор реализован в функциях helperPCAModel
и helperPCAClassifier
. Функция helperPCAModel
определяет основные компоненты для каждого класса цифр на основе функций рассеяния. Код для helperPCAModel
находится в конце этого примера. Функция helperPCAClassifier
классифицирует задержанные тестовые данные путем нахождения ближайшего соответствия (лучшая проекция) между основными компонентами каждого вектора тестовой функции с набора обучающих данных и присвоения класса соответственно. Код для helperPCAClassifier
находится в конце этого примера.
model = helperPCAModel(trainfeatures,30,trainImds.Labels); predlabels = helperPCAClassifier(testfeatures,model);
После построения модели и классификации тестового набора определите точность классификации тестового набора.
accuracy = sum(testImds.Labels == predlabels)./numel(testImds.Labels)*100
accuracy = 99.3750
Мы достигли 99,375% правильной классификации или 0,625% вероятности ошибок для 160 изображений в тестовом наборе. График матрицы неточностей показывает, что наша простая модель неправильно классифицировала одну текстуру.
figure confusionchart(testImds.Labels,predlabels)
В этом примере мы использовали вейвлет изображений, чтобы создать низкодисперсные представления текстур для классификации. Используя преобразование рассеяния и классификатор простых основных компонентов, мы достигли 99,375% правильной классификации на удерживаемом тестовом наборе. Этот результат сопоставим с современной эффективностью базы данных KTH-TIPS. [2]
[1] Бруна, Дж., и С. Маллат. «Инвариантные сети свертки рассеяния». Транзакции IEEE по шаблонному анализу и машинному анализу. Том 35, № 8, 2013, с. 1872-1886.
[2] Хейман, Э., Б. Капуто, М. Фриц и Й. О. Эклунд. «О значении реальных условий классификации материалов». В Компьютерное зрение - ECCV 2004, под редакцией Томаса Пайдлы и Йиржи Матаса, 3024: 253-66. Берлин, Гейдельберг: Спрингер Берлин Гейдельберг, 2004. https://doi.org/10.1007/978-3-540-24673-2_21.
[3] Mallat, S. «Group Invariant Scattering». Коммуникации в чистой и прикладной математике. Том 65, № 10, 2012, с. 1331-1398.
[4] Пужоль, О., и П. Радева. «Контролируемая классификация текстуры для характеристики внутрисосудистой ткани». В Справочнике по анализу биомедицинских изображений под редакцией Джасджита С. Сури, Дэвида Л. Уилсона и Свэми Лаксминараяна, 57-109. Бостон, Массачусетс: Springer US, 2005. https://doi.org/10.1007/0-306-48606-7_2.
[5] Sifre, L., and S. Mallat. «Вращение, масштабирование и деформация инвариантного рассеяния для дискриминации текстур». 2013 IEEE Conference on Компьютерное Зрение and Pattern Recognition. 2013, стр. 1233-1240. 10.1109/CVPR.2013.163.
[6] Домашняя страница баз изображений KTH-TIPS. https://www.csc.kth.se/cvap/databases/kth-tips/
helperScatImages_mean
function features = helperScatImages_mean(sf,x) x = imresize(x,[200 200]); smat = featureMatrix(sf,x); features = mean(mean(smat,2),3); end
helperPCAModel
function model = helperPCAModel(features,M,Labels) % This function is only to support wavelet image scattering examples in % Wavelet Toolbox. It may change or be removed in a future release. % model = helperPCAModel(features,M,Labels) % Copyright 2018 MathWorks % Initialize structure array to hold the affine model model = struct('Dim',[],'mu',[],'U',[],'Labels',categorical([]),'s',[]); model.Dim = M; % Obtain the number of classes LabelCategories = categories(Labels); Nclasses = numel(categories(Labels)); for kk = 1:Nclasses Class = LabelCategories{kk}; % Find indices corresponding to each class idxClass = Labels == Class; % Extract feature vectors for each class tmpFeatures = features(:,idxClass); % Determine the mean for each class model.mu{kk} = mean(tmpFeatures,2); [model.U{kk},model.S{kk}] = scatPCA(tmpFeatures); if size(model.U{kk},2) > M model.U{kk} = model.U{kk}(:,1:M); model.S{kk} = model.S{kk}(1:M); end model.Labels(kk) = Class; end function [u,s,v] = scatPCA(x,M) % Calculate the principal components of x along the second dimension. if nargin > 1 && M > 0 % If M is non-zero, calculate the first M principal components. [u,s,v] = svds(x-sig_mean(x),M); s = abs(diag(s)/sqrt(size(x,2)-1)).^2; else % Otherwise, calculate all the principal components. % Each row is an observation, i.e. the number of scattering paths % Each column is a class observation [u,d] = eig(cov(x')); [s,ind] = sort(diag(d),'descend'); u = u(:,ind); end end end
helperPCAClassifier
function labels = helperPCAClassifier(features,model) % This function is only to support wavelet image scattering examples in % Wavelet Toolbox. It may change or be removed in a future release. % model is a structure array with fields, M, mu, v, and Labels % features is the matrix of test data which is Ns-by-L, Ns is the number of % scattering paths and L is the number of test examples. Each column of % features is a test example. % Copyright 2018 MathWorks labelIdx = determineClass(features,model); labels = model.Labels(labelIdx); % Returns as column vector to agree with imageDatastore Labels labels = labels(:); %-------------------------------------------------------------------------- function labelIdx = determineClass(features,model) % Determine number of classes Nclasses = numel(model.Labels); % Initialize error matrix errMatrix = Inf(Nclasses,size(features,2)); for nc = 1:Nclasses % class centroid mu = model.mu{nc}; u = model.U{nc}; % 1-by-L errMatrix(nc,:) = projectionError(features,mu,u); end % Determine minimum along class dimension [~,labelIdx] = min(errMatrix,[],1); %-------------------------------------------------------------------------- function totalerr = projectionError(features,mu,u) % Npc = size(u,2); L = size(features,2); % Subtract class mean: Ns-by-L minus Ns-by-1 s = features-mu; % 1-by-L normSqX = sum(abs(s).^2,1)'; err = Inf(Npc+1,L); err(1,:) = normSqX; err(2:end,:) = -abs(u'*s).^2; % 1-by-L totalerr = sqrt(sum(err,1)); end end end