Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of poly2mask from matlab #56

Open
VPetukhov opened this issue Oct 9, 2020 · 8 comments
Open

Implementation of poly2mask from matlab #56

VPetukhov opened this issue Oct 9, 2020 · 8 comments

Comments

@VPetukhov
Copy link

Hi,

I was looking for implementation of a function, which would fill an image region based on the provided polygon. It exists in Matlab (poly2mask) and also was re-implemented in python (see the discussion).

The implementation is almost trivial (see below), and the function seems generally useful. Would you be interested in me making a PR?

function point_in_polygon(poly_xs::Vector{T}, poly_ys::Vector{T}, x::T, y::T) where T<: Real
    n_verts = length(poly_xs)
    j = n_verts
    c = false
    for i in 1:n_verts
        if (((poly_ys[i] <= y) && (y < poly_ys[j])) || ((poly_ys[j] <= y) && (y < poly_ys[i]))) && 
            (x < (poly_xs[j] - poly_xs[i]) * (y - poly_ys[i]) / (poly_ys[j] - poly_ys[i]) + poly_xs[i])
            c = !c
        end
        j = i
    end
    return c
end

function draw_polygon!(mask::Matrix{T2}, poly_xs::Vector{T}, poly_ys::Vector{T}, value::T2) where T<: Integer where T2 <: Real
    min_x, max_x = max(minimum(poly_xs), 1), min(maximum(poly_xs), size(mask, 2))
    min_y, max_y = max(minimum(poly_ys), 1), min(maximum(poly_ys), size(mask, 1))
    for y in min_y:max_y
        for x in min_x:max_x
            if point_in_polygon(poly_xs, poly_ys, x, y)
                mask[y, x] = value
            end
        end
    end
end

function polygons_to_mask(polygons::Array{Matrix{T}, 1} where T <: Real, max_x::Int, max_y::Int)
    poly_mask = zeros(Int, max_y, max_x);
    for (i,p) in enumerate(polygons)
        draw_polygon!(poly_mask, round.(Int, p[:,1]), round.(Int, p[:,2]), i)
    end
    return poly_mask
end
@timholy
Copy link
Member

timholy commented Oct 9, 2020

It might be interesting. However, what was the inspiration for this code? If you looked at the Matlab implementation then you are license-contaminated, and we can't accept it.

@johnnychen94
Copy link
Member

Could be possibly added to ImageDraw.jl with a new field fill in Polygon

function draw!(img::AbstractArray{T, 2}, polygon::Polygon, color::T) where T<:Colorant
draw!(img, Path(polygon.vertices), color)
draw!(img, LineSegment(first(polygon.vertices), last(polygon.vertices)), color)
end

I guess fill here is not ambiguous to Base.fill?

struct Polygon <: Drawable
    vertices::Vector{Point}
    fill::Bool
end

@VPetukhov
Copy link
Author

VPetukhov commented Oct 15, 2020

However, what was the inspiration for this code?

It was python scikit-image. Looks like they use a variation of the MIT license.

Could be possibly added to ImageDraw.jl with a new field fill in Polygon

If you think people would use it for other purposes.. Otherwise, changing an existing class for such tiny functionality seems like over-kill to me. Though I agree that having both draw!(img, polygon) and draw_polygon! is a bad style. Would it maybe be better to add fill_color::T where T<: Colorant as a keyword argument instead?

@johnnychen94
Copy link
Member

Adding an extra fill_color keyword to draw! sounds good to me.

@timholy
Copy link
Member

timholy commented Oct 15, 2020

Yes, scikit-image is not a problem with regards to licenses, and the plan you've come up with seems fine to me.

@timholy
Copy link
Member

timholy commented Oct 15, 2020

But maybe Union{Number,Colorant}, some people might want a Bool instead (if it's a mask).

@VPetukhov
Copy link
Author

Just realized that it does not exactly work, as the current draw! works only with Colorant, while working with a mask assumes it to be Integer or Bool. Maybe I'm missing something, but converting integers to Colorant and then back introduces a lot of hustle.

@johnnychen94
Copy link
Member

johnnychen94 commented Nov 6, 2020

Generally, we require functions accepting AbstractArray{<:Colorant}, with AbstractArray{<:Real} treated as gray image.

The type annotations in your example codes seem to be quite too restrictive.

@johnnychen94 johnnychen94 transferred this issue from JuliaImages/Images.jl Mar 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants