Learning Rust Part 1

Mark Boss
Mark Boss
Jul 25, 2017 · 4 min read
My eye processed with the canny edge implementation. My webcam has some problems with near focus. So the image is quite blurry. Which results in a bad edge detection.

To be honest: this isn’t my first attempt at learning rust. The first failed quite hard and it needed some time till I tried it again. I’m studying computer science and there are exercises and assignments I need to complete. Because of this, learning a new language can’t take a lot of time. Additionally there are projects with other students. They take place in an semester and time is limited here too. Setting up coding guidelines is too time consuming and so left out most of the time. This leads me to one particular project in c++ with lots of threading and pointers. Resulting in: mem leaks. Hunting these issues down was so frustratingly time consuming, that I decided to give rust a second try. And it paid of.

I first started with the rust book. I have read the first edition, but I would most likely recommend the second edition. This edition places an higher emphasis on borrowing and life times. These two concepts are the hardest to get used to and the most amazing of the language at the same time. While reading the book I worked through the rustling exercises. These are quite small exercises which you can run in your browser. So now I got some overview of the language. What next?

I used a site called exercism. It features 56 exercises for rust, which introduce you to more concepts of rust. All exercises feature unit tests and so you know when you’ve correctly implemented them. But the amazing concept of exercism is, that you upload your results and others can comment on your solution. You can look at other results of the exercise too. When you’re not too sure about your solution, you can pickup some techniques from others. I learned quite a lot from it.


Afterwards I had a general understanding of rust and I wanted to try it in a real project. Luckily I had a new project at the university and I was working on it alone. The goal: implementing eye tracking algorithms on the GPU.

The implementation is available on GitHub. Don’t expect the most optimized solution or the most correct one. As I mentioned I worked alone on it and time was scarce.

So I decided to use rust for this project. The first task was to assess if rust has any bindings to CUDA. As it turns out CUDA compiles its kernels at compile time and thus needs an own compiler. It isn’t easy to get running on rust. Well that’s a bummer. OK, what about OpenCL? I understand CUDA. So with some time I could get into OpenCL. I found some packages for OpenCL and I settled on ocl. I’ve written a small test program to assess it and I was quite impressed. It stripped away a lot of boilerplate code and everything just worked.

I started implementing a canny edge detection (In code: OpenCL, rust). I haven’t experienced any problems in that part and it was a pleasant experience. I know that I can increase the performance of the kernels quite a bit, but time is scarce. I need to add more features and algorithms to the program to call it usable or in progress to be usable. At that time I could read in one image, process it and save it. That’s not a real-time eye tracker. So I looked into webcam crates.


I started using camera_capture, which joins a video4linux crate with a directshow crate for windows. OK camera capturing on Windows and Linux. Sorry OSX :(. But I’ve created my own fork of the library with some extra features. Setting the desired FPS wasn’t working on the windows version. I fixed that here and here. Then the output was always in RGB. I added a compile time feature which let me change it to Luma or RGBA. At some point I needed this to save a few extra conversions.

To display everything I used the piston project. More specifically piston_window. The code to display the texture is available here. I wanted to add other streaming methods. So I needed an abstraction for the image acquisition. In rust this is done with traits. I struggled with it quite a bit. My first approach utilized threading and channels to pass it to the main function. But starting threads in a struct implementation is tricky. When the struct ends its lifetime, the thread stops too. Not really desirable when it should’ve been a long running thread. After some trial and error, I completely scrapped the threaded approach and ended up with this trait:

pub trait Stream {
fn setup() -> Self;
fn fetch_images(&self) -> Box<Iterator<Item = image::RgbImage>>;
fn get_resolution(&self) -> (u32, u32);
}

In fetch_images() I return an Iterator. With some help from stackoverflow I ended up with the above solution. At that time I didn’t run rust nightly. Now I would use the impl trait version in the stackoverflow answer. My implementation for a webcam stream is available here. Now I can add more streamers and swap them out with minimal effort.


Summing up: At the end of this part I got a program, which:

1. streams images from the webcam to the GPU

2. performs the canny edge detection

3. display the processed images

In the next part I will talk about contour processing and wrapping my head around composition over inheritance.

Mark Boss

Written by

Mark Boss

I like design, computer graphics development, cooking and coffee. I really like coffee.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade