Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.2.3"
[deps]
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[compat]
Expand Down
6 changes: 4 additions & 2 deletions src/ImageDraw.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
module ImageDraw

# package code goes here
using ImageCore, Distances
using ImageCore, Distances, ImageTransformations

include("core.jl")
include("line2d.jl")
include("ellipse2d.jl")
include("circle2d.jl")
include("paths.jl")
include("cross.jl")
include("roi.jl")

#export methods
export
draw,
draw!,
bresenham,
xiaolin_wu
xiaolin_wu,
inset_roi

#export types
export
Expand Down
90 changes: 90 additions & 0 deletions src/roi.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
@enum AlignOptions begin
top_left = 1
top_right = 2
bottom_right = 3
bottom_left = 4
end

function inset_roi(
img::AbstractArray{T, 2},
roi::NTuple{2, NTuple{2, <:Int}},
scale::R,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to ensure scale is positive

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

align::AlignOptions,
color::C
) where {T<:Colorant, R<:Real, C<:Colorant}
Comment on lines +8 to +15

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If roi is the top-left corner of the image, and we set align = top_left, there can be some overlap here.

This won't be a big issue as people are using it in a try-and-see manner.

It would be more convenient to make align optional.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this


((sx, sy), (ex, ey)) = roi

if !checkindex(Bool, axes(img, 1), sx) ||
!checkindex(Bool, axes(img, 1), ex) ||
!checkindex(Bool, axes(img, 2), sy) ||
!checkindex(Bool, axes(img, 2), ey)
throw(ArgumentError("Region of interest lies out of image"))
end
Comment on lines +17 to +41

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CartesianIndex helps handle N-D case in a generic way:

R = CartesianIndices(img)
roi = CartesianIndices(roi)
I_first, I_last = first(roi), last(roi)

(I_first in R && I_last in R) || throw(ArgumentError("Region of interest lies out of image"))

We don't need to check sx >= ex || sy >= ey because cases like -2:-1:-5 is not a AbstractUnitRange


U = promote_type(T, C) # support different types natively
img = convert.(U, img) # copy
color = convert(U, color)

roi_image = @view img[sx:ex, sy:ey]
roi_image = imresize(roi_image; ratio=scale) # copy

if !all(size(roi_image) .<= size(img))
throw(ArgumentError("The scaled region of interest is larger than the image"))
end

border_rect = [
(first(axes(roi_image, 2)), first(axes(roi_image, 1))),
(last(axes(roi_image, 2)), first(axes(roi_image, 1))),
(last(axes(roi_image, 2)), last(axes(roi_image, 1))),
(first(axes(roi_image, 2)), last(axes(roi_image, 1))),
]

draw!(roi_image, Polygon(border_rect), color)

roi_rect = [
(sy, sx),
(ey, sx),
(ey, ex),
(sy, ex)
]
draw!(img, Polygon(roi_rect), color)

if align == top_left
img[first(axes(img, 1)):first(axes(img, 1))+size(roi_image, 1)-1,
first(axes(img, 2)):first(axes(img, 2))+size(roi_image, 2)-1] = roi_image
elseif align == top_right
img[first(axes(img, 1)):first(axes(img, 1))+size(roi_image, 1)-1,
last(axes(img, 2))-size(roi_image, 2)+1:last(axes(img, 2))] = roi_image
elseif align == bottom_right
img[last(axes(img, 1))-size(roi_image, 1)+1:last(axes(img, 1)),
last(axes(img, 2))-size(roi_image, 2)+1:last(axes(img, 2))] = roi_image
else
align == bottom_left
img[last(axes(img, 1))-size(roi_image, 1)+1:last(axes(img, 1)),
first(axes(img, 2)):first(axes(img, 2))+size(roi_image, 2)-1] = roi_image
end

return img
end

function display_roi(
img::AbstractArray{T, 2},
roi::AbstractVector{NTuple{2, NTuple{2, <:Int}}},
size::AbstractVector{<:Real},
align::AbstractVector{AlignOptions},
color::AbstractVector{C}
) where {T<:Colorant, C<:Colorant}
if !(length(roi) == length(size) == length(color) == length(align))
throw(ArgumentError("Arrays roi, size, align and color must be of the same length, instead got $(length(roi)), $(length(size)), $(length(align)) and $(length(color))"))
end

if length(roi) > 4
throw(ArgumentError("Only upto 4 regions of interest can be displayed, instead got $(length(roi))"))
end

if length(unique(align)) < length(align)
@warn "Similarly aligned regions will likely overlap"
end

end