这是展示你的努力并解释你遇到了哪些问题的最佳方法,你将得到最好的答案来解决它。虽然你的问题不符合一个好问题的要求,但由于这个话题引起了我的兴趣和好奇心,我认为它是值得的。
为了更好地检测轮廓,首先我对图像进行细化以便更容易定位轮廓。我使用以下图像作为输入,以查看更大尺寸的结果:
using Images, FileIO, ImageBinarization
img = load("img.png")
gimg = Gray.(img)
bin = binarize(gimg, UnimodalRosin()) .> 0.5
thinned = thinning(bin, algo=GuoAlgo())
thinned
变量代表以下图片:
julia> Gray.(thinned)
![在这里输入图片描述](https://istack.dev59.com/SoTlB.webp)
现在,我定义了用于查找轮廓的函数:
"""
check_adjacent(loc::CartesianIndex{2}, all_locs::Vector{CartesianIndex{2}})
Return the number of adjacent locations that are in `all_locs` to `loc`.
This function is used to determine whether a location is a corner (contour) or not.
# Arguments
- `loc::CartesianIndex{2}`: the location to check.
- `all_locs::Vector{CartesianIndex{2}}`: all the locations that aren't black.
# Returns
- `Int`: the number of adjacent locations that are in `all_locs` to `loc`.
"""
function check_adjacent(loc::CartesianIndex{2}, all_locs::Vector{CartesianIndex{2}})
conditions = [
loc - CartesianIndex(0,1) ∈ all_locs,
loc + CartesianIndex(0,1) ∈ all_locs,
loc - CartesianIndex(1,0) ∈ all_locs,
loc + CartesianIndex(1,0) ∈ all_locs,
loc - CartesianIndex(1,1) ∈ all_locs,
loc + CartesianIndex(1,1) ∈ all_locs,
loc - CartesianIndex(1,-1) ∈ all_locs,
loc + CartesianIndex(1,-1) ∈ all_locs
]
return sum(conditions)
end
"""
find_the_contour(img::BitMatrix)
Return the contours of the image `img`.
# Arguments
- `img::BitMatrix`: the image to get the contours of.
# Returns
- `Vector{CartesianIndex{2}}`: the contours of the image `img`.
"""
function find_the_contour(img::BitMatrix)
img_matrix = convert(Array{Float64}, img)
not_black = findall(!=(0.0), img_matrix)
contours = Vector{CartesianIndex{2}}()
for nb∈not_black
t = check_adjacent(nb, not_black)
t==1 && push!(contours, nb)
end
return contours
end
现在我使用
find_the_contour
函数:
julia> contours = find_the_contour(thinned)
4-element Vector{CartesianIndex{2}}:
CartesianIndex(161, 334)
CartesianIndex(256, 452)
CartesianIndex(69, 1213)
CartesianIndex(210, 1243)
我应该如何知道这个函数能正确定位轮廓?我定义了另一个函数来突出显示轮廓:
"""
highlight_contours(img, contours)
Return the image `img` with the contours `contours` highlighted with red color.
# Arguments
- `img::BitMatrix`: the image to highlight the contours on.
- `contours::Vector{CartesianIndex{2}}`: the contours to highlight.
- `resize`::Bool=false: whether to resize the image to 512x512 or not.
- `scale`::Union{Int64, Float64}=1: the scale to resize the image to.
# Returns
- `img_matrix`: the image `img` with the contours `contours` highlighted with red color.
"""
function highlight_contours(img, contours; resize::Bool=false, scale::Union{Int64, Float64}=1)
img_matrix = convert(Array{RGB, 2}, img)
for c∈contours
img_matrix[c] = RGB(1,0,0)
end
if resize
img_matrix = typeof(scale)==Int64 ? imresize(img_matrix, size(img).*scale) : imresize(img_matrix, ratio=scale)
end
return img_matrix
end
然后我将thinned
矩阵和contours
传递给它:
julia> highlited = highlight_contours(thinned, contours)
如果你稍微放大一点,你会发现红色轮廓:
![enter image description here](https://istack.dev59.com/tlABo.webp)
现在我确认了轮廓的位置成功后,就开始计算轮廓之间的距离。我使用了每个轮廓的CartesianIndex之间的欧几里得距离!你可以根据自己的喜好进行调整:
"""
distance_between_contours(V::Vector{T}, v::T) where T<:Tuple{Int64, Int64}
Return the euclidean distance between the contour `v` and the contours in `V`.
# Arguments
- `V::Vector{T}`: the contours to check the distance to.
- `v::T`: the contour to check the distance from.
# Returns
- `Float64`: the euclidean distance between the contour `v` and the contours in `V`.
"""
function distance_between_contours(V::Vector{T}, v::T) where T<:Tuple{Int64, Int64}
return broadcast((x, y)->sqrt(sum((x.-y).^2)), V, Ref(v))
end
"""
distance_between_contours(all_contours::Vector{CartesianIndex{2}})
Return the euclidean distance between each pair of contours in `all_contours`.
# Arguments
- `all_contours::Vector{CartesianIndex{2}}`: the contours to calculate the distance between.
# Returns
- `Matrix{Float64}`: the euclidean distance between each pair of contours in `all_contours`.
"""
function distance_between_contours(all_contours::Vector{CartesianIndex{2}})
n = length(all_contours)
distances = Matrix{Float64}(undef, n, n)
for j in eachindex(all_contours)
distances[:, j] .= distance_between_contours(
Tuple.(all_contours),
Tuple(all_contours[j])
)
end
return distances
end
现在我将传递给它
contours
并计算每个之间的配对欧几里得距离:
julia> distance_between_contours(contours)
4×4 Matrix{Float64}:
0.0 151.489 883.801 910.32
151.489 0.0 783.639 792.336
883.801 783.639 0.0 144.156
910.32 792.336 144.156 0.0
在这个矩阵中,例如,
151.489
的值显示了第一个轮廓和第二个轮廓之间的距离。请记住,第一个和第二个轮廓分别是以下内容:
CartesianIndex(161, 334)
CartesianIndex(256, 452)
我按照同样的步骤处理了您的图像,以下是距离和轮廓:
julia> distance_between_contours(contours)
6×6 Matrix{Float64}:
0.0 27.7308 88.6397 168.6 166.676 170.188
27.7308 0.0 60.9262 140.872 139.284 142.622
88.6397 60.9262 0.0 80.1311 79.2465 82.0061
168.6 140.872 80.1311 0.0 26.2488 19.2354
166.676 139.284 79.2465 26.2488 0.0 8.06226
170.188 142.622 82.0061 19.2354 8.06226 0.0
highlited = highlight_contours(thinned, contours, resize=true, scale=2)
![这里输入图片描述](https://istack.dev59.com/BgXjU.webp)
简述
代码:
using Images, FileIO, ImageBinarization
function check_adjacent(loc::CartesianIndex{2}, all_locs::Vector{CartesianIndex{2}})
conditions = [
loc - CartesianIndex(0,1) ∈ all_locs,
loc + CartesianIndex(0,1) ∈ all_locs,
loc - CartesianIndex(1,0) ∈ all_locs,
loc + CartesianIndex(1,0) ∈ all_locs,
loc - CartesianIndex(1,1) ∈ all_locs,
loc + CartesianIndex(1,1) ∈ all_locs,
loc - CartesianIndex(1,-1) ∈ all_locs,
loc + CartesianIndex(1,-1) ∈ all_locs
]
return sum(conditions)
end
function find_the_contour(img::BitMatrix)
img_matrix = convert(Array{Float64}, img)
not_black = findall(!=(0.0), img_matrix)
contours = Vector{CartesianIndex{2}}()
for nb∈not_black
t = check_adjacent(nb, not_black)
t==1 && push!(contours, nb)
end
return contours
end
function distance_between_contours(V::Vector{T}, v::T) where T<:Tuple{Int64, Int64}
return broadcast((x, y)->sqrt(sum((x.-y).^2)), V, Ref(v))
end
function distance_between_contours(all_contours::Vector{CartesianIndex{2}})
n = length(all_contours)
distances = Matrix{Float64}(undef, n, n)
for j in eachindex(all_contours)
distances[:, j] .= distance_between_contours(
Tuple.(all_contours),
Tuple(all_contours[j])
)
end
return distances
end
img = load("img.png")
gimg = Gray.(img)
bin = binarize(gimg, UnimodalRosin()) .> 0.5
thinned = thinning(bin, algo=GuoAlgo())
contours = find_the_contour(thinned)
distance_between_contours(contours)