-
Notifications
You must be signed in to change notification settings - Fork 27
Description
I'm currently working on code to perform "delayed operations" on images. After working at it for awhile I'm realizing that what I'm writing is really an expression tree, and what I'm trying to do is simplify that tree before executing it.
A simplified layout of available operations are:
- L - Load an image from disk
- C - Crop an image to specific bounds
- W - Warp an image via an affine transform
- A - concatenate images along the channel dimension
An example tree might look like:
+- Crop
|
+- Cat
|
+- Warp
| |
| +- Cat
| |
| +- Crop
| | |
| | +- Load
| |
| +- Warp
| |
| +- Load
|
+- Warp
|
+- Load
or as a expression C(A(W(A(C(L), W(L))), W(L)))
However, if I was to simply execute this graph it would be inefficient. The crop at the root is likely going to throw away a lot of the intermediate computation. So in practice it might be better to rewrite this tree as:
+- Cat
|
+- Warp
| |
| +- Crop
| |
| +- Load
|
+- Warp
| |
| +- Crop
| |
| + Load
|
+- Warp
|
+- Crop
|
+- Load
and as an expression A(W(C(L)), W(C(L)), W(C(L))). (note I'm abusing notation, each operation may have different parameters)
Where all of the cat operations have been moved to the root (because cat is associative A(a, A(b, c)) = A(A(a, b), c)), all of the warp neighboring warp operations have been squashed together (they are all affine, so just multiply the matrices), and the crops have all moved towards the leafs (For an expression C(W(L)), we can compute a new crop and warp W' such that C(W(L)) = W'(C'(L)).
I may have not explained this exactly correctly, but the intuition is that all cats can be delayed until the end, all crops should happen immediately after a load, and all neighboring warps can be combined into a single operation.
In this new simplified expression tree all the crops occur immediately after a load operation, so you are only working with pixels that will influence the final result.
I'm currently slogging through the logic to implement this, but I'm at the point where I'm just going to have to hack it because I don't have a strong grasp on how to implement this properly. I did a bit of searching for resources or packages such that I might be able to define how parameters to operations change when you swap their order in the tree, and then hopefully that package might have a simplify operation that could compute the final structure I'm actually interested in in the general case.
I was wondering if this package might be used for something like that.