Как повернуть трехмерное изображение спектра в цифровой микрофотографии с помощью сценария?

Я хочу найти эквивалент команды сценария rotate(image, Degree) для поворота вокруг оси x или y (мне нужны только повороты на 90º). Я знаю, что могу сделать это с помощью меню инструментов, но было бы намного быстрее, если бы я мог найти команду или функцию, чтобы сделать это с помощью скрипта.

Заранее спасибо!


person Mario Peláez Fernández    schedule 31.08.2018    source источник


Ответы (2)


Использование команды Slice поначалу может сбивать с толку, поэтому вот подробное объяснение использования команды для вращения вокруг оси X.

В этом примере показано, как можно повернуть 3D-данные по часовой стрелке вокруг оси X (просмотр вдоль X) с помощью команды Slice3.

Команда Slice3 задает новое представление существующего массива данных.

  • Сначала он указывает исходный пиксель, то есть координаты (в исходных данных), которые будут представлены (0,0,0) в новом представлении.

  • Затем он указывает направление дискретизации, длину и размер шага для каждой из своих новых трех осей.
    Первый триплет указывает, как координаты (в исходных данных) изменяются в направлении x нового изображения, второй триплет — в направлении y нового изображения, а последний триплет — в направлении z нового изображения.

Таким образом, вращение вокруг оси X можно представить как: Вращение вокруг X

Для «пересчитанных» данных:

  • Новые (повернутые) данные имеют свое начало в исходной точке данных (0,0,SZ-1).
  • Его направление X остается прежним, т. е. один шаг по X в новых данных будет увеличивать тройку координат в исходных данных также на (1,0,0). из 1.
  • Его направление Y по сути является отрицательным направлением Z предыдущего, т. е. один шаг по оси Y в новых данных увеличит тройку координат в исходных данных также на (0,0,-1).
    Итак, продолжаем. Шаги SZ с размером шага -1.
  • Его направление Z, по сути, является направлением Y предыдущего, т. е. один шаг по оси Z в новых данных увеличивает триплет координат в исходных данных на (0,1,0). размер шага 1.

Итак, для вращения по часовой стрелке вокруг оси X используется следующая команда:
img.Slice3( 0,0,SZ-1, 0,SX,1, 2,SZ,-1, 1,SY,1 )

Эта команда просто создаст новое представление для тех же данных (т.е. дополнительная память не используется). Таким образом, чтобы получить повернутое изображение как новое изображение (со значениями данных, выровненными так, как они должны быть в памяти) , можно было бы клонировать это представление в новое изображение, используя ImageClone()

Итого, следующий скрипт показывает это в качестве примера:

// Demo of rotating 3D data orthogonally around the X axis
// This is done by resampling the data using the Slice3 command

// Creation of test image with regcognizeable pattern
number SX = 100
number SY = 30
number SZ = 50
image img := RealImage("Test",4, SX,SY,SZ)

// trig. modulated linear increase in X
img =  icol/iwidth* sin( icol/(iwidth-1) * 5 * Pi() ) **2       
// Simple linear increase in Y
img += (irow/iheight) * 2                                   
// Modulation of values in Z 
// (doubling values for index 0,1, 3, 4, 9, 16, 25, 36, 49) 
img *= (SQRT(iplane) == trunc(SQRT(iplane)) ? 2 : 1 )       
img.ShowImage()

// Show captions. Image coordinate system is
// Origin (0,0,0) in top-left-front most pixel
// X axis goes left to right
// Y axis goes top to down
// Z axis goes front to back 
img.ImageSetDimensionCalibration(0,0,1,"orig X",0)
img.ImageSetDimensionCalibration(1,0,1,"orig Y",0)
img.ImageSetDimensionCalibration(2,0,1,"orig Z",0)
img.ImageGetImageDisplay(0).ImageDisplaySetCaptionOn(1)

// Rotation around X axis, clockwise looking along X
// X --> X`  (unchanged)
// Y --> Z'
// Z --> -Y'
// old origin moves to bottom-left-front most 
// This means for "new" sampling:
// Specify sampling starting point:
//   New origin (0,0,0)'  will be value which was at (0,0,SZ-1)
//   Going one step in X' in the new data, will be like going one step in X 
//   Going one step in Y' in the new data, will be like going one step backwards in Z 
//   Going one step in Z' in the new data, will be like going one step in Y
image rotXCW := img.Slice3( 0,0,SZ-1, 0,SX,1, 2,SZ,-1, 1,SY,1 ).ImageClone()
rotXCW.SetName("rotated X, CW")
rotXCW.ShowImage()
rotXCW.ImageGetImageDisplay(0).ImageDisplaySetCaptionOn(1)


Следующие методы выполняют повороты на 90 градусов:

// Functions for 90degree rotations of data
image RotateXCW( image input )
{
    number SX,SY,SZ
    input.Get3DSize(SX,SY,SZ)
    return input.Slice3( 0,0,SZ-1, 0,SX,1, 2,SZ,-1, 1,SY,1 ).ImageClone()
}

image RotateXCCW( image input )
{
    number SX,SY,SZ
    input.Get3DSize(SX,SY,SZ)
    return input.Slice3( 0,SY-1,0, 0,SX,1, 2,SZ,1, 1,SY,-1 ).ImageClone()
}

image RotateYCW( image input )
{
    number SX,SY,SZ
    input.Get3DSize(SX,SY,SZ)
    return input.Slice3( SX-1,0,0, 2,SZ,1, 1,SY,1, 0,SX,-1 ).ImageClone()
}

image RotateYCCW( image input )
{
    number SX,SY,SZ
    input.Get3DSize(SX,SY,SZ)
    return input.Slice3( 0,0,SZ-1, 2,SZ,-1, 1,SY,1, 0,SX,1 ).ImageClone()
}

image RotateZCW( image input )
{
    number SX,SY,SZ
    input.Get3DSize(SX,SY,SZ)
    return input.Slice3( 0,SY-1,0, 1,SY,-1, 0,SX,1, 2,SZ,1 ).ImageClone()
}

image RotateZCCW( image input )
{
    number SX,SY,SZ
    input.Get3DSize(SX,SY,SZ)
    return input.Slice3( SX-1,0,0, 1,SY,1, 0,SX,-1, 2,SZ,1 ).ImageClone()
}

Вращение вокруг оси z также может быть выполнено с помощью RotateRight() и RotateLeft(). Обратите внимание, однако, что эти команды не адаптируют калибровку размеров изображений, в отличие от команды Slice3.

person BmyGuest    schedule 01.09.2018

Для чистого ортогонального вращения самым простым (и самым быстрым) способом является использование команд «slice», то есть «slice3» для 3D-изображений. Оказывается, в последней версии GMS есть пример в справочной документации, поэтому я просто копирую код сюда:

number sx = 10
number sy = 10
number sz = 10

number csx, csy, csz 
image img3D := RealImage( "3D", 4, sx, sy, sz )
img3D = 1000 + sin( 2*PI() * iplane/(idepth-1) ) * 100 + icol * 10  + irow
img3D.ShowImage()

// Rotate existing image
if ( OKCancelDialog( "Rotate clockwise (each plane)\n= Rotate block around z-axis" ) )
 img3D.RotateRight()



if ( OKCancelDialog( "Rotate counter-clockwise (each plane)\n= Rotate block around z-axis" ) )
 img3D.RotateLeft()


if ( OKCancelDialog( "Rotate block counter-clockwise around X-axis" ) )
{
 // Equivalent of sampling the data anew
 // x-axis remains 
 // y- and z-axis change their role
 img3D.Get3DSize( csx, csy, csz )        // current size along axes
 img3D = img3D.Slice3( 0,0,0, 0,csx,1, 2,csz,1, 1,csy,1 )
}

if ( OKCancelDialog( "Rotate block clockwise around X-axis" ) )
{
 // Equivalent of sampling the data anew
 // x-axis remains 
 // y- and z-axis change their role
 img3D.Get3DSize( csx, csy, csz )        // current size along axes
 img3D = img3D.Slice3( 0,csy-1,csz-1, 0,csx,1, 2,csz,-1, 1,csy,-1 )
}

if ( OKCancelDialog( "Rotate 30 degree (each plane)\n= Rotate block around z-axis" ) )
{
 number aDeg = 30
 number interpolMeth = 2
 number keepSize = 1
 image rotImg := img3D.Rotate( 2*Pi()/360 * aDeg, interpolMeth, keepSize )
 rotImg.ShowImage()
}

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

person BmyGuest    schedule 31.08.2018