# Measurement of Fish Morphological Features through Image Processing and Deep Learning Techniques
## 2 Materials and Methods
### Image Processing Approach  
The first approach in the estimation of the fish's morphological features was based on image processing techniques, and the steps of this technique are shown in Figure 1.  
Octave-forge Image package functions were used to read and write images and then resize and convert them into gray scale, rotate them and perform pattern matching. Most of the Octave Image package functions used were compatible with the corresponding OpenCV library routines; thus, portability to other platforms was guaranteed. As a first step, the initial image was read and resized to the supported resolution (80 rows, 160 columns). The specific resolution adaptation was necessary in order to avoid undesired overlapping with the patterns that would be tested for matching. The image was converted into gray scale for edge extraction. The discontinuities of the image corresponded to the edges of the objects appearing in the image. We desired to select the edges that corresponded to the contour of the fish in order to match an appropriate pattern template. Both coarse algorithms, such as the Sobel algorithm [27] and more sensitive ones (e.g., Canny [28]) were tested. Canny is based on frame-level statistics, and it is more accurate than Sobel but has higher complexity and latency. Experimental results showed that a finer edge detection algorithm such as Canny confused the adopted pattern matching algorithm, which often selected the wrong patterns with the wrong size, rotation and orientation. A custom edge detection algorithm that takes advantage of the \"imgradient\" function of the Octave-forge Image package was developed, offering higher accuracy than Sobel but not the confusing detail of Canny. It is described in Algorithm 1. The \"imgradient\" function returns the gradient magnitude and direction associated with each pixel (in the matrices \(gm\) and \(gd\), respectively). If the gradient magnitude of a pixel exceeds a high threshold (\(magn\_limit1\)), the pixel is assumed to belong to an edge; otherwise, a change in the vertical gradient direction is examined. If the gradient direction between adjacent vertical pixels seems to be reversed, and the gradient magnitude is above a second lower threshold, \(magn\_limit2\) (average magnitude \(\ll magn\_limit2\ll magn\_limit1\)), then the pixel is assumed to belong to the horizontal part of the fish contour. Horizontal gradient direction changes are intentionally ignored in order to avoid the detection of edges belonging to different objects. Since we assumed that the fish was at a horizontal alignment or with a slight inclination and never vertical, the largest part of the fish contour could be detected in this way, avoiding the detection of other irrelevant edges. This procedure corresponds to  
Figure 1: The image processing flow. the gradient edge detect step of Figure 1. Next, the mask displaying the detected edges (_edgesgm_) is scanned again to remove isolated or small groups of pixels (noise). This is the edge reduce step in Figure 1 that corresponds to step 18 of Algorithm 1. ```
1. \(\mathbf{gm}\), \(\mathbf{gd}\leftarrow\)imgradient(img)://get gradient magnitude/direction
2. \(\mathbf{edgesgm}\leftarrow\)zeros with the same size as gm
3. for i = 1 to rows(gm)
4. for j = 1 to columns(gm)
5. if img(i,j) is on the image borders continue;
6. ifgm(i,j) \(\geq\) magn_limit
7. //edge pixel if it corresponds to high gradient magnitude
8. \(\mathbf{edgesgm(i,j)}\leftarrow\)1;
9. else
10. if gd(i,j)*gd(i + 1,j) \(<\) 0
11. if (gd(i,j), gd(i + 1,j)) within angle limits) AND
12. (gm(i,j) > magn_limit2)
13. //gradient changed direction vertically and gradient
14. //magnitude higher than magn_limit2
15. \(\mathbf{edgesgm(i,j)}\leftarrow\)1;
16. else
17. \(\mathbf{edgesgm(i,j)}\leftarrow\)0;
18.