From 8fd47d0f5438390241433b8d303df27225f4476e Mon Sep 17 00:00:00 2001 From: Sergiu Deitsch Date: Tue, 12 Nov 2024 17:52:20 +0100 Subject: [PATCH] wip --- .dockerignore | 1 + .github/ISSUE_TEMPLATE.md | 15 -- .github/workflows/linux.yml | 47 ++++++ .github/workflows/wheels.yaml | 35 +++++ .gitignore | 4 + .readthedocs.yaml | 14 ++ CITATION.cff | 12 ++ README.md | 22 +++ README.rst | 36 ----- conics/__about__.py | 5 + conics/__init__.py | 27 ++-- conics/fitting.py | 102 +------------ docs/authors.rst | 1 - docs/bibliography.rst | 5 + docs/conf.py | 101 ++++--------- docs/contributing.rst | 1 - docs/ellipse.rst | 7 + docs/fitting.rst | 77 ++++++++++ docs/general_form.rst | 34 +++++ docs/geometry.rst | 7 + docs/history.rst | 1 - docs/index.rst | 25 ++-- docs/installation.rst | 51 ------- docs/license.rst | 13 ++ docs/parabola.rst | 7 + docs/pose_estimation.rst | 5 + docs/readme.rst | 7 +- docs/references.bib | 265 ++++++++++++++++------------------ docs/requirements.txt | 4 + docs/usage.rst | 146 ++----------------- pyproject.toml | 83 +++++++++++ pytest.ini | 2 - requirements.txt | 10 +- scripts/normalize-bib.sh | 17 +++ tests/__init__.py | 18 --- tests/test_conics.py | 4 +- tests/test_ellipse.py | 3 +- tests/test_fitting.py | 1 + tests/test_geometry.py | 1 + tests/test_parabola.py | 3 +- tox.ini | 6 - 41 files changed, 610 insertions(+), 615 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/workflows/linux.yml create mode 100644 .github/workflows/wheels.yaml create mode 100644 .readthedocs.yaml create mode 100644 CITATION.cff create mode 100644 README.md delete mode 100644 README.rst create mode 100644 conics/__about__.py delete mode 100644 docs/authors.rst create mode 100644 docs/bibliography.rst delete mode 100644 docs/contributing.rst create mode 100644 docs/ellipse.rst create mode 100644 docs/fitting.rst create mode 100644 docs/general_form.rst create mode 100644 docs/geometry.rst delete mode 100644 docs/history.rst delete mode 100644 docs/installation.rst create mode 100644 docs/license.rst create mode 100644 docs/parabola.rst create mode 100644 docs/pose_estimation.rst create mode 100644 docs/requirements.txt create mode 100644 pyproject.toml delete mode 100644 pytest.ini create mode 100755 scripts/normalize-bib.sh delete mode 100644 tests/__init__.py diff --git a/.dockerignore b/.dockerignore index 49b2f54..492e2f3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ ** +!/docs/requirements.txt !/requirements.txt diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 2622af1..0000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,15 +0,0 @@ -* Conics version: -* Python version: -* Operating System: - -### Description - -Describe what you were trying to get done. -Tell us what happened, what went wrong, and what you expected to happen. - -### What I Did - -``` -Paste the command(s) you ran and the output. -If there was a crash, please include the traceback here. -``` diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..15d8240 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,47 @@ +name: Linux + +on: [push, pull_request] + +jobs: + deploy: + runs-on: ubuntu-24.04 + strategy: + matrix: + python: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + - '3.13' + - 'pypy3.10' + + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{matrix.python}} + cache: 'pip' + cache-dependency-path: requirements.txt + + - name: Setup Dependencies + run: | + pip install --verbose --editable . + + - name: Test + run: | + coverage run -m pytest --junit-xml=report.xml + + - name: Generate Coverage + run: | + coverage report + coverage xml + + - name: Upload Coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.xml + fail_ci_if_error: true + verbose: true diff --git a/.github/workflows/wheels.yaml b/.github/workflows/wheels.yaml new file mode 100644 index 0000000..1af2b64 --- /dev/null +++ b/.github/workflows/wheels.yaml @@ -0,0 +1,35 @@ +name: Publish to PyPI + +on: + schedule: + - cron: '42 1 * * *' + push: + # release: + # types: [published] + +jobs: + deploy: + runs-on: ubuntu-latest + environment: + name: PyPI + url: https://pypi.org/p/conics + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v3 + with: + python-version: '3.13' + + - name: Setup Dependencies + run: | + pip install build + + - name: Build + run: python -m build + + - name: Publish + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 diff --git a/.gitignore b/.gitignore index 92248c1..1ebc11a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ *.orig *.py[cod] +/.coverage +/.env/ +/dist/ /docs/_build/ +/docs/references.bib.blg __pycache__/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..6a285a8 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,14 @@ +version: 2 + +build: + os: ubuntu-24.04 + tools: + python: "3.12" + +sphinx: + configuration: docs/conf.py + fail_on_warning: true + +python: + install: + - requirements: requirements.txt diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..acf05ab --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,12 @@ +cff-version: 1.2.0 +message: If you use conics in your work, please reference it as below. +title: conics +abstract: Library for managing conic sections +authors: +- family-names: Deitsch + given-names: Sergiu + orcid: https://orcid.org/0000-0001-8865-8066 +version: 0.1.0 +date-released: 2019-05-21 +license: Apache-2.0 +repository-code: https://github.com/sergiud/conics diff --git a/README.md b/README.md new file mode 100644 index 0000000..6bd0eb3 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Conics + +[![codecov](https://codecov.io/gh/sergiud/conics/graph/badge.svg?token=89OIQDFWHV)](https://codecov.io/gh/sergiud/conics) +[![Documentation Status](https://readthedocs.org/projects/conics/badge/?version=latest)](https://conics.readthedocs.io/en/latest/?badge=latest) + + +.. image:: https://pyup.io/repos/github/sergiud/conics/shield.svg + :target: https://pyup.io/repos/github/sergiud/conics/ + :alt: Updates + +Conics is a library for managing conic sections (or simply *conics*). + +## Features + +* Creation of conics +* Transformation +* Computing intersections of conics +* 5-D pose estimation of the supporting plane of an ellipse + +## License + +The library is provided under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0). diff --git a/README.rst b/README.rst deleted file mode 100644 index aa0ae22..0000000 --- a/README.rst +++ /dev/null @@ -1,36 +0,0 @@ -====== -Conics -====== - - -.. image:: https://img.shields.io/pypi/v/conics.svg - :target: https://pypi.python.org/pypi/conics - -.. image:: https://img.shields.io/travis/sergiud/conics.svg - :target: https://travis-ci.com/sergiud/conics - -.. image:: https://readthedocs.org/projects/conics/badge/?version=latest - :target: https://conics.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - - -.. image:: https://pyup.io/repos/github/sergiud/conics/shield.svg - :target: https://pyup.io/repos/github/sergiud/conics/ - :alt: Updates - - - -Conics is a library for dealing with conic sections (or simply `conics`). - - -* Free software: BSD license -* Documentation: https://conics.readthedocs.io. - - -Features --------- - -* Creation of conics -* Transformation -* Computing intersections of conics -* 5-D pose estimation of the supporting plane of an ellipse diff --git a/conics/__about__.py b/conics/__about__.py new file mode 100644 index 0000000..d1da249 --- /dev/null +++ b/conics/__about__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2024-present Sergiu Deitsch +# +# SPDX-License-Identifier: Apache-2.0 + +__version__ = "0.1.0a1.dev1" diff --git a/conics/__init__.py b/conics/__init__.py index f2f4082..56f4d1b 100644 --- a/conics/__init__.py +++ b/conics/__init__.py @@ -15,16 +15,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Top-level package for Conics.""" +__author__ = 'Sergiu Deitsch' -__author__ = """Sergiu Deitsch""" -__email__ = 'sergiu.deitsch@gmail.com' -__version__ = '0.1.0' +from ._conic import concentric_conics_vanishing_line +from ._conic import Conic +from ._conic import estimate_pose +from ._conic import projected_center +from ._conic import surface_normal +from ._ellipse import Ellipse +from ._parabola import Parabola -from ._conic import concentric_conics_vanishing_line # noqa: F401 -from ._conic import Conic # noqa: F401 -from ._conic import estimate_pose # noqa: F401 -from ._conic import projected_center # noqa: F401 -from ._conic import surface_normal # noqa: F401 -from ._ellipse import Ellipse # noqa: F401 -from ._parabola import Parabola # noqa: F401 +__all__ = ('concentric_conics_vanishing_line', + 'Conic', + 'estimate_pose', + 'projected_center', + 'surface_normal', + 'Ellipse', + 'Parabola', + ) diff --git a/conics/fitting.py b/conics/fitting.py index f5c469b..c6a2400 100644 --- a/conics/fitting.py +++ b/conics/fitting.py @@ -17,7 +17,7 @@ from ._conic import Conic from ._harker import fit_harker # noqa: F401 -from ._nievergelt import fit_nievergelt +from ._nievergelt import fit_nievergelt # noqa: F401 from .geometry import hnormalized from .geometry import line_intersection from .geometry import line_through @@ -102,103 +102,3 @@ def parabola_to_bezier(parabola, start, end): inter = hnormalized(inter) return np.column_stack((s1, inter, s2)) - - -if __name__ == '__main__': - from . import Parabola - import matplotlib.patches as mpatches - import matplotlib.pyplot as plt - - x = [-7, -3, 0, 0, 1, 1] - y = [9, 5, 4, 8, 3, 5] - - # x = [-6.6, -2.8, -0.2, 0.4, 1.2, 1.4] - # y = [8.8, 5.4, 3.6, 7.8, 3.4, 4.8] - - y = [-2, -0.1, 0, 1, 2, 3, 4, 5, 6, 7, 8] - x = [1, 0.5, 0.1, 0, 0, 0, 0.2, 0.3, 0.4, 0.5, 0.6] - - # x = [-1, 2, 5, 10, -4] - # y = [1, -2, 3, -4, -3] - - x = [-1.1, 0, 0, 0, -0.5] - y = [0, 1, 2, 3, 4] - - # x = np.array([-4, -2, -1, 0, 1, 2, 4]) - # y = 2*x**2+1*x+5 # +0.25*x**2+0 - # y = np.array([-4, -2, -1, 0, 1, 2, 4]) - # x = -2 * y**2 - 0.5 # +0.25*x**2+0 - # x = [1, 0, 3, 4, 5] - # y = [3, -1, 10, 50, 100] - - # x = [-34.75, -22, -15.5, -8.0, -4, -1.0, 1.5, 4.5, 9.25, 17, 23.5, 36, 64.5] - # y = [20.25, 17, 15.0, 13.5, 13, 12.5, 12.5, 13.0, 14.00, 16, 18.0, 21, 29.5] - - pts = np.vstack((x, y)).astype(np.float) - # pts[1] *= 1e-2 - # C = fit_nievergelt(pts, type='hyperbola') - C = fit_nievergelt(pts, type='parabola', scale=True) - - C = C.constrain(pts, fix_angle=np.pi / 4) - - vertex, p, alpha = C.to_parabola() - pb = Parabola(vertex, p, alpha) - pb1 = pb.refine(pts) - - C = pb1.to_conic() - vertex, p, alpha = C.to_parabola() - - # plt.figure() - # plt.axis('equal') - - # R = rot2d(alpha) - # x = np.linspace(-10, 10) - # y2 = 2*p*x - # y = np.sqrt(y2) - - # x, y = R @ np.vstack((x, y)) + vertex[..., np.newaxis] - # plt.plot(x, y) - - # plt.show() - - plt.figure() - plt.axis('equal') - - x, y = pts - - X, Y = np.meshgrid(np.linspace(np.min(x) - 1, np.max(x) + 1), - np.linspace(-1 + np.min(y), np.max(y) + 1)) - Z = C(np.vstack((X.ravel(), Y.ravel()))) - - plt.contour(X, Y, Z.reshape(X.shape), levels=0) - plt.scatter(x, y) - plt.scatter(*vertex) - - pb = Parabola(vertex, p, alpha) - - s1, inter, s2 = parabola_to_bezier(pb, *pts[:, [0, -1]].T).T - - pp1 = np.column_stack((s1, inter)) - pp2 = np.column_stack((s2, inter)) - - plt.plot(pp1[0], pp1[1]) - plt.plot(pp2[0], pp2[1]) - - path = mpatches.Path(np.vstack((s1.T, inter, s2.T)), [mpatches.Path.MOVETO, - mpatches.Path.CURVE3, mpatches.Path.CURVE3]) - pp = mpatches.PathPatch( - path, - linestyle='--', - edgecolor='blue', - facecolor='none', - lw=3) - - plt.gca().add_artist(pp) - - plt.scatter(*inter) - plt.scatter(*np.column_stack((s1, s2))) - - print(C(s1)) - print(C(s2)) - - plt.show() diff --git a/docs/authors.rst b/docs/authors.rst deleted file mode 100644 index e122f91..0000000 --- a/docs/authors.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../AUTHORS.rst diff --git a/docs/bibliography.rst b/docs/bibliography.rst new file mode 100644 index 0000000..89d5b67 --- /dev/null +++ b/docs/bibliography.rst @@ -0,0 +1,5 @@ +Further Reading +=============== + +.. bibliography:: references.bib + :style: alpha diff --git a/docs/conf.py b/docs/conf.py index b540cc9..3039b47 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,7 +40,7 @@ sys.path.insert(0, os.path.abspath('..')) # nopep8 -import conics +import conics.__about__ # -- General configuration --------------------------------------------- @@ -51,11 +51,12 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.viewcode', - 'sphinx.ext.mathjax', 'matplotlib.sphinxext.plot_directive', + 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'sphinx_copybutton', 'sphinxcontrib.bibtex', ] @@ -78,8 +79,8 @@ master_doc = 'index' # General information about the project. -project = 'Conics' -copyright = '2022, Sergiu Deitsch' +project = 'conics' +copyright = '2024, Sergiu Deitsch' author = 'Sergiu Deitsch' # The version info for the project you're documenting, acts as replacement @@ -87,9 +88,9 @@ # the built documents. # # The short X.Y version. -version = conics.__version__ +version = '0.1' # The full version, including alpha/beta/rc tags. -release = conics.__version__ +release = conics.__about__.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -115,7 +116,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'furo' # Theme options are theme-specific and customize the look and feel of a # theme further. For a list of options available for each theme, see the @@ -123,71 +124,29 @@ # # html_theme_options = {} + +html_theme_options = { + "source_repository": "https://github.com/sergiud/conics/", + "source_branch": "master", + "source_directory": "docs/", + "footer_icons": [ + { + "name": "GitHub", + "url": "https://github.com/sergiud/conics", + "html": """ + + + + """, + "class": "", + }, + ], +} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] - -# -- Options for HTMLHelp output --------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = 'conicsdoc' - - -# -- Options for LaTeX output ------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'conics.tex', - 'Conics Documentation', - 'Sergiu Deitsch', 'manual'), -] - - -# -- Options for manual page output ------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'conics', - 'Conics Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ---------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'conics', - 'Conics Documentation', - author, - 'conics', - 'One line description of project.', - 'Miscellaneous'), -] - bibtex_bibfiles = ['references.bib'] + +plot_format = dict(html='svg', latex='pdf') diff --git a/docs/contributing.rst b/docs/contributing.rst deleted file mode 100644 index e582053..0000000 --- a/docs/contributing.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../CONTRIBUTING.rst diff --git a/docs/ellipse.rst b/docs/ellipse.rst new file mode 100644 index 0000000..bf047a3 --- /dev/null +++ b/docs/ellipse.rst @@ -0,0 +1,7 @@ +Ellipse +======== + +An ellipse is a specific instance of a conic section. + +.. autoclass:: conics.Ellipse + :members: diff --git a/docs/fitting.rst b/docs/fitting.rst new file mode 100644 index 0000000..4ff362e --- /dev/null +++ b/docs/fitting.rst @@ -0,0 +1,77 @@ +Fitting Conics +============== + +Algebraic Fitting +----------------- + +.. autofunction:: conics.fitting.fit_dlt + +.. autofunction:: conics.fitting.fit_nievergelt + + +Geometric Fitting +----------------- + +Geometric fitting of conics involves minimizing some sort of orthogonal +distances between the observed points and the points on the conic. This is in +stark contrast to algebraic fitting which generally minimizes the quadratic curve +representation of conics, which can be done linearly. Geometric fitting, +however, generally requires solving a system of non-linear equations. + +Solving a system of non-linear equations is typically done iteratively by +minimizing a cost function assumed to be convex. The latter requires an initial +guess of the solution which is reasonably close to the global optimum. In +practice, one can employ algebraic fit to estimate the initial set of the conic +parameters and then refine solution using non-linearly. An example of a such +approach is implemented by :func:`conics.Parabola.refine` and illustrated in +the following example. + +.. plot:: ../examples/parabolas.py + + Geometrically fitted parabola in general position. + + +Parabola to Quadratic Bézier Curve +---------------------------------- + +A parabola can be exactly represented by a second-degree Bézier curve. Employing +accurate and does not suffer from quantization errors that particularly can +occur when computing isocurves. + +Specifying a second-degree Bézier curve requires providing three control points +which determine the curve. While the outer control points can be chosen to be +arbitrarily placed on the curve, the central control point must be computed from +the intersection of the parabola slopes at the outer control points. + + +.. autofunction:: conics.fitting.parabola_to_bezier + +.. plot:: ../examples/bezier.py + + +The Importance of Normalization +------------------------------- + +Standardizing the 2-D coordinates to be mean-free with unit standard deviation +may improve the numerical robustness of the fitting algorithm +:cite:`Chojnacki2003,Harker2004`. + +.. plot:: ../examples/normalization.py + + The effect of normalization on (algebraic) fit of a parabola. + +In this example, the large range of the vertical axis dominates over the much +smaller range of the horizontal axis. Without scaling, the algebraic fit +therefore produces an elongated parabola that covers the predominant vertical +axis. While this is a valid solution, it is perceptually inferior to the one +estimated using normalized coordinates. + + +Constraining Conics +------------------- + +Sometimes, one wishes to refine an already fitted conic with respect to a set of +points to obtain a conic of specific type or with specific properties. For +instance, the conic obtained using direct linear transform (DLT) results in a +circle. However, one wants a parabola instead. Such constraint can be enforced +using :meth:`conics.Parabola.refine`. diff --git a/docs/general_form.rst b/docs/general_form.rst new file mode 100644 index 0000000..9956459 --- /dev/null +++ b/docs/general_form.rst @@ -0,0 +1,34 @@ +============ +General Form +============ + +There are several ways of representing a conic section. A common representation, +however, is to employ a 6-D vector of coefficients +:math:`\vec\theta=(A,B,C,D,E,F)^\top\in\mathbb{R}^6` that define the +inhomogeneous quadratic equation + +.. math:: + + Q(x,y)=Ax^2+Bxy+Cx^2+Dx+Ey+C=0 + +The quadratic form of the equation can alternatively be defined in terms of a +dot product between the coefficients :math:`\vec\theta` and the monomials in +:math:`x,y` given by the vector :math:`\vec\xi = (x^2,xy,y^2,x,y,1)^\top` as +:cite:`Kanatani2016` + +.. math:: + + \langle \vec\xi,\vec\theta \rangle = 0 + \enspace . + +:math:`\vec\xi` is termed dual-Grassmanian and :math:`\vec\theta` Grassmanian +coordinates of the conics :cite:`Harker2008`. + +The quadratic equation can be homogenized be substituting :math:`x'=\frac{x}{w}` +and :math:`y'=\frac{y}{w}` for :math:`(x,y)^\top` :cite:`Hartley2004`. This +allows to obtain a symmetric :math:`3\times3` matrix that describes the conic. +Projective transformations can then be conveniently expressed by matrix +products. + +.. autoclass:: conics.Conic + :members: diff --git a/docs/geometry.rst b/docs/geometry.rst new file mode 100644 index 0000000..cea5c34 --- /dev/null +++ b/docs/geometry.rst @@ -0,0 +1,7 @@ +Geometry +======== + +.. automodule:: conics.geometry + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/history.rst b/docs/history.rst deleted file mode 100644 index 2506499..0000000 --- a/docs/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../HISTORY.rst diff --git a/docs/index.rst b/docs/index.rst index d838dfd..d21fc0d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,19 +1,26 @@ -Welcome to Conics's documentation! -====================================== +conics +====== + +Conics is a library for dealing with conic sections (or simply `conics`). + +Features +-------- + +* Construction of conics +* Geometric transformations +* Computing intersections of conics +* 5-D pose estimation of the supporting plane of an ellipse .. toctree:: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 4 + :hidden: readme - installation usage - contributing - authors - history + bibliography + license Indices and tables ================== * :ref:`genindex` -* :ref:`modindex` * :ref:`search` diff --git a/docs/installation.rst b/docs/installation.rst deleted file mode 100644 index 3bd58ae..0000000 --- a/docs/installation.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. highlight:: shell - -============ -Installation -============ - - -Stable release --------------- - -To install Conics, run this command in your terminal: - -.. code-block:: console - - $ pip install conics - -This is the preferred method to install Conics, as it will always install the most recent stable release. - -If you don't have `pip`_ installed, this `Python installation guide`_ can guide -you through the process. - -.. _pip: https://pip.pypa.io -.. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/ - - -From sources ------------- - -The sources for Conics can be downloaded from the `Github repo`_. - -You can either clone the public repository: - -.. code-block:: console - - $ git clone git://github.com/sergiud/conics - -Or download the `tarball`_: - -.. code-block:: console - - $ curl -OJL https://github.com/sergiud/conics/tarball/master - -Once you have a copy of the source, you can install it with: - -.. code-block:: console - - $ python setup.py install - - -.. _Github repo: https://github.com/sergiud/conics -.. _tarball: https://github.com/sergiud/conics/tarball/master diff --git a/docs/license.rst b/docs/license.rst new file mode 100644 index 0000000..7f44cdd --- /dev/null +++ b/docs/license.rst @@ -0,0 +1,13 @@ +License +======= + +.. image:: https://i.creativecommons.org/l/by-sa/4.0/88x31.png + :align: right + :alt: Creative Commons License + +This document and all the figures are licensed under a `Creative Commons +Attribution-ShareAlike 4.0 International License +`__. + +conics is distributed under `Apache License 2.0 +`__ terms. diff --git a/docs/parabola.rst b/docs/parabola.rst new file mode 100644 index 0000000..e2fad5e --- /dev/null +++ b/docs/parabola.rst @@ -0,0 +1,7 @@ +Parabola +======== + +A parabola is a specific instance of a conic section. + +.. autoclass:: conics.Parabola + :members: diff --git a/docs/pose_estimation.rst b/docs/pose_estimation.rst new file mode 100644 index 0000000..aab1c62 --- /dev/null +++ b/docs/pose_estimation.rst @@ -0,0 +1,5 @@ +Pose Estimation +=============== + +.. autofunction:: conics.estimate_pose + diff --git a/docs/readme.rst b/docs/readme.rst index 72a3355..c99c2e5 100644 --- a/docs/readme.rst +++ b/docs/readme.rst @@ -1 +1,6 @@ -.. include:: ../README.rst +Getting Started +=============== + +To use Conics in a project:: + + import conics diff --git a/docs/references.bib b/docs/references.bib index 4717e11..97b1419 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -1,188 +1,167 @@ -% Encoding: UTF-8 - -@Article{Ahn2001, - author = {Ahn, Sung Joon and Rauh, Wolfgang and Warnecke, Hans-J{\"{u}}rgen}, - journal = {Pattern Recognition}, - title = {Least-squares Orthogonal Distances Fitting of Circle, Sphere, Ellipse, Hyperbola, and Parabola}, - year = {2001}, - issn = {0031-3203}, - month = dec, - number = {12}, - pages = {2283--2303}, - volume = {34}, - abstract = {The least-squares fitting minimizes the squares sum of error-of-fit in predefined measures. By the geometric fitting, the error distances are defined with the orthogonal, or shortest, distances from the given points to the geometric feature to be fitted. For the geometric fitting of circle/sphere/ellipse/hyperbola/parabola, simple and robust nonparametric algorithms are proposed. These are based on the coordinate description of the corresponding point on the geometric feature for the given point, where the connecting line of the two points is the shortest path from the given point to the geometric feature to be fitted. ?? 2001 Pattern Recognition Society. Published by Elsevier Science Ltd. All rights reserved.}, - doi = {10.1016/S0031-3203(00)00152-7}, - file = {:home/sergiu/Documents/Mendeley Desktop/Ahn, Rauh, Warnecke/Pattern Recognition/Ahn, Rauh, Warnecke - 2001 - Least-squares orthogonal distances fitting of circle, sphere, ellipse, hyperbola, and parabola.pdf:pdf}, - isbn = {3-540-23966-9}, - keywords = {Circle fitting,Conic fitting,Gauss-Newton iteration,Nonlinear least squares,Orthogonal contacting condition,Orthogonal distance fitting,Singular value decomposition,Sphere fitting}, - mendeley-groups = {Conic Sections}, +@article{Ahn2001, + abstract = {The least-squares fitting minimizes the squares sum of error-of-fit in predefined measures. By the geometric fitting, the error distances are defined with the orthogonal, or shortest, distances from the given points to the geometric feature to be fitted. For the geometric fitting of circle/sphere/ellipse/hyperbola/parabola, simple and robust nonparametric algorithms are proposed. These are based on the coordinate description of the corresponding point on the geometric feature for the given point, where the connecting line of the two points is the shortest path from the given point to the geometric feature to be fitted. ?? 2001 Pattern Recognition Society. Published by Elsevier Science Ltd. All rights reserved.}, + author = {Ahn, Sung Joon and Rauh, Wolfgang and Warnecke, Hans-J\"{u}rgen}, + doi = {10.1016/S0031-3203(00)00152-7}, + isbn = {3-540-23966-9}, + issn = {0031-3203}, + journal = {Pattern Recognition}, + keywords = {Circle fitting,Conic fitting,Gauss-Newton iteration,Nonlinear least squares,Orthogonal contacting condition,Orthogonal distance fitting,Singular value decomposition,Sphere fitting}, + month = dec, + number = {12}, + pages = {2283--2303}, + title = {Least-squares Orthogonal Distances Fitting of Circle, Sphere, Ellipse, Hyperbola, and Parabola}, + volume = {34}, + year = {2001}, } -@Article{Nievergelt2004, +@article{Nievergelt2004, + abstract = {For each finite set of points in the Euclidean plane, and for each type of conic section - elliptic, hyperbolic, or parabolic - The algorithm presented here determines all the algebraically best fitting conics of the selected type: the best ellipse, the best hyperbola, or the best parabola. The supporting theory expands on Golub, Hoffman, and Stewart's generalization of the Schmidt-Mirsky matrix approximation theorem, on Bookstein's and Pratt's methods to fit conics, and on Gander, Golub, and Strebel's method to fit ellipses. Because neither the set of ellipses nor the set of hyperbolae is closed, the algorithm and its supporting theory must accommodate their boundary, which consists of the parabolic conics. The corresponding optimization problem consists in minimizing a quadratic form with two quadratic constraints, which an orthogonal change of variables transforms into a least-squares problem with one quadratic constraint. Hence analogies with geodetic coordinates identify geometric causes of numerical instability. For each type of conic, the resulting best fitting conic remains invariant under Euclidean transformations. Applications include the theory and use of sundials in archaeology and astronomy. {{${${$\copyright$}$}$}} 2003 Elsevier Inc. All rights reserved.}, author = {Nievergelt, Yves}, - journal = {Linear Algebra and Its Applications}, - title = {Fitting Conics of Specific Types to Data}, - year = {2004}, + doi = {10.1016/j.laa.2003.08.022}, issn = {0024-3795}, + journal = {Linear Algebra and Its Applications}, + keywords = {Algebraic,Conics,Curve fitting,Total least-squares}, number = {1-3}, pages = {1--30}, + title = {Fitting Conics of Specific Types to Data}, volume = {378}, - abstract = {For each finite set of points in the Euclidean plane, and for each type of conic section - elliptic, hyperbolic, or parabolic - The algorithm presented here determines all the algebraically best fitting conics of the selected type: the best ellipse, the best hyperbola, or the best parabola. The supporting theory expands on Golub, Hoffman, and Stewart's generalization of the Schmidt-Mirsky matrix approximation theorem, on Bookstein's and Pratt's methods to fit conics, and on Gander, Golub, and Strebel's method to fit ellipses. Because neither the set of ellipses nor the set of hyperbolae is closed, the algorithm and its supporting theory must accommodate their boundary, which consists of the parabolic conics. The corresponding optimization problem consists in minimizing a quadratic form with two quadratic constraints, which an orthogonal change of variables transforms into a least-squares problem with one quadratic constraint. Hence analogies with geodetic coordinates identify geometric causes of numerical instability. For each type of conic, the resulting best fitting conic remains invariant under Euclidean transformations. Applications include the theory and use of sundials in archaeology and astronomy. {\textcopyright} 2003 Elsevier Inc. All rights reserved.}, - doi = {10.1016/j.laa.2003.08.022}, - file = {:home/sergiu/Documents/Mendeley Desktop/Nievergelt/Linear Algebra and Its Applications/Nievergelt - 2004 - Fitting conics of specific types to data.pdf:pdf}, - keywords = {Algebraic,Conics,Curve fitting,Total least-squares}, + year = {2004}, } -@InProceedings{Harker2004, - author = {Harker, Matthew and O'Leary, Paul and Zsombor-Murray, Paul}, - booktitle = {Procedings of the British Machine Vision Conference}, - title = {Direct and Specific Fitting of Conics to Scattered Data}, - year = {2004}, - pages = {91--910}, - publisher = {British Machine Vision Association}, - abstract = {A new method to fit specific types of conics to scattered data points is in- troduced. Direct, specific fitting of ellipses and hyperbol{\ae} is achieved by im- posing a quadratic constraint on the conic coefficients, whereby an improved partitioning of the design matrix is devised so as to improve computational efficiency and numerical stability by eliminating redundant aspects of the fit- ting procedure. Fitting of parabolas is achieved by determining an orthogonal basis vector set in the Grassmannian space of quadratic conic forms. The lin- ear combination of the basis vectors which fulfills the parabolic condition and has a minimum residual is determined using Lagrange multipliers.}, - doi = {10.5244/C.18.9}, - file = {:home/sergiu/Documents/Mendeley Desktop/Harker, O'Leary, Zsombor-Murray/Procedings of the British Machine Vision Conference 2004/Harker, O'Leary, Zsombor-Murray - 2004 - Direct and Specific Fitting of Conics to Scattered Data.pdf:pdf}, - isbn = {1-901725-25-1}, - mendeley-groups = {Conic Sections}, +@inproceedings{Harker2004, + abstract = {A new method to fit specific types of conics to scattered data points is in- troduced. Direct, specific fitting of ellipses and hyperbol{\ae{}} is achieved by im- posing a quadratic constraint on the conic coefficients, whereby an improved partitioning of the design matrix is devised so as to improve computational efficiency and numerical stability by eliminating redundant aspects of the fit- ting procedure. Fitting of parabolas is achieved by determining an orthogonal basis vector set in the Grassmannian space of quadratic conic forms. The lin- ear combination of the basis vectors which fulfills the parabolic condition and has a minimum residual is determined using Lagrange multipliers.}, + author = {Harker, Matthew and O'Leary, Paul and Zsombor-Murray, Paul}, + publisher = {British Machine Vision Association}, + booktitle = {Procedings of the British Machine Vision Conference}, + doi = {10.5244/C.18.9}, + isbn = {1-901725-25-1}, + pages = {91--910}, + title = {Direct and Specific Fitting of Conics to Scattered Data}, + year = {2004}, } -@InCollection{Chen2004, - author = {Chen, Qian and Wu, Haiyuan and Wada, Toshikazu}, - booktitle = {Computer Vision - ECCV 2004}, - publisher = {Springer Berlin Heidelberg}, - title = {Camera Calibration with Two Arbitrary Coplanar Circles}, - year = {2004}, - editor = {Pajdla, Tom{\'{a}}{\v{s}} and Matas, Ji{{\v{r}}}{\'{i}}}, - isbn = {978-3-540-21982-8}, - pages = {521--532}, - series = {Lecture Notes in Computer Science}, - volume = {3023}, - abstract = {n this paper, we describe a novel camera calibration method to estimate the extrinsic parameters and the focal length of a camera by using only one single image of two coplanar circles with arbitrary radius. We consider that a method of simple operation to estimate the extrinsic parameters and the focal length of a camera is very important because in many vision based applications, the position, the pose and the zooming factor of a camera is adjusted frequently. An easy to use and convenient camera calibration method should have two characteristics: 1) the calibration object can be produced or prepared easily, and 2) the operation of a calibration job is simple and easy. Our new method satisfies this requirement, while most existing camera calibration methods do not because they need a specially designed calibration object, and require multi-view images. Because drawing beautiful circles with arbitrary radius is so easy that one can even draw it on the ground with only a rope and a stick, the calibration object used by our method can be prepared very easily. On the other hand, our method need only one image, and it allows that the centers of the circle and/or part of the circles to be occluded. Another useful feature of our method is that it can estimate the focal length as well as the extrinsic parameters of a camera simultaneously. This is because zoom lenses are used so widely, and the zooming factor is adjusted as frequently as the camera setting, the estimation of the focal length is almost a must whenever the camera setting is changed. The extensive experiments over simulated images and real images demonstrate the robustness and the effectiveness of our method.}, - doi = {10.1007/978-3-540-24672-5_41}, - file = {:home/sergiu/Documents/Mendeley Desktop/Chen, Wu, Wada/Computer Vision - ECCV 2004/Chen, Wu, Wada - 2004 - Camera Calibration with Two Arbitrary Coplanar Circles(2).pdf:pdf;:home/sergiu/Documents/Mendeley Desktop/Chen, Wu, Wada/Computer Vision - ECCV 2004/Chen, Wu, Wada - 2004 - Camera Calibration with Two Arbitrary Coplanar Circles.pdf:pdf}, - keywords = {conic,pose estimation}, - mendeley-groups = {Conic Sections}, - mendeley-tags = {conic,pose estimation}, +@incollection{Chen2004, + abstract = {n this paper, we describe a novel camera calibration method to estimate the extrinsic parameters and the focal length of a camera by using only one single image of two coplanar circles with arbitrary radius. We consider that a method of simple operation to estimate the extrinsic parameters and the focal length of a camera is very important because in many vision based applications, the position, the pose and the zooming factor of a camera is adjusted frequently. An easy to use and convenient camera calibration method should have two characteristics: 1) the calibration object can be produced or prepared easily, and 2) the operation of a calibration job is simple and easy. Our new method satisfies this requirement, while most existing camera calibration methods do not because they need a specially designed calibration object, and require multi-view images. Because drawing beautiful circles with arbitrary radius is so easy that one can even draw it on the ground with only a rope and a stick, the calibration object used by our method can be prepared very easily. On the other hand, our method need only one image, and it allows that the centers of the circle and/or part of the circles to be occluded. Another useful feature of our method is that it can estimate the focal length as well as the extrinsic parameters of a camera simultaneously. This is because zoom lenses are used so widely, and the zooming factor is adjusted as frequently as the camera setting, the estimation of the focal length is almost a must whenever the camera setting is changed. The extensive experiments over simulated images and real images demonstrate the robustness and the effectiveness of our method.}, + author = {Chen, Qian and Wu, Haiyuan and Wada, Toshikazu}, + editor = {Pajdla, Tom\'{a}\v{s} and Matas, Ji{\v{r}}\'{\i}}, + publisher = {Springer Berlin Heidelberg}, + booktitle = {Computer Vision - ECCV 2004}, + doi = {10.1007/978-3-540-24672-5_41}, + isbn = {978-3-540-21982-8}, + keywords = {conic,pose estimation}, + pages = {521--532}, + series = {Lecture Notes in Computer Science}, + title = {Camera Calibration with Two Arbitrary Coplanar Circles}, + volume = {3023}, + year = {2004}, } -@Article{Kanatani1993, - author = {Kanatani, K. and Liu, W.}, - journal = {CVGIP: Image Understanding}, - title = {{3D Interpretation of Conics and Orthogonality}}, - year = {1993}, - issn = {1049-9660}, - number = {3}, - pages = {286--301}, - volume = {58}, - abstract = {Computational techniques involving conics are formulated in the framework of projective geometry, and basic notions of projective geometry such as poles, polars, and conjugate pairs are reformulated as "computational procedures" with special emphasis on computational aspects. It is shown that the 3D geometry of three orthogonal lines can be interpreted by computing conics. We then describe an analytical procedure for computing the 3D geometry of a conic of a known shape from its projection. Real image examples are also given. {\textcopyright} 1993 Academic Press. All rights reserved.}, - doi = {10.1006/ciun.1993.1043}, - file = {:home/sergiu/Documents/Mendeley Desktop/Kanatani, Liu/CVGIP Image Understanding/Kanatani, Liu - 1993 - 3D interpretation of conics and orthogonality(2).pdf:pdf;:home/sergiu/Documents/Mendeley Desktop/Kanatani, Liu/CVGIP Image Understanding/Kanatani, Liu - 1993 - 3D interpretation of conics and orthogonality.pdf:pdf}, - keywords = {conic,ellipse,pose estimation}, - mendeley-tags = {conic,ellipse,pose estimation}, +@article{Kanatani1993, + abstract = {Computational techniques involving conics are formulated in the framework of projective geometry, and basic notions of projective geometry such as poles, polars, and conjugate pairs are reformulated as "computational procedures" with special emphasis on computational aspects. It is shown that the 3D geometry of three orthogonal lines can be interpreted by computing conics. We then describe an analytical procedure for computing the 3D geometry of a conic of a known shape from its projection. Real image examples are also given. {{${${$\copyright$}$}$}} 1993 Academic Press. All rights reserved.}, + author = {Kanatani, K. and Liu, W.}, + doi = {10.1006/ciun.1993.1043}, + issn = {1049-9660}, + journal = {CVGIP: Image Understanding}, + keywords = {conic,ellipse,pose estimation}, + number = {3}, + pages = {286--301}, + title = {{3D Interpretation of Conics and Orthogonality}}, + volume = {58}, + year = {1993}, } -@Article{Ayoub1993, - author = {Ayoub, Ayoub B.}, - journal = {Mathematics Magazine}, - title = {The Central Conic Sections Revisited}, - year = {1993}, - issn = {0025-570X}, - month = dec, - number = {5}, - pages = {322--325}, - volume = {66}, - doi = {10.1080/0025570X.1993.11996157}, - file = {:home/sergiu/Documents/Mendeley Desktop/Ayoub/Mathematics Magazine/Ayoub - 1993 - The Central Conic Sections Revisited.pdf:pdf}, - keywords = {conic center}, - mendeley-tags = {conic center}, +@article{Ayoub1993, + author = {Ayoub, Ayoub B.}, + doi = {10.1080/0025570X.1993.11996157}, + issn = {0025-570X}, + journal = {Mathematics Magazine}, + keywords = {conic center}, + month = dec, + number = {5}, + pages = {322--325}, + title = {The Central Conic Sections Revisited}, + volume = {66}, + year = {1993}, } -@Article{Prasad2013, +@article{Prasad2013, + abstract = {A novel ellipse fitting method which is selective for digital and noisy elliptic curves is proposed in this paper. The method aims at fitting an ellipse only when the data points are highly likely belong to an ellipse. This is achieved using the geometric distances of the ellipse from the data points. The proposed method models the non-linear problem of ellipse fitting as a combination of two operators, with one being linear, numerically stable, and easily invertible, while the other being non-linear but unique and easily invertible operator. As a consequence, the proposed ellipse fitting method has several salient properties like unconstrained, stable, non-iterative, and computationally inexpensive. The efficacy of the method is compared against six contemporary and recent algorithms based on the least squares formulation using five experiments of diverse practical challenges, like digitization, incomplete ellipses, and Gaussian noise (up to 30{\%}). Three of the experiments comprise of a total of 44,400 ellipses (positive test data) while the other two are tested on 320,000 non-elliptic conics (negative test data). The results show that the proposed method is quite selective to elliptic shapes only and provides accurate fitting results, indicating potential application in medical, robotics, object detection, and other image processing industrial applications.}, author = {Prasad, Dilip K and Leung, Maylor K H and Quek, Chai}, - journal = {Pattern Recognition}, - title = {{ElliFit}: An Unconstrained, Non-iterative, Least Squares Based Geometric Ellipse Fitting Method}, - year = {2013}, + url = {http://www.sciencedirect.com/science/article/pii/S0031320312004694}, + doi = {10.1016/j.patcog.2012.11.007}, issn = {0031-3203}, + journal = {Pattern Recognition}, + keywords = {Ellipse fitting}, number = {5}, pages = {1449--1465}, + title = {{ElliFit}: An Unconstrained, Non-iterative, Least Squares Based Geometric Ellipse Fitting Method}, volume = {46}, - abstract = {A novel ellipse fitting method which is selective for digital and noisy elliptic curves is proposed in this paper. The method aims at fitting an ellipse only when the data points are highly likely belong to an ellipse. This is achieved using the geometric distances of the ellipse from the data points. The proposed method models the non-linear problem of ellipse fitting as a combination of two operators, with one being linear, numerically stable, and easily invertible, while the other being non-linear but unique and easily invertible operator. As a consequence, the proposed ellipse fitting method has several salient properties like unconstrained, stable, non-iterative, and computationally inexpensive. The efficacy of the method is compared against six contemporary and recent algorithms based on the least squares formulation using five experiments of diverse practical challenges, like digitization, incomplete ellipses, and Gaussian noise (up to 30{\%}). Three of the experiments comprise of a total of 44,400 ellipses (positive test data) while the other two are tested on 320,000 non-elliptic conics (negative test data). The results show that the proposed method is quite selective to elliptic shapes only and provides accurate fitting results, indicating potential application in medical, robotics, object detection, and other image processing industrial applications.}, - doi = {10.1016/j.patcog.2012.11.007}, - file = {:home/sergiu/Documents/Mendeley Desktop/Prasad, Leung, Quek/Pattern Recognition/Prasad, Leung, Quek - 2013 - ElliFit An unconstrained, non-iterative, least squares based geometric Ellipse Fitting method.pdf:pdf}, - keywords = {Ellipse fitting}, - url = {http://www.sciencedirect.com/science/article/pii/S0031320312004694}, + year = {2013}, } -@Book{RichterGebert2011, - author = {Richter-Gebert, J{\"{u}}rgen}, - publisher = {Springer Berlin Heidelberg}, - title = {Perspectives on Projective Geometry}, - year = {2011}, - address = {Berlin, Heidelberg}, - isbn = {978-3-642-17285-4}, - doi = {10.1007/978-3-642-17286-1}, - file = {:home/sergiu/Documents/Mendeley Desktop/Richter-Gebert/Unknown/Richter-Gebert - 2011 - Perspectives on Projective Geometry.pdf:pdf}, - mendeley-groups = {Conic Sections,Conic Sections/Books}, +@book{RichterGebert2011, + author = {Richter-Gebert, J\"{u}rgen}, + publisher = {Springer Berlin Heidelberg}, + address = {Berlin, Heidelberg}, + doi = {10.1007/978-3-642-17286-1}, + isbn = {978-3-642-17285-4}, + title = {Perspectives on Projective Geometry}, + year = {2011}, } -@Book{Hartley2004, +@book{Hartley2004, author = {Hartley, Richard and Zisserman, Andrew}, publisher = {Cambridge University Press}, - title = {Multiple View Geometry in Computer Vision}, - year = {2004}, address = {New York, NY, USA}, edition = {2}, - isbn = {0521540518}, + isbn = {0-521-54051-8}, pages = {655}, - pdf = {:home/sergiu/Documents/Mendeley Desktop/Hartley, Zisserman/Unknown/Hartley, Zisserman - 2004 - Multiple View Geometry in Computer Vision.pdf:pdf}, + title = {Multiple View Geometry in Computer Vision}, + year = {2004}, } -@Book{Kanatani2016, +@book{Kanatani2016, author = {Kanatani, Kenichi and Sugaya, Yasuyuki and Kanazawa, Yasushi}, - editor = {G{\'{e}}rard Medioni and Sven Dickinson}, + editor = {Medioni, G\'{e}rard and Dickinson, Sven}, publisher = {Morgan \& Claypool}, - title = {Ellipse Fitting for Computer Vision}, - year = {2016}, - isbn = {9781627054980}, + doi = {10.2200/S00713ED1V01Y201603COV008}, + isbn = {978-1-62705-498-0}, month = apr, number = {8}, - series = {Synthesis Lectures on Computer Vision}, - doi = {10.2200/S00713ED1V01Y201603COV008}, pagetotal = {141}, + series = {Synthesis Lectures on Computer Vision}, subtitle = {Implementation and Applications}, + title = {Ellipse Fitting for Computer Vision}, + year = {2016}, } -@Article{Harker2008, - author = {Harker, Matthew and O'Leary, Paul and Zsombor-Murray, Paul}, - journal = {Image and Vision Computing}, - title = {Direct Type-specific Conic Fitting and Eigenvalue Bias Correction}, - year = {2008}, - issn = {0262-8856}, - month = mar, - number = {3}, - pages = {372--381}, - volume = {26}, - abstract = {A new method to fit specific types of conics to scattered data points is introduced. Direct, specific fitting of ellipses and hyperbolae is achieved by imposing a quadratic constraint on the conic coefficients, whereby an improved partitioning of the design matrix is devised so as to improve computational efficiency and numerical stability by eliminating redundant aspects of the fitting procedure. Fitting of parabolas is achieved by determining an orthogonal basis vector set in the Grassmannian space of the quadratic terms' coefficients. The linear combination of the basis vectors that fulfills the parabolic condition and has a minimum residual norm is determined using Lagrange multipliers. This is the first known direct solution for parabola specific fitting. Furthermore, the inherent bias of a linear conic fit is addressed. We propose a linear method of correcting this bias, producing better geometric fits which are still constrained to specific conic type. ?? 2007.}, - doi = {10.1016/j.imavis.2006.12.006}, - file = {:home/sergiu/Documents/Mendeley Desktop/Harker, O'Leary, Zsombor-Murray/Image and Vision Computing/Harker, O'Leary, Zsombor-Murray - 2008 - Direct type-specific conic fitting and eigenvalue bias correction.pdf:pdf}, - keywords = {Conics,Constrained least squares,Curve fitting}, - mendeley-groups = {Conic Sections}, +@article{Harker2008, + abstract = {A new method to fit specific types of conics to scattered data points is introduced. Direct, specific fitting of ellipses and hyperbolae is achieved by imposing a quadratic constraint on the conic coefficients, whereby an improved partitioning of the design matrix is devised so as to improve computational efficiency and numerical stability by eliminating redundant aspects of the fitting procedure. Fitting of parabolas is achieved by determining an orthogonal basis vector set in the Grassmannian space of the quadratic terms' coefficients. The linear combination of the basis vectors that fulfills the parabolic condition and has a minimum residual norm is determined using Lagrange multipliers. This is the first known direct solution for parabola specific fitting. Furthermore, the inherent bias of a linear conic fit is addressed. We propose a linear method of correcting this bias, producing better geometric fits which are still constrained to specific conic type. ?? 2007.}, + author = {Harker, Matthew and O'Leary, Paul and Zsombor-Murray, Paul}, + doi = {10.1016/j.imavis.2006.12.006}, + issn = {0262-8856}, + journal = {Image and Vision Computing}, + keywords = {Conics,Constrained least squares,Curve fitting}, + month = mar, + number = {3}, + pages = {372--381}, + title = {Direct Type-specific Conic Fitting and Eigenvalue Bias Correction}, + volume = {26}, + year = {2008}, } -@Article{Chojnacki2003, - author = {Chojnacki, Wojciech and Brooks, M.J. and van den Hengel, A. and Gawley, Darren}, - journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence}, - title = {Revisiting {Hartley}'s Normalized Eight-point Algorithm}, - year = {2003}, - issn = {0162-8828}, - month = sep, - number = {9}, - pages = {1172--1177}, - volume = {25}, - doi = {10.1109/TPAMI.2003.1227992}, - file = {:home/sergiu/Documents/Mendeley Desktop/Chojnacki et al/IEEE Transactions on Pattern Analysis and Machine Intelligence/Chojnacki et al. - 2003 - Revisiting hartley's normalized eight-point algorithm.pdf:pdf}, - mendeley-groups = {Conic Sections}, +@article{Chojnacki2003, + author = {Chojnacki, Wojciech and Brooks, M.J. and van den Hengel, A. and Gawley, Darren}, + doi = {10.1109/TPAMI.2003.1227992}, + issn = {0162-8828}, + journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence}, + month = sep, + number = {9}, + pages = {1172--1177}, + title = {Revisiting {Hartley}'s Normalized Eight-point Algorithm}, + volume = {25}, + year = {2003}, } -@Comment{jabref-meta: databaseType:bibtex;} +@comment{jabref-meta: databaseType:bibtex; +} diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..8eec6fb --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,4 @@ +furo>=2024.07.18 +sphinx-copybutton>=0.5.2 +sphinx>=4.0.0 +sphinxcontrib-bibtex diff --git a/docs/usage.rst b/docs/usage.rst index a0f8b4e..318d027 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,139 +1,13 @@ -===== -Usage -===== +================= +API Documentation +================= -To use Conics in a project:: - import conics +.. toctree:: - -General Form -============ - -There are several ways of representing a conic section. A common representation, -however, is to employ a 6-D vector of coefficients -:math:`\vec\theta=(A,B,C,D,E,F)^\top\in\mathbb{R}^6` that define the -inhomogeneous quadratic equation - -.. math:: - - Q(x,y)=Ax^2+Bxy+Cx^2+Dx+Ey+C=0 - -The quadratic form of the equation can alternatively be defined in terms of a -dot product between the coefficients :math:`\vec\theta` and the monomials in -:math:`x,y` given by the vector :math:`\vec\xi = (x^2,xy,y^2,x,y,1)^\top` as -:cite:`Kanatani2016` - -.. math:: - - \langle \vec\xi,\vec\theta \rangle = 0 - \enspace . - -:math:`\vec\xi` is termed dual-Grassmanian and :math:`\vec\theta` Grassmanian -coordinates of the conics :cite:`Harker2008`. - -The quadratic equation can be homogenized be substituting :math:`x'=\frac{x}{w}` -and :math:`y'=\frac{y}{w}` for :math:`(x,y)^\top` :cite:`Hartley2004`. This -allows to obtain a symmetric :math:`3\times3` matrix that describes the conic. -Projective transformations can then be conveniently expressed by matrix -products. - -.. autoclass:: conics.Conic - :members: - - -Parabola --------- - -A parabola is a specific instance of a conic section. - -.. autoclass:: conics.Parabola - :members: - - -Fitting -======= - -Algebraic Fitting ------------------ - -.. autofunction:: conics.fitting.fit_dlt - -.. autofunction:: conics.fitting.fit_nievergelt - - -Geometric Fitting ------------------ - -Geometric fitting of conics involves minimizing some sort of orthogonal -distances between the observed points and the points on the conic. This is in -stark contrast to algebraic fitting which generally minimizes the quadratic curve -representation of conics, which can be done linearly. Geometric fitting, -however, generally requires solving a system of non-linear equations. - -Solving a system of non-linear equations is typically done iteratively by -minimizing a cost function assumed to be convex. The latter requires an initial -guess of the solution which is reasonably close to the global optimum. In -practice, one can employ algebraic fit to estimate the initial set of the conic -parameters and then refine solution using non-linearly. An example of a such -approach is implemented by :func:`conics.Parabola.refine` and illustrated in -the following example. - -.. plot:: ../examples/parabolas.py - - Geometrically fitted parabola in general position. - - -Parabola to Quadratic Bézier Curve ----------------------------------- - -A parabola can be exactly represented by a second-degree Bézier curve. Employing -accurate and does not suffer from quantization errors that particularly can -occur when computing isocurves. - -Specifying a second-degree Bézier curve requires providing three control points -which determine the curve. While the outer control points can be chosen to be -arbitrarily placed on the curve, the central control point must be computed from -the intersection of the parabola slopes at the outer control points. - - -.. autofunction:: conics.fitting.parabola_to_bezier - -.. plot:: ../examples/bezier.py - - -The Importance of Normalization -------------------------------- - -Standardizing the 2-D coordinates to be mean-free with unit standard deviation -may improve the numerical robustness of the fitting algorithm -:cite:`Chojnacki2003,Harker2004`. - -.. plot:: ../examples/normalization.py - - The effect of normalization on (algebraic) fit of a parabola. - -In this example, the large range of the vertical axis dominates over the much -smaller range of the horizontal axis. Without scaling, the algebraic fit -therefore produces an elongated parabola that covers the predominant vertical -axis. While this is a valid solution, it is perceptually inferior to the one -estimated using normalized coordinates. - - -Constraining Conics -------------------- - -Sometimes, one wishes to refine an already fitted conic with respect to a set of -points to obtain a conic of specific type or with specific properties. For -instance, the conic obtained using direct linear transform (DLT) results in a -circle. However, one wants a parabola instead. - - - -Pose Estimation -=============== - -.. autofunction:: conics.estimate_pose - -.. bibliography:: references.bib - :style: plain + general_form + parabola + ellipse + fitting + pose_estimation + geometry diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c687b23 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,83 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "conics" +dynamic = ["version"] +description = 'Conic sections library' +readme = "README.md" +requires-python = ">=3.9" +license = "Apache-2.0" +keywords = ['parabola', 'hyperbola', 'ellipse', 'circle'] +authors = [ + { name = "Sergiu Deitsch", email = "sergiu.deitsch@gmail.com" }, +] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = [ + 'numpy>=1.25', + 'scipy>=1.14.0', +] + +[project.urls] +Documentation = "https://conics.readthedocs.io" +Issues = "https://github.com/sergiud/conics/issues" +Source = "https://github.com/sergiud/conics" + +[tool.hatch.version] +path = "conics/__about__.py" + +[tool.hatch.envs.types] +extra-dependencies = [ + "mypy>=1.0.0", +] +[tool.hatch.envs.types.scripts] +check = "mypy --install-types --non-interactive {args:src/conics tests}" + +[tool.coverage.run] +source_pkgs = ["conics"] +branch = true +parallel = true +omit = [ + "conics/__about__.py", +] + +[tool.coverage.paths] +conics = ["conics"] + +[tool.coverage.report] +exclude_lines = [ + "no cov", + "if __name__ == .__main__.:", + "if TYPE_CHECKING:", +] + +[tool.isort] +force_single_line = true +from_first = true +no_sections = true +order_by_type = false + +[tool.pytest.ini_options] +junit_family = 'xunit2' +testpaths = ['tests'] +xfail_strict = true +addopts = [ + '--import-mode=importlib', +] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index d212028..0000000 --- a/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -junit_family = xunit2 diff --git a/requirements.txt b/requirements.txt index 8760e6c..4350c91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,10 @@ autopep8>=2.3.1 -bump2version>=0.5.11 coverage>=4.5.4 flake8>=3.7.8 isort>=5.13.2 matplotlib>=3.9.0 numpy>=1.25 -pytest-runner>=5.1 pytest>=4.6.5 scipy>=1.14.0 -Sphinx>=1.8.5 -sphinxcontrib.bibtex>=2.6.2 -tox>=3.14.0 -twine>=1.14.0 -watchdog>=0.9.0 -wheel>=0.33.6 + +-r docs/requirements.txt diff --git a/scripts/normalize-bib.sh b/scripts/normalize-bib.sh new file mode 100755 index 0000000..97dbe79 --- /dev/null +++ b/scripts/normalize-bib.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -eo pipefail + +for input in "$@"; do + biber --tool \ + --isbn-normalise \ + --output-align \ + --output-encoding=ascii \ + --output-field-replace=location:address,journaltitle:journal \ + --output-fieldcase=lower \ + --output-format=bibtex \ + --output-indent=2 \ + --output-legacy-dates \ + --output-file >(sponge "$input") \ + "$input" +done diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index d9d1be0..0000000 --- a/tests/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ - -# conics - Python library for dealing with conics -# -# Copyright 2024 Sergiu Deitsch -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit test package for conics.""" diff --git a/tests/test_conics.py b/tests/test_conics.py index 6da921c..dcd316a 100644 --- a/tests/test_conics.py +++ b/tests/test_conics.py @@ -1,5 +1,4 @@ -#!/usr/bin/env python - +# # conics - Python library for dealing with conics # # Copyright 2024 Sergiu Deitsch @@ -15,6 +14,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# """Tests for `conics` package.""" diff --git a/tests/test_ellipse.py b/tests/test_ellipse.py index c9dc452..1041e21 100644 --- a/tests/test_ellipse.py +++ b/tests/test_ellipse.py @@ -1,4 +1,4 @@ - +# # conics - Python library for dealing with conics # # Copyright 2024 Sergiu Deitsch @@ -14,6 +14,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# from conics import Ellipse from conics.fitting import fit_dlt diff --git a/tests/test_fitting.py b/tests/test_fitting.py index c6960a8..1ce6ed9 100644 --- a/tests/test_fitting.py +++ b/tests/test_fitting.py @@ -14,6 +14,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# from conics import Ellipse from conics.fitting import fit_harker diff --git a/tests/test_geometry.py b/tests/test_geometry.py index c5c4f0d..872f99d 100644 --- a/tests/test_geometry.py +++ b/tests/test_geometry.py @@ -14,6 +14,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# from conics.geometry import hnormalized from conics.geometry import homogeneous diff --git a/tests/test_parabola.py b/tests/test_parabola.py index a95dcaf..2c16c1a 100644 --- a/tests/test_parabola.py +++ b/tests/test_parabola.py @@ -1,4 +1,4 @@ - +# # conics - Python library for dealing with conics # # Copyright 2024 Sergiu Deitsch @@ -14,6 +14,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# from conics import Conic from conics import Parabola diff --git a/tox.ini b/tox.ini index c3753fc..5b5e735 100644 --- a/tox.ini +++ b/tox.ini @@ -2,11 +2,5 @@ ignore = E501,E741,W504 exclude = .venv,docs/_build/,docs/conf.py -[isort] -force_single_line = true -from_first = true -no_sections = true -order_by_type = false - [pycodestyle] aggressive = 0