///|
/// Valid image support summary for projected measurements.
pub(all) struct ImageSupport {
total : Int
valid_count : Int
invalid_count : Int
valid_ratio : Double
margin_min : Double
} derive(Debug, Eq)
///|
pub fn image_support_mask(
size : ImageSize,
pixels : ArrayView[@core.Point2],
) -> ImageSupport {
let mut valid = 0
let mut margin = 0.0
for pixel in pixels {
let current = image_margin(pixel, size)
if current >= 0.0 {
valid += 1
if valid == 1 {
margin = current
} else {
margin = margin.min(current)
}
}
}
{
total: pixels.length(),
valid_count: valid,
invalid_count: pixels.length() - valid,
valid_ratio: if pixels.length() == 0 {
0.0
} else {
valid.to_double() / pixels.length().to_double()
},
margin_min: if valid == 0 {
0.0
} else {
margin
},
}
}
///|
pub fn image_support_ratio(
size : ImageSize,
pixels : ArrayView[@core.Point2],
) -> Double {
image_support_mask(size, pixels).valid_ratio
}
///|
pub fn border_distance(size : ImageSize, pixel : @core.Point2) -> Double {
image_margin(pixel, size)
}
///|
pub fn image_margin_histogram(
size : ImageSize,
pixels : ArrayView[@core.Point2],
bins : Int,
) -> Array[Int] {
let result : Array[Int] = []
for _ in 0..= 0.0 && result.length() > 0 {
let index = (margin / maximum * result.length().to_double())
.to_int()
.min(result.length() - 1)
result[index] += 1
}
}
result
}
///|
pub(all) struct DepthHistogram {
bins : Array[Int]
total : Int
valid : Int
minimum : Double
maximum : Double
} derive(Debug, Eq)
///|
pub fn depth_histogram(
depths : ArrayView[Double],
bins~ : Int,
minimum~ : Double,
maximum~ : Double,
) -> DepthHistogram {
let counts : Array[Int] = []
for _ in 0..= minimum &&
depth <= maximum &&
counts.length() > 0 {
let width = (maximum - minimum).max(0.000000000001)
let index = ((depth - minimum) / width * counts.length().to_double())
.to_int()
.min(counts.length() - 1)
.max(0)
counts[index] += 1
valid += 1
}
}
{ bins: counts, total: depths.length(), valid, minimum, maximum }
}
///|
pub fn depth_histogram_peak(histogram : DepthHistogram) -> Int {
let mut index = 0
for i in 1.. histogram.bins[index] {
index = i
}
}
index
}
///|
pub fn depth_histogram_entropy(histogram : DepthHistogram) -> Double {
if histogram.valid == 0 {
return 0.0
}
let mut entropy = 0.0
for count in histogram.bins {
if count > 0 {
let probability = count.to_double() / histogram.valid.to_double()
entropy -= probability * @math.ln(probability)
}
}
entropy
}
///|
pub fn depth_valid_mask(
depths : ArrayView[Double],
minimum : Double,
maximum : Double,
) -> Array[Bool] {
let result : Array[Bool] = []
for depth in depths {
result.push(depth == depth && depth >= minimum && depth <= maximum)
}
result
}
///|
pub fn depth_valid_indices(
depths : ArrayView[Double],
minimum : Double,
maximum : Double,
) -> Array[Int] {
let result : Array[Int] = []
for i in 0..= minimum && depths[i] <= maximum {
result.push(i)
}
}
result
}
///|
pub fn depth_percentile2(
depths : ArrayView[Double],
probability : Double,
) -> Double raise @core.GeometryError {
let valid : Array[Double] = []
for depth in depths {
if depth == depth && depth > 0.0 {
valid.push(depth)
}
}
@core.quantile_linear(valid, probability)
}
///|
pub fn depth_trimmed_mean(
depths : ArrayView[Double],
minimum : Double,
maximum : Double,
) -> Double {
let mut sum = 0.0
let mut count = 0
for depth in depths {
if depth == depth && depth >= minimum && depth <= maximum {
sum += depth
count += 1
}
}
if count == 0 {
0.0
} else {
sum / count.to_double()
}
}
///|
pub fn project_visibility_mask(points : ArrayView[@core.Point3]) -> Array[Bool] {
let result : Array[Bool] = []
for point in points {
result.push(point.z > 0.000000000001)
}
result
}
///|
pub fn project_visibility_indices(
points : ArrayView[@core.Point3],
) -> Array[Int] {
let result : Array[Int] = []
for i in 0.. 0.000000000001 {
result.push(i)
}
}
result
}
///|
pub fn visible_point_depths(points : ArrayView[@core.Point3]) -> Array[Double] {
let result : Array[Double] = []
for point in points {
if point.z > 0.000000000001 {
result.push(point.z)
}
}
result
}