Modify an element in a matrix

Hi, if I want to modify an element in a matrix, in ITK 4.13.3, I can code like


But in ITK 5.2.1, the same code seems fail to change the element.

I’d like to know what’s the way to do this in ITK 5. Thanks in advance.

@matt.mccormick, trying the above code on my computer also gives me an error, in two different environments:

Python 3.8.13 | packaged by conda-forge | (default, Mar 25 2022, 05:59:45) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import itk
>>> a=itk.Matrix[itk.D,3,3]
>>> a.GetVnlMatrix().set(0,0,1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: GetVnlMatrix() missing 1 required positional argument: 'self'
>>> itk.__file__
'C:\\Users\\Dzenan\\miniconda3\\envs\\deep_learning\\lib\\site-packages\\itk\\__init__.py'
>>> itk.__version__
'5.2.1'
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import itk
>>> a=itk.Matrix[itk.D,3,3]
>>> a.GetVnlMatrix().set(0,0,1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: GetVnlMatrix() missing 1 required positional argument: 'self'
>>> itk.__file__
'M:\\a\\ITK-py\\Wrapping\\Generators\\Python\\itk\\__init__.py'
>>> itk.__version__
'5.3.0'

Ooops, I forgot instantiation parentheses. With that I get the same output as @zhuangming.shen in both of these enviroments.

I think the use of set was incorrect originally. vnl_matrix has a set method, but it’s not doing what you are trying to do there.

  //: Fills (laminates) this matrix with the given data, then returns it.
  // A synonym for copy_in()
  vnl_matrix& set(T const *d) { return copy_in(d); }

If you want to set a pixel in a vnl_matrix, you need to use put instead of set. Or probably easier, use itk.GetArrayViewFromVnlMatrix. And use numpy operator [] to manipulate it.

I am not sure if the ITK4 code is calling a constructor on-the-fly with arguments (0, 0, 1) and passing it to set?

I tried “put” instead of “set”, but still fail to change the element in ITK 5.2.1.

Umm, the problem is that the GetVnlMatrix() returns a copy, instead of a reference.

In [2]: m = itk.Matrix[itk.D, 3,3]()

In [3]: m
Out[3]: itkMatrixD33 ([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]])

In [4]: m.GetVnlMatrix()
Out[4]: <itk.vnl_matrix_fixedPython.vnl_matrix_fixedD_3_3; proxy of <Swig Object of type 'vnl_matrix_fixedD_3_3 *' at 0x7fb3662bdb90> >

In [5]: m.GetVnlMatrix()
Out[5]: <itk.vnl_matrix_fixedPython.vnl_matrix_fixedD_3_3; proxy of <Swig Object of type 'vnl_matrix_fixedD_3_3 *' at 0x7fb423e87240> >

It was changed here:

2 Likes

Opened an issue here:

Thanks for reporting it @zhuangming.shen
I am not sure right now how to modify an element from an itk.Matrix in python.

Since ITK can now convert matrices from / to NumPy arrays, I think the best is to do something like

>>> import itk
>>> import numpy as np
>>> m = itk.Matrix[itk.D, 3,3]()
>>> m.GetVnlMatrix().get(0,0)
0.0
>>> a=itk.array_from_matrix(m)
>>> a[0,0]=1
>>> m=itk.matrix_from_array(a)
>>> m.GetVnlMatrix().get(0,0)
1.0
4 Likes