A computer vision application for data collection and analysis on cranberries in the lab.
Project Proposal
The Team
Frank Lazar is a close friend of Laik’s and works in the Cranberry Genetics and Genomics Laboratory (CGGL) under Prof. Zalapa on UW Madison campus, and is in need of a computer vision tool to quickly perform analysis on their cranberries. We were presented with two tasks. The first was to analyze images of full cranberries from different yields, recording data on individual size, width, height, and any other relevant data. The second was to analyze images of cut open cranberries, recording comparisons between the cranberries overall area to its hollow locule area.
With this tool, we hope to aid the researchers at the genetic labs by offering an easier and more efficient way to collect necessary data on their cranberries. Instead of having to measure, record, and analyze cranberry properties by hand, or paying a larger company to work on this, our tool only requires a loosely formatted image in order to present relevant statistics on the cranberries pictured. This is very useful to the researchers as it would save a lot of time and effort in their research efforts, helping the researchers in a very tangible way.
There are many methods for object detection utilizing computer vision, although we had not been able to find any specifically for cranberry research. Of the methods we found, two stood out to us. The first approach was utilizing simple boundary detection algorithms like Canny Edge Detection and then implementing our own logic to distinguish and analyze the cranberries from the contours. The second approach was to utilize a neural network to recognize the cranberries. Although the name CranberryNet reflects our initial intentions to pursue the secondary approach, in the end we decided to implement our solution using boundary detection algorithms.
We aimed to reimplement existing solutions of detecting objects and finding their boundaries. The images that our tool receives has the cranberries spaced out in a grid-like formation with objects of known size also in the image. Therefore, the process of analyzing the cranberries involves identifying each cranberry and comparing them with the objects of known size. For the locule problem, we also had to differentiate the inner locule from the cranberry as a whole. We decided to use OpenCV, Python, and some Mathematica prototyping for our implementation, as it seemed simple to learn and effective for our needs.
Full Cranberry Implementation
For the full cranberry case, our first thought was to use simple contour detection, utilizing the built in Python and OpenCV functions. One of the biggest problems we ran into early on was that some cranberries were colored too similarly to the surface the image was taken on, and the contours were not forming properly, if at all. We spent a long time brainstorming and implementing different image processing techniques to try and solve this issue. Some of these techniques included fine tuning blurs, changing the saturation, color thresholding, and and even more involved methods of semantic segmentation like a neural network to name a few.
In the end, we found that a simple canny edge detection after a Kuwahara filter worked very well. The Kuwahara filter blurs while preserving edges, which was perfect as we could blur the color variances within the cranberry so they wouldn't be mistaken as edges, while still preserving the important edges -- the actual edges of the cranberry.
Some of the contours generated using this method would still not create a closed figure however, disturbing our area calculations. In those cases, we simply closed the contours using a convex hull approximation. Using simple logic, we were able to differentiate cranberry contours from the objects of known size based on area, as well as ignoring smaller spurious contours detected as a result of noise. From there, we used the built in contourArea() function to get the area of each contour.
Original Image
Kuwahara Filter
Canny Edge Detection
Contour Generation
Removing Spurious Contours
In order to get the width and height of the cranberries, we noted that most cranberry contours are ovular in shape. If we use OpenCV's FitEllipse function, it will fit the best ellipse it can to the previously found contour. The ellipse data that is returned includes the ellipse's major and minor axis lengths, which we just said was good enough for the width and height. This method could break down if the cranberries are a particularly abnormal shape, but none of the cranberries in the data have that problem.
In the photo above, you can see the 1in diameter circles used as a reference to approximate the area, narrowest width, and longest length of each cranberry (which is written directly on the image in that order).
An alternate method to finding the narrowest width and longest length of each cranberry is to use a Radon transform, in which we just look at the image of the cranberry from all angles in order to find the angles with the widest and narrowest parts of the cranberry. Using that angle, we rotate the cranberry to be aligned, binarize the image, add up the total of each row of the image, and the maximum total is the width/length. We were able to get this to work in Mathematica (seen above) because the Radon transform is already implemented, but we were having trouble with using an implementation of the Radon transform in OpenCV, so we went with the much simpler ellipse solution.
Locule Analysis Implementation
For the locule analysis case, we used Mathematica. There are a few different reasons for using Mathematica's built-in functions rather than something like OpenCV:
Mathematica is very powerful prototyping playground with lots of built in Image Processing tools. It is where we did a lot of brainstorming.
We have a working prototype in Mathematica, and the effort to figure out how to convert it to OpenCV looked to be more work than originally thought and planned for.
It was working better in Mathematica than OpenCV, and Mathematica functions were more different compared to OpenCV than expected. For example, increasing the contrast of the images was not working the same way, and there looked to be extra work to re-implement the Watershed Segmentation method than we had originally thought.
We wanted to prioritize having many different data points recorded with many different computer vision algorithms rather than putting in the work to re-implement computer vision algorithms ourselves.
Mathematica is more user-friendly to those unfamiliar with code, such as the cranberry genetics lab faculty.
We are still using applications of computer vision and image processing techniques and intuition learned from class, even though we are not re-implementing the fine details.
We wanted to prioritize getting working end results by using already implemented image processing techniques than to put more time into re-implementing something that was not built into OpenCV.
Original
Increase Contrast
Kuwahara Filter
Watershed Segmentation*
(*many times)
Binarize to get Locule Mask
Contours of Original
Add Locule Mask to Contours of Original
Invert
Original - This is a cropped version of the original photo
Increase Contrast - Increasing the contrast by an absurd amount helps a lot to better see the locules, because they are very similar to the rest of the color of the cranberry. This makes the edges sharper.
Kuwahara Filter - This smooths the image while preserving edges. This helps to eliminate unwanted regions in the segmentation step
Watershed Segmentation - This step does the majority of the work, and takes the most amount of run time (about a minute or two). The Watershed Segmentation method was done many different times with different settings, because in experimentation, different settings worked better for different parts of the locules and different cranberries. The results of each were binarized and added together to get the final Locule Mask. The image shown is one of many instances, so that is why it does not quite look like it belongs with the rest of the steps.
Separate the image from the previous step (Kuwahara filter) into it's RGB channels
For each RGB channel, Binarize the image at different threshold values (from 0 to 1 with increases of 0.05)
For each binary image from the previous step, we perform Mathematica's implementation of Watershed Segmentation algorithm with MinimumSaliency of 0.3 (this affects the "tolerance" of different smaller segments being considered to be combined into one larger segment)
Binarize to get Locule Mask - All results from each Watershed pass are visualized into a binary image and added together to get a resulting mask. Mathematica's DeleteSmallComponents function (which uses "cluster variance maximization (Otsu's algorithm)") is ran to remove random flecks still remaining in the image.
Contours of Original - Given original image again, returns a binary image of where there are zeros (black background)
Add Locule Mask to Contours of Original
Invert to get mask of the cranberries' "footprint" without the hollow locule
Below is a spattering of different interesting examples of how we recorded and presented results.
Full Cranberry Contour Analysis Output
Below is an example of visualizing the results right on the original image itself.
Below is just labeling the cranberries ID numbers so that the data can instead be placed into a CSV file where it can be more easily analyzed.
Below is a snapshot of an example CSV file produced from the analyzed image above.
The code also outputs the images of the cranberries individually - with their given ID number and also annotated versions.
Locule Analysis Output
Used mathematica to create a visual matrix of information about each cranberry. The format is: "Original", "Avg. Color", "Avg. Color (RGB 0-1)", "Mask", "Total area", "Hollow area", "Non-hollow area".
We also create a CSV file output of the same information in the same order, but without the image files (because those do not show up in a CSV file).
By naming this project "CranberryNet," we originally were implying that we wanted and needed to use some sort of machine learning/deep learning/neural network/AI powered approach. It would have been nice to expose ourselves to that kind of technology, since it seems to be very popular these days, so it would have been a good skill to work on. It seems that many other people in the course also thought so.
There are many reasons why we ultimately strayed away from an AI approach:
We didn't need to - We were able to be very successful without relying on something like neural nets, and that speaks to the power of the simpler and more classic methods that we learned in class.
We couldn't think of anything - There is an old saying, "if the only tool you have is a hammer, everything you see is a nail." If neural networks was a hammer, we could not figure out how to view this problem as a nail. There was no classifying to be done, no changes in video frames, the photos were very structured. The only possible idea was using some semantic or instance segmentation techniques to improve the segmentation of the locules, but even that felt like over-engineering the problem. We wanted the problem to tell us what it needed to be solved, we did not want to force a screw in with a hammer.
Our runtime is very fast - Neural networks are notoriously slow to train. Our code runs either practically instantaneously within a few seconds, or only takes a minute or two. This proved way better in the development cycle for rapid testing and iteration.
We had a very specific problem - Neural nets are good at generalizing in very unstructured photos. Our photos happened to be very structured, and that allows us to make a lot of assumptions and get very specific with our expectations of the image
The data set is very small - Even if we wanted to use our data set of cranberries to train a neural net on, it was difficult to retrieve enough photos from the lab. We only have about 20 photos of the cranberry yields, and only 8 photos of the sliced open locule scans.
The vast majority of the Cranberry Genetics lab do not know how to code - One goal of this project was to make something simple and easy to use for less computer savvy people. Something like Mathematica or 1 simple command line command is much easier to teach them how to use than a whole neural net.
Ultimately, this project was a great lesson in the application of Ockham's Razor. While there are a lot more involved and complicated computer vision algorithms and applications, we feel as if our implementation of our solution is simple, effective, efficient, and robust for the problem we set out to solve. We hope that this tool will be useful to the genetics lab and their research, and in the future we could certainly improve and add to the tool as well for extended functionality.
AI on the Bog: Monitoring and Evaluating Cranberry Crop Risk
Peri Akiva, Benjamin Planche, Aditi Roy, Kristin Dana, Peter Oudemans, Michael Mars;
Comprehensive analysis of the internal structure and firmness in American cranberry (Vaccinium macrocarpon Ait.) fruit
Luis Diaz-Garcia, Lorraine Rodriguez-Bonilla,Matthew Phillips, Arnoldo Lopez-Hernandez, Edward Grygleski, Amaya Atucha, Juan Zalapa
https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0222451