///|
pub struct FlowField {
width : Int
height : Int
vectors : Array[FlowVector]
} derive(Debug, Eq)
///|
pub fn FlowField::new(width~ : Int, height~ : Int) -> FlowField {
{ width: max_i(0, width), height: max_i(0, height), vectors: [] }
}
///|
pub fn FlowField::from_vectors(
size : Size,
vectors : Array[FlowVector],
) -> FlowField {
{ width: size.width, height: size.height, vectors }
}
///|
pub fn FlowField::constant(size : Size, dx : Int, dy : Int) -> FlowField {
FlowField::from_vectors(size, constant_flow(size, 1, dx~, dy~))
}
///|
pub fn FlowField::size(self : FlowField) -> Size {
Size::new(width=self.width, height=self.height)
}
///|
pub fn FlowField::at(self : FlowField, x : Int, y : Int) -> FlowVector {
for vector in self.vectors {
if vector.x == x && vector.y == y {
return vector
}
}
FlowVector::new(x~, y~, dx=0, dy=0)
}
///|
pub fn FlowField::magnitude_image(self : FlowField) -> GrayImage {
let out = GrayImage::new(width=self.width, height=self.height)
for vector in self.vectors {
out.set(vector.x, vector.y, Gray::new(flow_magnitude_l1(vector) * 16))
}
out
}
///|
pub fn FlowField::direction_image(self : FlowField) -> GrayImage {
let out = GrayImage::new(width=self.width, height=self.height)
for vector in self.vectors {
let direction = if vector.dx > 0 {
255
} else if vector.dx < 0 {
64
} else if vector.dy > 0 {
192
} else {
128
}
out.set(vector.x, vector.y, Gray::new(direction))
}
out
}
///|
pub fn FlowField::mean(self : FlowField) -> Point {
flow_mean(self.vectors)
}
///|
pub fn FlowField::to_json(self : FlowField) -> String {
let sb = StringBuilder()
sb.write_string(
"{\"width\":\{self.width},\"height\":\{self.height},\"vectors\":[",
)
for i, vector in self.vectors {
if i > 0 {
sb.write_string(",")
}
sb.write_string(
"{\"x\":\{vector.x},\"y\":\{vector.y},\"dx\":\{vector.dx},\"dy\":\{vector.dy}}",
)
}
sb.write_string("]}")
sb.to_string()
}
///|
pub fn warp_by_flow(
source : GrayImage,
field : FlowField,
fill : Gray,
) -> GrayImage {
let out = GrayImage::new(width=source.width, height=source.height, fill~)
for vector in field.vectors {
let target_x = vector.x + vector.dx
let target_y = vector.y + vector.dy
if out.in_bounds(target_x, target_y) {
out.set(target_x, target_y, source.get(vector.x, vector.y))
}
}
out
}
///|
pub fn inverse_warp_by_flow(
source : GrayImage,
field : FlowField,
fill : Gray,
) -> GrayImage {
let out = GrayImage::new(width=source.width, height=source.height, fill~)
for y in 0.. Int {
let count = min_i(expected.length(), actual.length())
if count == 0 {
0
} else {
let mut total = 0
for i in 0.. Int {
if field.width * field.height == 0 {
0
} else {
field.vectors.length() * 1000 / (field.width * field.height)
}
}
///|
pub fn translate_flow(size : Size, dx : Int, dy : Int, step : Int) -> FlowField {
FlowField::from_vectors(size, constant_flow(size, step, dx~, dy~))
}
///|
pub fn compose_flow(first : FlowField, second : FlowField) -> FlowField {
let out = FlowField::new(width=first.width, height=first.height)
for vector in first.vectors {
let second_vector = second.at(vector.x + vector.dx, vector.y + vector.dy)
out.vectors.push(
FlowVector::new(
x=vector.x,
y=vector.y,
dx=vector.dx + second_vector.dx,
dy=vector.dy + second_vector.dy,
),
)
}
out
}
///|
pub fn scale_flow(
field : FlowField,
numerator : Int,
denominator : Int,
) -> FlowField {
let den = if denominator == 0 { 1 } else { denominator }
let out = FlowField::new(width=field.width, height=field.height)
for vector in field.vectors {
out.vectors.push(
FlowVector::new(
x=vector.x,
y=vector.y,
dx=vector.dx * numerator / den,
dy=vector.dy * numerator / den,
),
)
}
out
}
///|
pub fn scene_with_flow(scene : SceneOutput, field : FlowField) -> SceneOutput {
SceneOutput::new(
plan=scene.plan,
image=scene.image,
mask=scene.mask,
boxes=scene.boxes,
flow=field.vectors,
)
}