Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read .pfm to numpy and conversion from pixel to world #16

Closed
zaksel opened this issue Feb 13, 2020 · 3 comments
Closed

Read .pfm to numpy and conversion from pixel to world #16

zaksel opened this issue Feb 13, 2020 · 3 comments

Comments

@zaksel
Copy link

zaksel commented Feb 13, 2020

Hi,
i am using a rc_visard 65m and this library to stream disparity images via GenICam.
I read the Image from the .pfm-File (e.g. image_946691111.740987800_Disparity_1_0.zip) with this snippet (abducted from here: https://lmb.informatik.uni-freiburg.de/resources/datasets/IO.py):

            file = open(path_to_pfm, 'rb')
            #skip metadata
            file.readline().rstrip()
            file.readline().rstrip()
            file.readline().rstrip()
            #read into numpy array Big Endian float
            data = np.fromfile(file, dtype='>f')
            #reshape and flip
            data = np.reshape(data, (480, 640))
            data = np.flipud(data)

And get this Image:
DisparityImage

I got the cam parameters via gc_info serial_no?Scan3dControl and they are:

self.params = {'FocalLengthFactor': 0.843637, 'Scan3dOutputMode': 'DisparityC', 'Scan3dDistanceUnit': 'Pixel', 'Scan3dCoordinateOffset': 0.0, 'Scan3dInvalidDataValue': 0.0, 'Scan3dCoordinateScale': 0.0625, 'Scan3dInvalidDataFlag': 1.0, 'Scan3dFocalLength': 539.927, 'Scan3dBaseline': 0.0649325, 'Scan3dPrincipalPointU': 320.0, 'Scan3dPrincipalPointV': 240.0, 'Baseline': 0.0649325}

But when I want to calculate the pixel [240, 320] in real world coordinates like here:
https://doc.rc-visard.com/latest/en/gigevision.html#image-stream-conversions

        p_x = (x-self.params['Scan3dPrincipalPointU']) * self.params['Scan3dBaseline']/(dik*self.params['Scan3dCoordinateScale'])
        p_y = (y-self.params['Scan3dPrincipalPointV']) * self.params['Scan3dBaseline']/(dik*self.params['Scan3dCoordinateScale'])
        p_z = self.params['Scan3dFocalLength'] * self.params['Scan3dBaseline']/(dik*self.params['Scan3dCoordinateScale'])

The distance for an Object that is 80cm away is p_z=7.6m.

I think i've made a mistake reading the disparity Image from file, because my Image contains very small values. More like uint8 than uint16. And so dik is small and p_z is following by that too big.

I have tried to change dtype='>u2' when reading the .pfm but then i cant shape the Image to the correct size because i get twice as much values (614400 instead of 307200)?

Anybody knows where I have made a mistake or succeeded with getting the conversion from pixel to world done?

Thanks for your help
derEskimo

@zaksel

This comment has been minimized.

@flixr
Copy link
Member

flixr commented Feb 13, 2020

The Scan3dCoordinateScale is only needed when converting the 16bit image (as in the GenICam image buffer) to a floating point disparity value in pixels.

Since you are using the cli tool gc_stream which already saves the disparity image in float format (*.pfm), you alreay have the floating point value in pixels and the scaling should not be applied again.

@zaksel
Copy link
Author

zaksel commented Feb 13, 2020

Ahh alright. Thank you! So i do the conversion like that:

p_x = (x-self.params['Scan3dPrincipalPointU']) * self.params['Scan3dBaseline']/dik
p_y = (y-self.params['Scan3dPrincipalPointV']) * self.params['Scan3dBaseline']/dik
p_z = self.params['Scan3dFocalLength'] * self.params['Scan3dBaseline']/dik

@zaksel zaksel closed this as completed Feb 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants