Соответствует ли измерение PrincipalAxisLength диаметру объекта на выходе regionprops3? - PullRequest
3 голосов
/ 12 июня 2019

Я использую команду regionprops3 для вычисления свойств объекта в MATLAB. Я думал, PrincipalAxisLength - это диаметр моего объекта, но это не так.

Я создал двоичное изображение I, содержащее эллипсоид с радиусами (40, 10, 10). Я получаю эти значения от regionprops3:

sum(I(:)) = 16741
stats.volume = 16741
stats.EquivDiameter = 31.739  % 4/3*pi*(31.739/2)^3=16741
stats.PrincipalAxisLength = [71.535, 17.936, 17.908]

Если PrincipalAxisLength - это 3 диаметра эллипсоида, то его объем:

4/3*pi*71.535/2*17.936/2*17.908/2 = 12031

Что не эквивалентно вышеуказанному объему.

Итак, как мне вычислить радиусы эллипсоида?

1 Ответ

3 голосов
/ 12 июня 2019

Документация для измерения формы PrincipalAxisLength описывает его как (выделено мной):

Длина (в вокселях) главных осей эллипсоида, которые имеют такие же нормализованные вторые центральные моменты , что и область, возвращенная как вектор 1 на 3. regionprops3 сортирует значения по возрастанию.

Другими словами, он соответствует многомерному распределению вероятностей для региона и рассчитывает центральные моменты для этого распределения, возвращая второй центральный момент (то есть дисперсию) для измерения PrincipalAxisLength.

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

% Create 3D binary data containing ellipsoid:
[X, Y, Z] = meshgrid(-50:50, -20:20, -20:20);
R = [40 10 10];
I = ((X./R(1)).^2 + (Y./R(2)).^2 + (Z./R(3)).^2 <= 1);

% Calculate statistics with regionprops3:
stats = regionprops3(I, 'all');
L = stats.PrincipalAxisLength./2;

% Create ellipsoid surface from second central moments and plot:
[x, y, z] = ellipsoid(0, 0, 0, L(1), L(2), L(3), 100);
surf(x, y, z, 'FaceAlpha', 0.5, 'FaceColor', 'r', 'EdgeColor', 'none');
axis equal;
hold on;

% Create image of middle slice through ellipsoid and plot:
imageSlice = 256.*uint8(I(:, :, 21));
imageSlice = cat(3, imageSlice, imageSlice, imageSlice);
image(-50:50, -20:20, imageSlice);
view(0, 90);

И вот последний сюжет, который вы получите:

enter image description here

Если вы хотите подогнать поверхность эллипсоида к вашему двоичному объекту, вы, вероятно, могли бы использовать измерение PrincipalAxisLength в качестве начального предположения для истинных длин осей. На файловой бирже есть эта функция , которая выполняет подгонку эллипсоида, но использует набор точек поверхности, а не двоичный объем. Возможно, вы сможете адаптировать этот код под свои нужды.

Обновление

Ссылка , предоставленная Крисом в комментарии, предполагает, что можно определить четкую математическую связь для того, как связаны вторые центральные моменты и радиусы эллипса. Хотя у меня еще не было возможности проработать математику, я заметил, что простое масштабирование PrincipalAxisLength на sqrt(5/16) дает значения, соблазнительно близкие к R:

>> sqrt(5/16).*stats.PrincipalAxisLength

ans =

  40.008372204885049   9.970908565527971   9.970908565527971
...