tlambert03 / nd2

Full-featured nd2 (Nikon NIS Elements) file reader for python. Outputs to numpy, dask, and xarray. Exhaustive metadata extraction
https://tlambert03.github.io/nd2
BSD 3-Clause "New" or "Revised" License
51 stars 15 forks source link

How to convert ROI coordinates from relative to pixels #232

Open Kees-van-der-Oord-Nikon opened 2 months ago

Kees-van-der-Oord-Nikon commented 2 months ago

Description

This is not really an issue, just a suggestion to add to the documentation

What I Did

The code below converts the ROI coordinates from relative fractions to pixel coordinates. The Ellipse ROI width and height are before rotation over the indicated angle. The only missing detail is the inner circle of the Ring ROI.

f = nd2.ND2File(sys.argv[1])

mid_x = f.shape[1] / 2.
mid_y = f.shape[0] / 2.

def RelToPixSizeX(x):
    return mid_x * x

def RelToPixSizeY(y):
    return mid_y * y

def RelToPixPosX(x):
    return mid_x + mid_x * x

def RelToPixPosY(y):
    return mid_y + mid_y * y

for id in f.rois:
    roi = f.rois[id]
    header = str(roi.id) + ";" + nd2.structures.RoiShapeType(roi.info.shapeType).name + ";"
    pnts = ""
    info = roi.animParams[0]
    if (roi.info.shapeType == nd2.structures.RoiShapeType.Rectangle) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.Square) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.Circle) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.Ellipse) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.Ring):
        pnts = "(" + \
            "{:#.1f}".format(RelToPixPosX(info.centerX)) + "," + \
            "{:#.1f}".format(RelToPixPosY(info.centerY)) + "),(" + \
            "{:#.1f}".format(RelToPixSizeX(info.boxShape.sizeX)) + "," + \
            "{:#.1f}".format(RelToPixSizeY(info.boxShape.sizeY)) + ")"
    elif (roi.info.shapeType == nd2.structures.RoiShapeType.Line) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.Polygon) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.PolyLine) or \
            (roi.info.shapeType == nd2.structures.RoiShapeType.Bezier):
        for pnt in roi.animParams[0].extrudedShape.basePoints:
            if len(pnts) != 0:
                pnts += ","
            pnts += "(" + "{:#.1f}".format(RelToPixPosX(pnt.x+info.centerX)) + "," + "{:#.1f}".format(RelToPixPosY(pnt.y+info.centerY)) + ")"
    print(header + pnts + ";" + "{:#.4f}".format(info.rotationZ))

f.close()

WR,

Kees

tlambert03 commented 2 months ago

hey @Kees-van-der-Oord-Nikon

Thanks for your note. I agree, it's pretty cumbersome to use ROIs straight from the file metadata :joy: This is great and i'd be happy to add a convenience like this to the code base. Would you be interested in opening a PR to that effect? (Happy to do it myself if not)

Kees-van-der-Oord-Nikon commented 2 months ago

Dear Talley,

Thanks for your response. I think you are more fluent in github than me, so please do the PR. The biggest challenge was that f.shape array has the dimensions in an unexpected order (height,width).

I think the interface should support moving ROIs as well. I expect that the animsParam array has more entries in that case (one for every control frame ?)

WR,

Kees

Dr. Kees van der Oord European Support Specialist T: +31207099246 M: +31623367589 E: @.*** Website Nikon Europe B.V. Stroombaan 14 1181 VX Amstelveen Netherlands

Registered Chamber of Commerce Amsterdam No. 34139593 VAT No. NL 8091.99.889.B.01

This e-mail may contain information that is PRIVILEGED and/or CONFIDENTIAL. This e-mail is intended solely for the individual or entity to whom it is addressed. If you are not, or have reason to believe you are not the intended recipient of this e-mail please contact us by reply e-mail as soon as possible. Immediately after contacting us, please destroy this e-mail (including attachment(s)) from your computer system(s). Any unauthorized copying, disclosure or distribution of this e-mail (including attachment(s)) is not allowed. Nikon Europe BV hereby disclaims any and all liabilities which may arise in relation to any of its electronic communication. No obligation is entered into by virtue of this e-mail, unless confirmed in writing and duly signed by an authorized representative of Nikon Europe BV From: Talley Lambert @.> Sent: 20 June, 2024 16:29 To: tlambert03/nd2 @.> Cc: Oord, Kees van der @.>; Mention @.> Subject: Re: [tlambert03/nd2] How to convert ROI coordinates from relative to pixels (Issue #232)

hey @Kees-van-der-Oord-Nikonhttps://github.com/Kees-van-der-Oord-Nikon

Thanks for your note. I agree, it's pretty cumbersome to use ROIs straight from the file metadata 😂 This is great and i'd be happy to add a convenience like this to the code base. Would you be interested in opening a PR to that effect? (Happy to do it myself if not)

— Reply to this email directly, view it on GitHubhttps://github.com/tlambert03/nd2/issues/232#issuecomment-2180853580, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AXSSBOSB2W2GBE4FDVE7EPTZILRJZAVCNFSM6AAAAABJUA6XNOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOBQHA2TGNJYGA. You are receiving this because you were mentioned.Message ID: @.**@.>>

tlambert03 commented 2 months ago

please do the PR.

no worries, will do

The biggest challenge was that f.shape array has the dimensions in an unexpected order (height,width).

yes (height, width) (row major) is the standard convention for arrays in python, numpy, etc.., so nd2 sticks with this convention. it's true that needs to be taken into consideration when comparing to the file metadata