Recently, I've been experimenting with training TensorFlow models on image datasets using Edge Impulse. So while thinking about Halloween, there's a common problem that nearly everyone runs into. Why does it take so long to sort through and organize all of the candy? Because picking up each piece individually and chucking it into its respective pile consumes far too much effort, I wanted to automate the process using the power of machine learning.
The theory goes as follows: the user begins by placing a piece of candy onto a platform, where it is then scanned by a camera. That image gets classified by a model which produces a label of what it thinks the candy is. Based on the result, a pile is chosen, and then platform then moves to that location. Once it has arrived, some kind of pushing mechanism shoves the candy into the pile, and the platform then returns and the cycle resets.
Setting Up Edge ImpulseTo gather training data and produce a TensorFlow model, I went with Edge Impulse. I began by creating a new project called "candySorter" and then heading to the device page. Edge Impulse has a nice feature where you can import many types of data an automatically infer their labels based on just the filename, so I wrote a simple Python script that takes a picture using the Pi's camera and saves it with the desired label when a button is pressed.
Now that there is a large amount of image data, it's time to train a TensorFlow model on it. For input, I went with an image block that scales the original image to one that is 96x96 pixels large. The processing block just sets the color depth to RGB instead of monochrome, and the training block utilizes transfer learning with the MobileNetV2 model. Output is one of the following labels: kitkat
, sour patch
, twizzler
, or reeses
.
After training had finished, I deployed the model as a standalone web assembly library that can be called externally from a Node.js source file.
The system works by using a Raspberry Pi 4 to capture an image with the Raspberry Pi Camera module, but the classifier can't understand that format, it needs an array of pixel values of a certain size instead. So the capture gets saved to a BytesIO
stream and resized to 96x96 pixels large. It is then converted into a string of flattened pixel values, which takes in a tuple of RGB values and transforms it into a single hex value and appends it to a list.
The Node.js source file is called by the subprocess.run()
function, and it passes the color data string as an argument to the program where it is then parsed and given to the model. After the model comes up with what it thinks the object is, a JSON string is outputted over stdout, where it is then piped into a Python variable and parsed as a dictionary object. Finally, the maximum value is found and the associated label is extracted and used to determine into which bin the candy should be placed. This bin number is then sent over USB to the awaiting Arduino Mega 2560.
First and foremost, there is the x-axis roller, which gets moved into position by a single NEMA17 stepper motor that is driven by a DRV8825 stepper motor driver module.
When the Arduino Mega 2560 starts up, it homes the axis by slowly sliding the roller until it hits the limit switch, at which point it's at 0. When there's new serial data, it gets read and parsed into an integer, which says the bin the candy should be placed into. The bins are spaced 10cm apart, so this number is multiplied by 100mm and the stepper moves the corresponding number of steps. Once at the destination, there's a solenoid on the top that activates and quickly pushes the candy below.
With the ML model loaded onto the Pi, I plugged everything in. the actual sorting mechanism whirred to life and home on its own, and the Pi started showing a preview of what it was seeing. From there, I simply placed a piece of candy onto the platform and pressed the button to take a picture of it. That image was resized and sent to the model, which determined its label. Finally, the bin number was sent over and the candy was deposited into the correct spot. In the future, I would like to automate this even more by adding a hopper that can have candy just dumped in the top and then deposit each piece individually over time.
Comments