In the fifth part of our series we will build another grid application to measure leaf angle in corn but use another grid device. Specifically we are going to estimate the leaf insertion angle at different local points along the leaf skeleton line and thereby use Batch Maker to simplify the multiplication of processing streams.
This part can be useful for you in two ways. First, you can extend your previous pipeline from part IV to extract more information on leaf angle. Secondly you learn how to use Batch Maker as a multiplication device for other tasks, for example processing multiple images from a motion imaging stack or multi-spectral imaging.
Here’s a quick overview of how Batch Maker works.
It creates an n-multiple copy of the source input and returns the output as an image stack. Suppose you have created n-number of unique image masks and you need to apply each on a greyscale image. In this case LemnaGrid requires two equally sized image stacks and process each image pairs accordingly (cf LemnaGrid workshop – Application of Batch Mux and Batch Demux).
We use this example image to demonstrate how leaf insertion angles are measured:
Now let’s revisit the leaf insertion angle problem. In part IV, we made the assumption that we can estimate the angle of insertion using leaf segments (skeletons) that are in close proximity of the stem. In other words we define a region of measurement around the stem using some small radius values (ri) . Here we use i = {5, 10, 15, 20, 25} which correspond to the dilation steps of the stem. The result is a set of five different image masks and we need to apply each on the skeleton image. This is now easily done in LemnaGrid by using Batch Maker.
The Skeleton Graph Writer extracts geometric information from the skeleton that are relevant for leaf angle analysis:-
Start.Point.X: x coordinate of leaf tip
Start.Point.Y: y coordinate of leaf tip
End.Point.X: x coordinate of leaf insertion
End.Point.Y: y coordinate of leaf insertion
For the calculation of leaf insertion angle we use this formula:
x = Start.Point.X – End.Point.X
y = Start.Point.Y – End.Point.Y
angle = acos( -y / (sqrt(x*x + y*y) * sqrt(1) )) * 180/pi
Notice that the image coordinate system has <x,y> = <0,0> at left top and the number of rows is represented by the y-coordinate.
Here is the R command I used to create the data plot:
### Simple R script to demonstrate the calculation of leaf angles
### using the start and end coodinates of the leaf skeleton graph segments.
library(dplyr)
library(ggplot2)
read.table(“angle.csv”, header=T, sep=”;”, dec=”.”) %>%
mutate(i=as.integer(gsub(“^.+_r”, “”, Writer.Label))) %>%
select(d=Growth.Direction,
l=AlignmentLabel,
i,
Start.Point.X,
End.Point.X,
Start.Point.Y,
End.Point.Y) %>%
group_by(l,i) %>%
filter(d!=”Stem”) %>%
mutate(x=Start.Point.X-End.Point.X,
y=Start.Point.Y-End.Point.Y,
angle= acos( -y / (sqrt(sum(c(x,y)^2)) * sqrt(1) ))*180/pi ) %>%
ungroup %>%
mutate(l=factor(l, levels=paste0(“Leaf”, 4:0))) %>%
ggplot(aes(x=i,y=angle)) + geom_point() + facet_grid(l~d)
The output of our approach is represented in the table and figure below:
d |
l |
i |
Start.Point.X |
End.Point.X |
Start.Point.Y |
End.Point.Y |
x |
y |
angle |
L |
Leaf0 |
5 |
618 |
626 |
928 |
940 |
-8 |
-12 |
34 |
R |
Leaf1 |
5 |
639 |
630 |
843 |
850 |
9 |
-7 |
52 |
L |
Leaf2 |
5 |
617 |
624 |
736 |
744 |
-7 |
-8 |
41 |
R |
Leaf3 |
5 |
644 |
631 |
603 |
615 |
13 |
-12 |
47 |
L |
Leaf4 |
5 |
628 |
631 |
599 |
615 |
-3 |
-16 |
11 |
L |
Leaf0 |
10 |
614 |
626 |
908 |
940 |
-12 |
-32 |
21 |
R |
Leaf1 |
10 |
643 |
630 |
833 |
850 |
13 |
-17 |
37 |
L |
Leaf2 |
10 |
613 |
624 |
726 |
744 |
-11 |
-18 |
31 |
R |
Leaf3 |
10 |
646 |
631 |
596 |
615 |
15 |
-19 |
38 |
L |
Leaf4 |
10 |
627 |
631 |
594 |
615 |
-4 |
-21 |
11 |
L |
Leaf0 |
15 |
609 |
626 |
891 |
940 |
-17 |
-49 |
19 |
R |
Leaf1 |
15 |
648 |
630 |
823 |
850 |
18 |
-27 |
34 |
L |
Leaf2 |
15 |
607 |
624 |
710 |
744 |
-17 |
-34 |
27 |
R |
Leaf3 |
15 |
647 |
631 |
590 |
615 |
16 |
-25 |
33 |
L |
Leaf4 |
15 |
626 |
631 |
589 |
615 |
-5 |
-26 |
11 |
L |
Leaf0 |
20 |
604 |
626 |
878 |
940 |
-22 |
-62 |
20 |
R |
Leaf1 |
20 |
653 |
630 |
814 |
850 |
23 |
-36 |
33 |
L |
Leaf2 |
20 |
598 |
624 |
689 |
744 |
-26 |
-55 |
25 |
R |
Leaf3 |
20 |
649 |
631 |
584 |
615 |
18 |
-31 |
30 |
L |
Leaf4 |
20 |
626 |
631 |
584 |
615 |
-5 |
-31 |
9 |
L |
Leaf0 |
25 |
598 |
626 |
867 |
940 |
-28 |
-73 |
21 |
R |
Leaf1 |
25 |
658 |
630 |
806 |
850 |
28 |
-44 |
32 |
L |
Leaf2 |
25 |
593 |
624 |
677 |
744 |
-31 |
-67 |
25 |
R |
Leaf3 |
25 |
651 |
631 |
579 |
615 |
20 |
-36 |
29 |
L |
Leaf4 |
25 |
626 |
631 |
579 |
615 |
-5 |
-36 |
8 |
The extracted data from our example image indicate that the calculated leaf angles are comparable within the range of i = 15..25. More digital images are needed to validate that we can stably use an average i-value to measure leaf angles.