From 6d2df0e84f7f5a0b910234590243678d0637a151 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Fri, 11 Apr 2025 15:53:50 -0700 Subject: [PATCH] feat: Iterative rectangle refinement --- Manifest.toml | 2 +- Project.toml | 2 ++ src/image.jl | 4 ++-- src/tdpacking.jl | 62 ++++++++++++++++++++++++++++++++++-------------- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index ae3e78a..7b38006 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.11.4" manifest_format = "2.0" -project_hash = "0a18a0873213e0e8660a5eb202a1fa9f1621a652" +project_hash = "ec502e8d73a739a6239b751344af945fa59e7806" [[deps.AbstractFFTs]] deps = ["LinearAlgebra"] diff --git a/Project.toml b/Project.toml index 9661941..a619579 100644 --- a/Project.toml +++ b/Project.toml @@ -7,10 +7,12 @@ version = "0.1.0" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" VideoIO = "d6d074c3-1acf-5d4c-9a43-ef38773959a2" [compat] FileIO = "1.17.0" Images = "0.26.2" Luxor = "4.2.0" +Statistics = "1.11.1" VideoIO = "1.1.1" diff --git a/src/image.jl b/src/image.jl index a34f334..3eaf2f9 100644 --- a/src/image.jl +++ b/src/image.jl @@ -3,6 +3,6 @@ using Images """ Converts image to grayscale """ -function greyscale(c::Images.RGB)::UInt8 - return c.r +function greyscale(c::Images.RGB)::Real + return Real(c.r) end diff --git a/src/tdpacking.jl b/src/tdpacking.jl index a39c8d4..fa602e7 100644 --- a/src/tdpacking.jl +++ b/src/tdpacking.jl @@ -1,38 +1,64 @@ +using Base +using Statistics, Images + # Time-dependent packing -struct Rect - pos::Tuple{UInt,UInt} - size::Tuple{UInt,UInt} +@kwdef struct Rect + pos::Tuple{Int,Int} + size::Tuple{Int,Int} color::Real end +function area(r::Rect)::Int + return r.size[1] * r.size[2] +end +function aspect_ratio(r::Rect)::Real + return r.size[1] / r.size[2] +end + """ - divide_image(img::BitMatrix, size_min::UInt=16, size_max::UInt=256) + divide_image(img::BitMatrix, size_min::Int=16, size_max::Int=256) Divides an image into rectangles of the same colour. The rectangles are not allowed to have extreme aspect ratios. There is a minimal size of each retangle. """ -function divide_image(img::Matrix{}, size_min::UInt=16, size_max::UInt=256)::Array{Rect} +function divide_image(img::Matrix{}, size_min::Int=16, size_max::Int=256, threshold_aspect::Real=3.0, threshold_std::Real=0.4)::Array{Rect} + remainder = Rect[Rect(pos=(1,1), size=size(img), color=mean(img))] result = Rect[] - # Remaining area - area = sizeof(img) - # Loop until the entire field is filled - while area > 0 - pos = (9, 9) - size = (threshold, threshold) - region = img.size + while length(remainder) > 0 + section = pop!(remainder) + + width = size_min + height = size_min # Try to expand this rectangle to the maximum size - while size[1] < region[1] || size[2] < region[2] + while width < section.size[1] || height < section.size[2] + subimg = img[section.pos[1]:section.pos[1]+width-1, section.pos[2]:section.pos[2]+height-1] + if std(subimg) >= threshold_std + break + end + colour = mean(subimg) + ar = width / height + + if width < section.size[1] && ar < threshold_aspect + width += 1 + elseif height < section.size[1] + height += 1 + else + break + end end + subimg = img[section.pos[1]:section.pos[1]+width-1, section.pos[2]:section.pos[2]+height-1] + rect = Rect( + pos=section.pos, + size=(width, height), + color=mean(subimg), + ) + push!(result, rect) - color = 0.5 - push!(result, Rect(pos, size, color)) - - # Update the boundary markers for the next iteration - area -= size[1] * size[2] + # FIXME: Add next iteration region end return result