Labsmore / pyuscope

Python machine vision platform
BSD 2-Clause "Simplified" License
80 stars 17 forks source link

Documentation request: how to derive the optical factors in the microscope config #475

Open philpem opened 5 months ago

philpem commented 5 months ago

In the configuration for a microscope there are several parameters related to its optical setup. These seem to be fed into a bunch of places in Pyuscope. It would be good to have some documentation about which of these parameters are important, and how to derive them.

Reason being, I have an Olympus BH2 series Metallurgical microscope which I've customised by adding a Raspberry Pi HQ Camera and a motorised X-Y stage for use with Pyuscope. I also have objectives which aren't included in the default Pyuscope setup.

Settings like native_pixel_pitch_um seem fairly straightforward and I've got a working value from the IMX477 datasheet. However I have no idea how to pass details of the optical path to Pyuscope (there's a projection lens on the trinocular port, and a relay lens in the C-mount adapter), or create profiles for the objectives I have (Olympus MSPlan and Plan series).

The LIP-A1 config includes some configurations which seem to relate to a relay lens, but there are no details about how e.g, the x_view value was derived.

I have an Olympus OBMM reflective scale so can put that on the stage and take measurements if needed.

philpem commented 4 months ago

I've been looking into this, and think I've figured it out - but would appreciate some confirmation/commentary. Apologies for the length of this comment, it includes a lot of working-out!

At the moment, I have native_pixel_pitch_um = 1.55 in the config, which matches the raw pixel size of the IMX477 sensor. I'm finding that the overlap Pyuscope gives on scans is excessive. I could delete every other image and still be able to stitch them together.

On the optical side, my BH2 has a WF10x eyepiece mated with a set of objectives on the turret. If I had the 5x selected (as an example), the total magnification would be 5x times the 10x of the viewfinder, or 50x.

The camera setup on the BH2 is intended to match the field of view of the optical viewfinder, provided that the correct parts are used. With a 35mm film or digital SLR setup, there'd be a Photomicro Adapter and NFK 2.5x LD projection eyepiece on the trinocular turret. This should, in theory, produce an image with the same field of view as what would be seen through the microscope eyepiece. This makes a sort of sense and fits for most applications where the size of the object on the stage doesn't need to be known.

With a video camera mounted, the setup is slightly different. The same NFK 2.5x LD is in play, along with a 0.3x relay lens in the C-mount adapter, which steps the 43.26mm diagonal image (35mm film frame) down to 16mm diagonal for a 1" C-mount sensor. This gives mostly the same field of view (in theory). This would also apply to the IMX477 if it were a 1" sensor: but it's not, it's a 1/2.3" (7.857mm diagonal) sensor. That means there's a 16/7.856 ~= 2.04x magnification caused by the sensor being smaller than the projected image circle (aka "crop factor").

Pulling this discussion back to Pyuscope: from its perspective, during a pan scan, the X and Y motion step need to be calculated from several known factors:

The X and Y pixel size multiplied by the pixel size gives the active area size:

To figure out the total magnification factor, I picked the 10x objective, found two features on an IC I had on the stage, and measured the X and Y travel needed to move them to the opposite side of the image:

Working backwards:

Unfortunately I haven't been able to work out how the lens factors (2.5x projection eyepiece, 0.3x relay lens) and crop factor (2.04x) end up in this number - but it seems to be correct because it gives accurate images with about 30% overlap, which matches the Pyuscope logs.