Skip to content

Commit

Permalink
build based on a368144
Browse files Browse the repository at this point in the history
  • Loading branch information
Documenter.jl committed Dec 22, 2024
1 parent 5c4e68c commit ef9a6cc
Show file tree
Hide file tree
Showing 276 changed files with 42,303 additions and 34,896 deletions.
2 changes: 1 addition & 1 deletion dev/.documenter-siteinfo.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-20T19:09:21","documenter_version":"1.7.0"}}
{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-22T19:59:21","documenter_version":"1.7.0"}}
Binary file modified dev/JuMP.pdf
Binary file not shown.
32 changes: 16 additions & 16 deletions dev/api/JuMP.Containers/index.html

Large diffs are not rendered by default.

558 changes: 279 additions & 279 deletions dev/api/JuMP/index.html

Large diffs are not rendered by default.

Binary file added dev/assets/cartwheel_galaxy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions dev/background/algebraic_modeling_languages/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/background/bibliography/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/changelog/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/developers/checklists/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/developers/contributing/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/developers/custom_solver_binaries/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/developers/extensions/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/developers/roadmap/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/developers/style/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/extensions/DimensionalData/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/extensions/introduction/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/installation/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/callbacks/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/complex/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/constraints/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/containers/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/expressions/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/models/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/nlp/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/nonlinear/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/objective/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/solutions/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/manual/variables/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/background/duality/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/background/infeasibility_certificates/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/moi/background/motivation/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/moi/background/naming_conventions/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/changelog/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/developer/checklists/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/manual/constraints/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/moi/manual/models/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/manual/modification/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/manual/solutions/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/manual/standard_form/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/manual/variables/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/callbacks/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/constraints/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/errors/index.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dev/moi/reference/models/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/modification/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/nonlinear/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/standard_form/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/reference/variables/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/release_notes/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Benchmarks/overview/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Benchmarks/reference/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Bridges/implementation/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Bridges/list_of_bridges/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Bridges/overview/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Bridges/reference/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/FileFormats/overview/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/FileFormats/reference/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Nonlinear/overview/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Nonlinear/reference/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Test/overview/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Test/reference/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/submodules/Utilities/overview/index.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dev/moi/submodules/Utilities/reference/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/tutorials/bridging_constraint/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/tutorials/example/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/tutorials/implementing/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/tutorials/latency/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/tutorials/manipulating_expressions/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/moi/tutorials/mathprogbase/index.html

Large diffs are not rendered by default.

Binary file modified dev/objects.inv
Binary file not shown.
4 changes: 2 additions & 2 deletions dev/packages/Alpine/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/AmplNLWriter/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/BARON/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/BilevelJuMP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/CATrustRegionMethod/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/CDCS/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/CDDLib/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/COPT/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/COSMO/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/CPLEX/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/CSDP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Cbc/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Clarabel/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Clp/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/DAQP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/DSDP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/DiffOpt/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/DisjunctiveProgramming/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Dualization/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/EAGO/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/ECOS/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/GAMS/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/GLPK/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Gurobi/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/HiGHS/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Hypatia/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/InfiniteOpt/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Ipopt/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Juniper/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/KNITRO/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Loraine/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MAiNGO/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MadNLP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Manopt/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MathOptAI/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MathOptSymbolicAD/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MiniZinc/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MosekTools/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/MultiObjectiveAlgorithms/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/NEOSServer/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/NLopt/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/OSQP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Optim/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/PATHSolver/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Pajarito/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/ParametricOptInterface/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Pavito/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Percival/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/PiecewiseLinearOpt/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Plasmo/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/PolyJuMP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/ProxSDP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SCIP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SCS/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/packages/SDDP/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SDPA/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SDPLR/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SDPNAL/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SDPT3/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SeDuMi/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/SumOfSquares/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Tulip/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/packages/Xpress/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/packages/solvers/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/release_notes/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/search_index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/should_i_use/index.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dev/tutorials/algorithms/benders_decomposition/index.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/tutorials/algorithms/parallelism/index.html

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions dev/tutorials/algorithms/pdhg/index.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions dev/tutorials/algorithms/rolling_horizon/index.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions dev/tutorials/algorithms/tsp_lazy_constraints/index.html

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dev/tutorials/applications/optimal_power_flow/index.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions dev/tutorials/applications/power_systems/index.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 85 additions & 0 deletions dev/tutorials/applications/two_stage_stochastic/9b71f37c.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 0 additions & 85 deletions dev/tutorials/applications/two_stage_stochastic/d1f47013.svg

This file was deleted.

100 changes: 0 additions & 100 deletions dev/tutorials/applications/two_stage_stochastic/ea7af52c.svg

This file was deleted.

96 changes: 96 additions & 0 deletions dev/tutorials/applications/two_stage_stochastic/fdb6a7d2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 32 additions & 32 deletions dev/tutorials/applications/two_stage_stochastic/index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dev/tutorials/applications/web_app/index.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dev/tutorials/conic/arbitrary_precision/index.html

Large diffs are not rendered by default.

52 changes: 26 additions & 26 deletions dev/tutorials/conic/dualization/index.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions dev/tutorials/conic/ellipse_approx/index.html

Large diffs are not rendered by default.

378 changes: 378 additions & 0 deletions dev/tutorials/conic/ellipse_fitting.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
# Copyright 2017, Iain Dunning, Joey Huchette, Miles Lubin, and contributors #src
# This Source Code Form is subject to the terms of the Mozilla Public License #src
# v.2.0. If a copy of the MPL was not distributed with this file, You can #src
# obtain one at https://mozilla.org/MPL/2.0/. #src

# # Example: fitting of circles and ellipses

# Ellipse fitting is a common task in data analysis and computer vision and is
# of key importance in many application areas. In this tutorial we show how to
# fit an ellipse to a set of points using a conic optimization approach.

# ## Required packages

# This tutorial uses the following packages:

using JuMP
import Clarabel
import Clustering
import DSP
import Images
import LinearAlgebra
import LinearOperatorCollection as LOC
import Plots
import RegularizedLeastSquares as RLS
import Wavelets

# ## Parametrization of an ellipse

# An ellipse is a set of the form:
# ```math
# \mathcal{E} = \{ \xi : (\xi - c)^\top D (\xi - c) = r^2 \}
# ```
# where ``c \in \mathbb{R}^2`` is the center of the ellipse,
# ``D \in \mathbb{R}^{2 \times 2} \succ 0`` is a symmetric positive definite
# matrix and ``r > 0``.

# We can setup a coordinate system ``(x, y) \in \mathbb{X} \times \mathbb{Y}``
# with ``x, y \geq 0``. We use definition (1) to write an ellipse as the root of
# a quadratic form in homogeneous coordinates:
# ```math
# \begin{bmatrix} \xi \\ 1 \end{bmatrix}^T \begin{bmatrix} Q & d \\ d^T & e \end{bmatrix} \begin{bmatrix} \xi \\ 1 \end{bmatrix} = 0
# ```
# where:
# ```math
# \begin{align}
# Q &= D\\
# d &= -D c\\
# e &= c^T D c - r^2
# \end{align}
# ```
# The residual distance ``r_0`` of a random point ``\xi_0 = (x_0, y_0)`` to the
# ellipse is then given by:
# ```math
# r_0 \triangleq \begin{bmatrix} \xi_0 \\ 1 \end{bmatrix}^T \begin{bmatrix} Q & d \\ d^T & e \end{bmatrix} \begin{bmatrix} \xi_0 \\ 1 \end{bmatrix}
# ```
# The value of ``r_0`` is positive if the point is outside the ellipse, zero if
# it is on the ellipse and negative if it is inside the ellipse. We also see we
# only need six parameters to uniquely define an ellipse.

# ## Helper functions

# We define some helper functions to help us visualize the results.

function plot_dwt(x, sz = (500, 500))
return Plots.heatmap(
x;
color = :grays,
aspect_ratio = 1,
cbar = false,
xlims = (0, size(x, 2)),
ylims = (0, size(x, 1)),
size = sz,
dpi = 300,
)
end

function normalize(x::AbstractArray)
l, u = extrema(x)
return (x .- l) ./ (u - l)
end

# ## Reading the test image

# To test our ellipse-fitting algorithm we need a test image with elliptical
# features. For our test image we will use an image of the cartwheel galaxy,
# [captured by the James Webb Space Telescope](https://webbtelescope.org/contents/media/images/2022/039/01G8JXN0K2VBQP112RNSQWTCTH).
# Galaxies [come in many shapes and sizes](https://science.nasa.gov/universe/galaxies/types/),
# elliptical being one of them.

# This is just a toy problem with little scientific value, but you can imagine
# how the rotation and position of elliptical galaxies can be useful information
# to astronomers.

filename = joinpath(@__DIR__, "..", "..", "assets", "cartwheel_galaxy.png")
img = Images.load(filename);

# We convert the image to gray scale so that we can work with a single channel.

img_gray = Images.Gray.(img)
Images.mosaicview(img, img_gray; nrow = 1)

# Instead of operating on the entire image, we select a region of interest (ROI)
# which is a subset of ``\mathbb{X} \times \mathbb{Y}``.

sz = 256
X_c = 600
Y_c = 140
X = X_c:X_c+sz-1
Y = Y_c:Y_c+sz-1
roi = (X, Y)
img_roi = img[roi...]
img_gray_roi = img_gray[roi...]
Images.mosaicview(img_roi, img_gray_roi; nrow = 1)

# ## Extracting image features

# We cannot directly fit ellipses to the image, so we need to extract features
# that enable us to find the elliptical galaxies.

# The first step is to find a sparse representation of the image. We will use
# the discrete wavelet transform (DWT) in combination with the Iterative
# Shrinking and Thresholding (ISTA) algorithm to denoise the image and find a
# sparse representation. This will remove redundant information and make it much
# easier to detect the edges of galaxies.

# Finding a sparse representation amounts to solving the following optimization
# problem:
# ```math
# \min_{x} \frac{1}{2} \left\| y - \Phi x \right\|_2^2 + \lambda \left\| x \right\|_1
# ```
# where ``y`` is the noisy image, ``\Phi`` is the sparsifying basis, ``x`` is
# the sparse representation of our image, and ``\lambda`` is the regularization
# parameter which we set to `0.1`.

# To work with our image we must first convert it to Float64.

x = convert(Array{Float64}, img_gray_roi)

# We then use ISTA in combination with our wavelet sparsifying basis ``\Psi``
# obtained from the [family of Daubechies wavelets](https://en.wikipedia.org/wiki/Daubechies_wavelet).
# We use the db4 wavelet which has 4 vanishing moments. We set the number of
# iterations to 15.

reg = RLS.L1Regularization(0.1);
Φ = LOC.WaveletOp(
Float64;
shape = size(x),
wt = Wavelets.wavelet(Wavelets.WT.db4),
);
solver = RLS.createLinearSolver(RLS.OptISTA, Φ; reg = reg, iterations = 15);

# The sampled image in wavelet domain is given by:

b = Φ * vec(x);

# We can now solve the optimization problem to find the sparse representation of
# the image.

x_approx = RLS.solve!(solver, b)
x_approx = reshape(x_approx, size(x));
x_final = normalize(x_approx)
Images.mosaicview(x, Images.Gray.(x_final); nrow = 1)

# We then use a binarization algorithm to map each grayscale pixel
# ``(x_i, y_i)`` to a binary value so ``x_i, y_i \to \{0, 1\}``.

x_bin = Images.binarize(x_final, Images.Otsu(); nbins = 128)
x_bin = convert(Array{Bool}, x_bin)
plt = plot_dwt(img_roi)
Plots.heatmap!(x_bin; color = :grays, alpha = 0.45)

# ## Edge detection and clustering

# Now that we have our binary image, we can use edge detection to find the edges
# of the galaxies. We will use the [Sobel operator](https://en.wikipedia.org/wiki/Sobel_operator)
# for this task.

function edge_detector(
f_smooth::Matrix{Float64},
d1::Float64 = 0.1,
d2::Float64 = 0.1,
)
rows, cols = size(f_smooth)
gradient_magnitude = zeros(Float64, rows, cols)
laplacian_magnitude = zeros(Float64, rows, cols)
sobel_x = [-1 0 1; -2 0 2; -1 0 1]
sobel_y = [-1 -2 -1; 0 0 0; 1 2 1]
sobel_xx = [-1 2 -1; 2 -4 2; -1 2 -1]
sobel_yy = [-1 2 -1; 2 -4 2; -1 2 -1]
gradient_x = DSP.conv(f_smooth, sobel_x)
gradient_y = DSP.conv(f_smooth, sobel_y)
gradient_magnitude = sqrt.(gradient_x .^ 2 + gradient_y .^ 2)
gradient_xx = DSP.conv(f_smooth, sobel_xx)
gradient_yy = DSP.conv(f_smooth, sobel_yy)
laplacian_magnitude = sqrt.(gradient_xx .^ 2 + gradient_yy .^ 2)
return (gradient_magnitude .> d1) .& (laplacian_magnitude .< d2)
end

# We apply the Sobel operator to the binary image:

edges = edge_detector(convert(Matrix{Float64}, x_bin), 1e-1, 1e2)
edges = Images.thinning(edges; algo = Images.GuoAlgo())

# And finally we cluster the edges using `dbscan` so we can fit ellipses to
# individual galaxies. We can control the minimum size of galaxies by changing
# the minimum cluster size.

points = findall(edges)
points = getfield.(points, :I)
points = hcat([p[1] for p in points], [p[2] for p in points])'
result = Clustering.dbscan(
convert(Matrix{Float64}, points),
3.0;
min_neighbors = 2,
min_cluster_size = 15,
)

# The result of the clustering is a list of clusters to which we will assign a
# unique color. Each cluster is a list of points that belong to the same galaxy.

clusters = result.clusters
N_clusters = length(clusters)
colors = Plots.distinguishable_colors(N_clusters + 1)[2:end]
plt = plot_dwt(x_final)
for (i, cluster) in enumerate(clusters)
p_cluster = points[:, cluster.core_indices]
Plots.scatter!(
plt,
p_cluster[2, :],
p_cluster[1, :];
color = colors[i],
label = false,
markerstrokewidth = 0,
markersize = 1.5,
)
end
Plots.plot!(
plt;
axis = false,
legend = :topleft,
legendcolumns = 1,
legendfontsize = 12,
)

# ## Fitting ellipses

# Now that we have all the ingredients we can finally start fitting ellipses. We
# will use a conic optimization approach to do so since it is a very natural way
# to represent ellipses.

# First, we define the residual distance definition (6) of a point to an ellipse
# in JuMP:

function create_ellipse_model::Array{Tuple{Int,Int},1}, ϵ = 1e-5)
N = length(Ξ)
model = Model(Clarabel.Optimizer)
set_silent(model)
@variable(model, Q[1:2, 1:2], PSD)
@variable(model, d[1:2])
@variable(model, e)
@expression(
model,
r[i in 1:N],
[Ξ[i][1], Ξ[i][2], 1]' * [Q d; d' e] * [Ξ[i][1], Ξ[i][2], 1]
)
return model
end

# ## Objective 1: Minimize the total squared distance

# For our first objective we will minimize the total squared distance of all
# points to the ellipse. Hence we will use the sum of the squared distances as
# our objective function, also known as the ``L^2`` norm:
# ```math
# \min_{Q, d, e} P_\text{res}(\mathcal{E}) = \min_{Q, d, e} \sum_{i \in N}
# d^2_{\text{res}}(\xi_i, \mathcal{E}) = \min_{Q, d, e} ||d_{\text{res}}||^2_2
# ```

# This problem is equivalent to:
# ```math
# \begin{align}
# \min_{Q, d, e, ζ} &ζ \\
# \text{s.t.} \quad ζ \geq d^2_{\text{res}}(\xi_i, \mathcal{E}) &\quad \forall i \in N
# \end{align}
# ```
# And hence can be modelled as a second-order cone program (SOCP) using
# [`MOI.RotatedSecondOrderCone`](@ref) as follows:

ellipses_C1 = Dict{Symbol,Any}[]
for (i, cluster) in enumerate(clusters)
p_cluster = points[:, cluster.core_indices]
Ξ = [(point[1], point[2]) for point in eachcol(p_cluster)]
model = create_ellipse_model(Ξ)
@variable(model, ζ >= 0)
@constraint(
model,
[1 / 2; ζ; model[:r]] in
MOI.RotatedSecondOrderCone(2 + length(model[:r]))
)
@objective(model, Min, ζ)
optimize!(model)
@assert is_solved_and_feasible(model)
Q, d, e = value.(model[:Q]), value.(model[:d]), value.(model[:e])
push!(ellipses_C1, Dict(:Q => Q, :d => d, :e => e))
end
W, H = size(img_roi)
x_range = 0:1:W
y_range = 0:1:H
X, Y = [x for x in x_range], [y for y in y_range]
function ellipse_eq(x, y, Q, d, e)
Z = zeros(length(x), length(y))
for i in eachindex(x), j in eachindex(y)
ξ = [x[i], y[j]]
Z[i, j] = [ξ; 1.0]' * [Q d; d' e] * [ξ; 1.0]
end
return Z
end
for ellipse in ellipses_C1
Q, d, e = ellipse[:Q], ellipse[:d], ellipse[:e]
Z_sq = ellipse_eq(X, Y, Q, d, e)
Plots.contour!(
plt,
x_range,
y_range,
Z_sq;
levels = [0.0],
linewidth = 2,
color = :red,
cbar = false,
)
end
plt

# ## Objective 2: Minimize the maximum residual distance

# For our second objective we will minimize the maximum residual distance of all
# points to the ellipse:
# ```math
# \min_{Q, d, e} \max_{\xi_i \in \mathcal{F}} d_\text{res}(\xi_i, \mathcal{E}) =
# \min_{Q, d, e} ||d_\text{res}||_\infty
# ```

# This objective can be implemented in JuMP using [`MOI.NormInfinityCone`](@ref)
# as follows:

ellipses_C2 = Dict{Symbol,Any}[]
for (i, cluster) in enumerate(clusters)
p_cluster = points[:, cluster.core_indices]
Ξ = [(point[1], point[2]) for point in eachcol(p_cluster)]
model = create_ellipse_model(Ξ)
N = length(Ξ)
@variable(model, ζ)
@constraint(
model,
[ζ; model[:r]] in MOI.NormInfinityCone(1 + length(model[:r]))
)
@objective(model, Min, ζ)
optimize!(model)
@assert is_solved_and_feasible(model; allow_almost = true)
Q, d, e = value.(model[:Q]), value.(model[:d]), value.(model[:e])
push!(ellipses_C2, Dict(:Q => Q, :d => d, :e => e))
end
for ellipse in ellipses_C2
Q, d, e = ellipse[:Q], ellipse[:d], ellipse[:e]
Z_sq = ellipse_eq(X, Y, Q, d, e)
Plots.contour!(
plt,
x_range,
y_range,
Z_sq;
levels = [0.0],
linewidth = 2,
color = :green,
cbar = false,
)
end
Plots.scatter!([0], [0]; color = :red, label = "Squared (Obj. 1)")
Plots.scatter!([0], [0]; color = :green, label = "Min-Max (Obj. 2)")
Binary file added dev/tutorials/conic/ellipse_fitting/4942d237.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ef9a6cc

Please sign in to comment.