SciSharp/Numpy.NET

fft() failed: “index -2 is out of bounds for axis 0 with size 1”

timiil opened this issue · 9 comments

test.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Emgu.CV" Version="4.6.0.5131" />
    <PackageReference Include="Emgu.CV.runtime.windows" Version="4.6.0.5131" />
    <PackageReference Include="Numpy" Version="3.11.1.33" />
  </ItemGroup>

</Project>

Program.cs:

using Emgu.CV;
using Emgu.CV.Structure;
using Numpy;


Image<Gray, byte> img = new Image<Gray, byte>(args[0]);

var data = img.Mat.GetRawData();
var ndasrc = np.asfarray(data);
var ndaFFT = np.fft.fft2(ndasrc);    //failed here ->

Console.WriteLine(ndaFFT.len);

dotnet run ..\green.tif

failed:

Could not find platform dependent libraries <exec_prefix>
Unhandled exception. Python.Runtime.PythonException: index -2 is out of bounds for axis 0 with size 1
  File "C:\Users\timiil\AppData\Local\python-3.11.0-embed-amd64\Lib\numpy\core\fromnumeric.py", line 43, in _wrapit
    result = getattr(asarray(obj), method)(*args, **kwds)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\timiil\AppData\Local\python-3.11.0-embed-amd64\Lib\numpy\core\fromnumeric.py", line 54, in _wrapfunc
    return _wrapit(obj, method, *args, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\timiil\AppData\Local\python-3.11.0-embed-amd64\Lib\numpy\core\fromnumeric.py", line 190, in take
    return _wrapfunc(a, 'take', indices, axis=axis, out=out, mode=mode)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<__array_function__ internals>", line 180, in take
  File "C:\Users\timiil\AppData\Local\python-3.11.0-embed-amd64\Lib\numpy\fft\_pocketfft.py", line 688, in _cook_nd_args
    s = take(a.shape, axes)
        ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\timiil\AppData\Local\python-3.11.0-embed-amd64\Lib\numpy\fft\_pocketfft.py", line 703, in _raw_fftnd
    s, axes = _cook_nd_args(a, s, axes)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\timiil\AppData\Local\python-3.11.0-embed-amd64\Lib\numpy\fft\_pocketfft.py", line 1014, in fft2
    return _raw_fftnd(a, s, axes, fft, norm)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<__array_function__ internals>", line 180, in fft2
   at Python.Runtime.PythonException.ThrowLastAsClrException()
   at Python.Runtime.PyObject.Invoke(PyTuple args, PyDict kw)
   at Python.Runtime.PyObject.InvokeMethod(String name, PyTuple args, PyDict kw)
   at Numpy.np.fft.fft2(NDarray a, Int32[] s, Int32[] axes, String norm)
   at Program.<Main>$(String[] args) in D:\code\bandpass\app\bandpassdemo\Program.cs:line 13

henon commented

Can you make a little snippet that doesn't depend on anything else? Show that it works in Python and that it fails in Numpy.NET. Then I can fix the problem quickly.

henon commented

And no huge data like images please.

test.py:

import cv2
import numpy as np

img = cv2.imread("green.tif", cv2.IMREAD_GRAYSCALE)

fft_img = np.fft.fft2(img)
fft_img = np.fft.fftshift(fft_img)

print(fft_img.size)
python3 ./test.py

the above code is very work. any kind of image like tif or png is OK .

henon commented

I have here a snippet without cv2 that works in python:

>>> img = np.arange(27).reshape(3,3,3)
>>> img
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]],

       [[18, 19, 20],
        [21, 22, 23],
        [24, 25, 26]]])
>>> fft_img = np.fft.fft2(img)
>>> fft_img = np.fft.fftshift(fft_img)
>>> fft_img
array([[[  0. +0.j        , -13.5-7.79422863j,   0. +0.j        ],
        [ -4.5-2.59807621j, 198. +0.j        ,  -4.5+2.59807621j],
        [  0. +0.j        , -13.5+7.79422863j,   0. +0.j        ]],

       [[  0. +0.j        , -13.5-7.79422863j,   0. +0.j        ],
        [ -4.5-2.59807621j,  36. +0.j        ,  -4.5+2.59807621j],
        [  0. +0.j        , -13.5+7.79422863j,   0. +0.j        ]],

       [[  0. +0.j        , -13.5-7.79422863j,   0. +0.j        ],
        [ -4.5-2.59807621j, 117. +0.j        ,  -4.5+2.59807621j],
        [  0. +0.j        , -13.5+7.79422863j,   0. +0.j        ]]])
>>>

It also works in C# with Numpy.NET

        [TestMethod]
        public async Task IssueByTimiil()
        {            
            var img = np.arange(27).reshape(3, 3, 3);
            var fft_img = np.fft.fft2(img);
            fft_img = np.fft.fftshift(fft_img);
            Console.WriteLine(fft_img.repr);
        }

So my conclusion is that the data you input is wrong. I guess the shape is wrong because I get the same error in python when I apply fft2 to a one-dimensional array.

opencv load an image into an struct Image<Gray, byte> , which should be a 'two dimensional matrix', do i need to convert 'Image<Gray, byte>' or 'Mat' into a one-dimensional array to join fftshift method ??

henon commented

Image<Gray, byte> img = new Image<Gray, byte>(args[0]);

var data = img.Mat.GetRawData();
var ndasrc = np.asfarray(data);
var ndaFFT = np.fft.fft2(ndasrc); //failed here ->

By doing a GetRawData you get a 1D array and you create a 1D arra ndasrc from it. I guess you need to reshape it so that it has the dimensions of the image.

henon commented

To be clear you need to do this:

var data = img.Mat.GetRawData();
var ndasrc = np.asfarray(data).reshape(imagew, imageh); 

before doing the fft2

To be clear you need to do this:

var data = img.Mat.GetRawData();
var ndasrc = np.asfarray(data).reshape(imagew, imageh); 

before doing the fft2

thanks very much, it is all WORK for now:

var file = args.Length > 0 ? args[0] : @"..\..\..\..\green.tif";
Image<Gray, byte> img = new Image<Gray, byte>(file);

var data = img.Mat.GetRawData();
var ndasrc = np.asfarray(data);
var reshape = ndasrc.reshape(img.Height, img.Width);

var ndaFFT = np.fft.fft2(reshape);

var fftShift = np.fft.fftshift(ndaFFT);

...

Thanks you very much.

BTW, hou can i convert the NDArray back to CLR types ?

var file = args.Length > 0 ? args[0] : @"..\..\..\..\green.tif";
Image<Gray, byte> img = new Image<Gray, byte>(file);

var data = img.Mat.GetRawData();
var ndasrc = np.asfarray(data);
var reshape = ndasrc.reshape(img.Height, img.Width);

byte[,] backraw = null;  //which API can make reshape convert (boxing) back to backraw ??

henon commented

Getting the data of an NDarray as a C# array is documented here: https://github.com/SciSharp/Numpy.NET#create-a-numpy-array-from-a-c-array-and-vice-versa