csertegt3 / ransac.jl Goto Github PK
View Code? Open in Web Editor NEWEfficient RANSAC in Julia
Home Page: https://csertegt3.github.io/RANSAC.jl/stable/
License: Other
Efficient RANSAC in Julia
Home Page: https://csertegt3.github.io/RANSAC.jl/stable/
License: Other
Would be greate to have loggers that can log messages between two levels (and not only above a threshold).
The used levels should be under Debug, so you can't turn them on with Debug level.
A new type of AbstractLogger
, that has a method definition for shouldlog
?
Forgot to do that, should be easy.
Probably the octree and the point cloud (PointCloud
type) should live together, for example in a RansacCloud
.
Edit: they should be and can be constructed at the same time. It would eliminate some confusing parts, for example why is the levelscore of a point cloud initialized to [0.0]
?
julia> using RANSAC
julia> exportJSON(stdout, [])
ERROR: MethodError: no method matching toDict(::Array{Any,1})
Closest candidates are:
toDict(::FittedShape) at C:\Users\Laci\.julia\dev\RANSAC\src\json.jl:10
toDict(::ShapeCandidate) at C:\Users\Laci\.julia\dev\RANSAC\src\json.jl:18
toDict(::ScoredShape) at C:\Users\Laci\.julia\dev\RANSAC\src\json.jl:20
...
Stacktrace:
[1] exportJSON(::Base.TTY, ::Array{Any,1}) at C:\Users\Laci\.julia\dev\RANSAC\src\json.jl:58
[2] top-level scope at REPL[2]:1
I'm thinking on being able to use the package in a docker container. I'm planning something like:
I have 3 options in mind for the config file format:
Pkg.TOML
- TOML parser in PkgEither way, a RANSACParameters
struct must be constructed. I'm thinking on a constructor that takes a Dict{String,Any}
dictionary and uses the get(collection, key, default)
method to lookup the fieldnames
of the struct. Different keys (like setallepsilons
) can be hardcoded this way as well. I also think, that all of this must not be that performant, because will happen only while setting up the algorithm.
With the above in mind:
Pkg.TOML
is not a public API, and I must find something that is supported through all the 1.x lifecycle (eg. it must work on 1.0.x, 1.x and nightly as well)Edit:
from the docs:
Inside f, kwargs will be a key-value iterator over a named tuple. Named tuples (as well as dictionaries with keys of Symbol) can be passed as keyword arguments using a semicolon in a call, e.g. f(x, z=1; kwargs...).
I somehow get a negative sqrt at:
function hypergeomdev(N, x, n)
sq = sqrt((x*n*(N-x)*(N-n))/(N-1))
(min=(x*n+sq)/N, max=(x*n-sq)/N)
end
My stack trace:
ERROR: LoadError: DomainError with -1.381857106372905e12:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
[1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:33
[2] sqrt at ./math.jl:573 [inlined]
[3] hypergeomdev(::Int64, ::Int64, ::Int64) at /home/ole/.julia/packages/RANSAC/wkHhD/src/confidenceintervals.jl:54
[4] estimatescore at /home/ole/.julia/packages/RANSAC/wkHhD/src/confidenceintervals.jl:69 [inlined]
[5] scorecandidate(::RANSACCloud{Array{SArray{Tuple{3},Float32,1,3},1},Array{SArray{Tuple{3},Float32,1,3},1},Array{Float32,1}}, ::FittedPlane{SArray{Tuple{3},Float32,1,3},SArray{Tuple{3},Float32,1,3}}, ::Int64, ::NamedTuple{(:iteration, :common, :plane, :cone, :cylinder, :sphere),Tuple{NamedTuple{(:drawN, :minsubsetN, :prob_det, :shape_types, :τ, :itermax, :extract_s, :terminate_s),Tuple{Int64,Int64,Float64,Array{UnionAll,1},Int64,Int64,Symbol,Symbol}},NamedTuple{(:collin_threshold, :parallelthrdeg),Tuple{Float64,Float64}},NamedTuple{(:ϵ, :α),Tuple{Float64,Float64}},NamedTuple{(:ϵ, :α, :minconeopang),Tuple{Float64,Float64,Float64}},NamedTuple{(:ϵ, :α),Tuple{Float64,Float64}},NamedTuple{(:ϵ, :α, :sphere_par),Tuple{Float64,Float64,Float64}}}}) at /home/ole/.julia/packages/RANSAC/wkHhD/src/shapes/plane.jl:69
It works for some parts of my points and normals but haven't been able to figure out why it fails for the whole point cloud.
Do you have a test fail that I can check to see whether we have the same data structure? Or do you have any ideas why this might happen?
PRs and corresponding branches also run on AppVeyor and Travis, which is completely unnecessary. In theory the settings are correct, but they don't do what I want. Maybe CI behaviour should be controlled from the CI scripts.
Struct-of-arrays would maybe a better way to store ScoredShapes.
There's a huge garbage collection in the findhighestscore()
function, due to calling getproperty()
many times.
One problem with SoA approach is, that one of the arrays would be FittedShape[]
, which is an abstract container.
Edit: should I use a package, or implement it myself?
One day the sampling and example point clouds from RANSACBenchmark.jl should be merged back. One of the example/benchmark point clouds should be used to validate the functionality of the package by running the algorithm on it as part of CI.
The score estimatation may not be correct, because the whole size of a subset is used, not just the enabled ones. Must check the paper what to use.
Sampling is currently requires time and ugly. I should completely rethink it.
PointCloud
and the parameters.julia> using RANSAC
julia> RANSACParameters()
ERROR: MethodError: no method matching RANSACParameters(::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::Int64, ::Int64, ::Float64, ::Int64, ::Int64, ::Int64, ::Int64, ::Float64, ::Int64, ::Float64, ::Float64, ::Symbol, ::Int64, ::Int64, ::Float64, ::Float64, ::Bool, ::Symbol, ::Float64, ::Float64, ::Float64, ::Bool, ::Array{Symbol,1}, ::Symbol, ::Symbol)
Closest candidates are:
RANSACParameters(::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::R, ::Any, ::Any, ::R, ::Any, ::Any, ::Any, ::R, ::R, ::R, ::R, ::R, ::Any, ::Any, ::Any, ::R, ::R, ::Any, ::Any, ::R, ::R, ::R, ::Any, ::Any, ::Any, ::Any) where R<:Real
Docs of Parameters.jl suggests that it should work.
Performance related issues. If most of it is solved, the package is ready for announcement.
There are places, where @view
could be used. Should check the whole core for such parts.
Currently I use Float64 everywhere. Maybe speed is not comparable with the paper because "everyone" uses Float32 in reverse engineering(?). Types should be propagated and Float64 shouldn't be used in code (1/2 or 1//2 instead of 0.5). A function is needed that converts the parameters to the requested type. Should it be done automatically?
Instead of:
function ransac(...., reset_rand=false)
reset_rand && Random.seed!(1234)
...
end
do this:
function ransac(..., reset_rand::Union{Nothing,Int}=nothing)
reset_rand === nothing || Random.seed!(reset_rand)
...
end
The ConstructiveGeometry.jl package could be used for visualization by implementing "conversion" in RANSACVisualizer.jl. It's a question if I could use it for other purposeses as well.
In most cases radian is used, but would be nice, if there would be a constructor, that converts from degrees to radian, so one must not do this by hand.
Package link.
I should check the performance, but it shouldn't really be affected.
I think I use outdated CI services. Probably everything should be moved to GH actions. That maybe solves #23 without taking care of it really.
From #12:
The isntequal()
function is not working 100% as I want:
julia> t1 = (a1 = [1,2,3], b=4)
(a1 = [1, 2, 3], b = 4)
julia> t2 = (a1 = [2,3,1], b=4)
(a1 = [2, 3, 1], b = 4)
julia> isntequal(t1,t2)
false
The two arrays are different, but they have the same elements, therefore in this case they are equal. One workaround would be to sort the arrays:
function isntequal(t1::T1,t2::T2) where {T1<:AbstractArray, T2<:AbstractArray}
return sort(t1) == sort(t2)
end
but sort()
is not define for FittedShape
types, so it's not a real workaround.
It only affects tests, so I'll just open an issue for the record.
Originally posted by @cserteGT3 in #12 (comment)
This is not an issue, I just wanted to let you know that there is another RANSAC implementation in Julia: https://github.com/peterkovesi/ImageProjectiveGeometry.jl/blob/master/doc/ransac.md. It seems that they have line and plane fitting only.
What needs to be done, to add a new shape primitive? (Just gathering the tasks, syntax and names are subject to change.)
struct NewShape <: FittedShape
: a new typefitshape(::Type{NewShape},...)
: a function that fits the primitivecompatibles(shape::NewShape)
: compute the compatible pointsscorecandidate()
- is it even necessary?refitshape()
RANSACParameters
)A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.