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

Issues with EllipseModel #5042

Closed
rk-exxec opened this issue Oct 30, 2020 · 8 comments
Closed

Issues with EllipseModel #5042

rk-exxec opened this issue Oct 30, 2020 · 8 comments

Comments

@rk-exxec
Copy link
Contributor

rk-exxec commented Oct 30, 2020

Description

Hey, I have issues with the EllipseMopdel estimate function.
It produces a completely wrong ellipse, what am I doing wrong.
This is what it looks like:
grafik

I am detecting a contour with opencv (blue line) and then feeding that contour to the EllipseModel.

Way to reproduce

import math
import cv2
import numpy as np
from skimage.measure import EllipseModel
def evaluate_droplet(img, y_base):
    crop_img = img[:y_base,:]
    shape = img.shape
    height = shape[0]
    width = shape[1]

    bw_edges = cv2.Canny(crop_img, 76, 179)

    contours, hierarchy = cv2.findContours(bw_edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    if len(contours) == 0:
        raise ValueError('No contours found!')

    edge = max(contours, key=cv2.contourArea)

    img = cv2.drawContours(img,edge,-1,(255,0,0),2)
    points = edge.reshape(-1,2)
    ell = EllipseModel()
    if not ell.estimate(points): raise RuntimeError('Couldn\'t fit ellipse')
    x0, y0, a, b, phi = ell.params

    img = cv2.ellipse(img, (int(round(x0)),int(round(y0))), (int(round(a)),int(round(b))), int(round(math.degrees(phi))), 0, 360, (255,0,255), thickness=1, lineType=cv2.LINE_AA)

if __name__ == "__main__":
    im = cv2.imread('untitled1.png')
    try:
        drp = evaluate_droplet(im, 250)
    except Exception as ex:
        print(ex)
    cv2.imshow('Test',im)
    cv2.waitKey(0)

Version information

>>> import sys; print(sys.version)
3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]
>>> import platform; print(platform.platform())
Windows-10-10.0.18362-SP0
>>> import skimage; print("scikit-image version: {}".format(skimage.__version__))
scikit-image version: 0.17.2
>>> import numpy; print("numpy version: {}".format(numpy.__version__))
numpy version: 1.19.2

Original image:
untitled1

@jni jni added the type: bug label Oct 31, 2020
@jni
Copy link
Member

jni commented Oct 31, 2020

I gotta say I can't figure this one out after a bit of playing with it. Anyone in @scikit-image/core have experience with ellipse estimation and have time to play with this?

@mark-boer
Copy link
Contributor

This looks interesting, I have some experience with fitting geometric shapes (mostly 3D tho), I'll have a look, maybe I can figure it out.

@mark-boer
Copy link
Contributor

mark-boer commented Jan 7, 2021

Found it! It is an integer overflow in

S1 = D1.T @ D1
Just convert your input to floats, points = points.astype(float). That should fix your issue.

Also, be careful with using opencv and scikit-image, they have slightly different definitions of the order of coordinates 😉

@maintainers we should probably convert the input of CircleModelestimate.estimate and EllipseModel.estimate to floats, because they are pretty much guaranteed to overflow.

Happy coding!

@grlee77
Copy link
Contributor

grlee77 commented Jan 7, 2021

@maintainers we should probably convert the input of CircleModelestimate.estimate and EllipseModel.estimate to floats, because they are pretty much guaranteed to overflow.

Thanks for looking into this! Indeed, it seems like casting data to float should be done within these functions. Are you interested in making a PR for this? (no worries if you want us to handle it, just let us know)

@grlee77
Copy link
Contributor

grlee77 commented Jan 7, 2021

p.s. I don't think maintainers pings anyone here? Most likely @scikit-image/core was what you wanted, but in general we try to monitor new issues, so usually it won't be necessary to specifically ping the full team unless you think something is falling through the cracks and needs special attention.

@mark-boer
Copy link
Contributor

Thanks for looking into this! Indeed, it seems like casting data to float should be done within these functions. Are you interested in making a PR for this? (no worries if you want us to handle it, just let us know)

Sure, I'll create one this weekend.

@rk-exxec
Copy link
Contributor Author

rk-exxec commented Jan 7, 2021

Thank you mark!

@rfezzani
Copy link
Member

Closing this since #5179 is merged. Thank you again @mark-boer 😉

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

5 participants