с угла в трехмерном пространстве. Вам также необходимо уменьшить ширину искривленной фигуры при увеличении угла 3D.

оложим, у меня есть матрица 2x2, заполненная значениями, которые будут представлять плоскость. Теперь я хочу вращать плоскость вокруг себя в 3-х направлениях в направлении z. Для лучшего понимания смотрите следующее изображение:

Я задавался вопросом, возможно ли это с помощью простой аффинной матрицы, поэтому я создал следующий простой скрипт:

%Create a random value matrix
A = rand*ones(200,200);

%Make a box in the image
A(50:200-50,50:200-50) = 1;

Теперь я могу применять преобразования в двумерной комнате просто с помощью матрицы вращения, например:

R = affine2d([1 0 0; .5 1 0; 0 0 1])
tform = affine3d(R);
transformed = imwarp(A,tform);

Однако это не даст желаемого результата выше, и я не совсем уверен, как создать 2-D аффинную матрицу для создания такого поведения.

Я предполагаю, что трехмерная аффинная матрица может добиться цели. Однако, если я определю 3-D аффинную матрицу, я больше не смогу работать с 2-D представлением матрицы, так как MATLAB выдаст ошибку:

The number of dimensions of the input image A must be 3 when the
specified geometric transformation is 3-D.

Итак, как я могу кодировать желаемый результат с помощью аффинной матрицы?

 m3tho14 нояб. 2017 г., 11:17
Этот вопрос может быть полезным.

Ответы на вопрос(2)

которое можно оценить, используя положение углов на первом и втором изображениях.

originalP='peppers.png';
original = imread(originalP);
imshow(original);
s = size(original);
matchedPoints1 = [1 1;1 s(1);s(2) s(1);s(2) 1];
matchedPoints2 = [1 1;1 s(1);s(2) s(1)-100;s(2) 100];
transformType = 'projective';

tform = fitgeotrans(matchedPoints1,matchedPoints2,'projective');

outputView = imref2d(size(original));
Ir = imwarp(original,tform,'OutputView',outputView);
figure; imshow(Ir);

Это результат кода выше:

Исходное изображение:

Преобразованное изображение:

 Kev1n9114 нояб. 2017 г., 11:00
Спасибо за ваш ответ, это идет в правильном направлении. Можно ли указать угол напрямую? Или хотя бы знать, на сколько градусов было повернуто изображение?
 m3tho14 нояб. 2017 г., 11:12
Вы можете вычислить высоту черных треугольников (т.е.100 в 6-й строке) с угла на левой части изображения с помощью тригонометрии:H=s(2)*tan(angleRadiants), Но я понятия не имею, как вычислитьangleRadiants с угла в трехмерном пространстве. Вам также необходимо уменьшить ширину искривленной фигуры при увеличении угла 3D.
Решение Вопроса

ответ от m3tho правильно адрес, как вы быприменять преобразование вы хотите: используяfitgeotrans с'projective' преобразованиеТаким образом, требуется указать 4 контрольные точки (т.е. 4 пары соответствующих точек на входном и выходном изображении). Затем вы можете применить это преобразование, используяimwarp.

Таким образом, проблема заключается вкак Вы выбираете эти пары точек, чтобы создать желаемое преобразование, которое в этом случае должно создатьперспективная проекция, Как показано ниже, перспективная проекция принимает во внимание, что положение просмотра (то есть «камера») будет иметь заданный угол обзора, определяющий коническое поле зрения. Сцена визуализируется путем взятия всех трехмерных точек в пределах этого конуса и проецирования их на плоскость просмотра, которая является плоскостью, расположенной у цели камеры, которая перпендикулярна линии, соединяющей камеру и ее цель.

Давайте сначала предположим, что ваше изображение лежит в плоскости просмотра и что углы описываются нормализованной системой отсчета, так что они охватывают[-1 1] в каждом направлении. Сначала нам нужно выбрать желаемую степень перспективы, выбрав угол обзора, а затем вычислив расстояние между камерой и плоскостью обзора. Угол обзора около 45 градусов может имитировать ощущение перспективы нормального человеческого зрения, поэтому, используя углы плоскости обзора для определения края конического поля зрения, мы можем вычислить расстояние до камеры следующим образом:

camDist = sqrt(2)./tand(viewAngle./2);

Теперь мы можем использовать это для генерации набора контрольных точек для преобразования. Сначала мы применяем3-D вращение до угловых точек плоскости обзора, вращающихся вокруг оси y на величинуtheta, Это вращает их вне плоскости, поэтому мы теперь проецируем угловые точки обратно на плоскость просмотра, определяя линию от камеры через каждую повернутую угловую точку инайти точку пересечения плоскости, Я избавлю вас от математических выводов (вы можете реализовать их самостоятельно по формулам в приведенных выше ссылках), но в этом случае все упрощается до следующего набора вычислений:

term1 = camDist.*cosd(theta);
term2 = camDist-sind(theta);
term3 = camDist+sind(theta);
outP = [-term1./term2  camDist./term2; ...
         term1./term3  camDist./term3; ...
         term1./term3 -camDist./term3; ...
        -term1./term2 -camDist./term2];

А такжеoutP теперь содержит ваш нормализованный набор контрольных точек в выходном изображении. Учитывая изображение размераsМы можем создать набор входных и выходных контрольных точек следующим образом:

scaledInP = [1 s(1); s(2) s(1); s(2) 1; 1 1];
scaledOutP = bsxfun(@times, outP+1, s([2 1])-1)./2+1;

И вы можете применить преобразование так:

tform = fitgeotrans(scaledInP, scaledOutP, 'projective');
outputView = imref2d(s);
newImage = imwarp(oldImage, tform, 'OutputView', outputView);

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

Вот некоторый код, иллюстрирующий вышеприведенные преобразования путем анимации вращающегося изображения:

img = imread('peppers.png');
s = size(img);
outputView = imref2d(s);
scaledInP = [1 s(1); s(2) s(1); s(2) 1; 1 1];
viewAngle = 45;
camDist = sqrt(2)./tand(viewAngle./2);

for theta = linspace(0, 360, 360)
  term1 = camDist.*cosd(theta);
  term2 = camDist-sind(theta);
  term3 = camDist+sind(theta);
  outP = [-term1./term2  camDist./term2; ...
           term1./term3  camDist./term3; ...
           term1./term3 -camDist./term3; ...
          -term1./term2 -camDist./term2];
  scaledOutP = bsxfun(@times, outP+1, s([2 1])-1)./2+1;
  tform = fitgeotrans(scaledInP, scaledOutP, 'projective');
  spinImage = imwarp(img, tform, 'OutputView', outputView);
  if (theta == 0)
    hImage = image(spinImage);
    set(gca, 'Visible', 'off');
  else
    set(hImage, 'CData', spinImage);
  end
  drawnow;
end

А вот и анимация:

Ваш ответ на вопрос