After playing around with some oF examples, I cames across a nice color tracking tool by Rick Companje here: https://sites.google.com/site/ofauckland/examples/10-testing. I wanted to make a game controller that is cheap, easy and effective. I was thinking of a steering wheel.
I cut out a circle from cardboard and I painted to circles on opposite sides. After some experimentation, I used two shades of blue, because my webcam seems to have "an eye" for blue more than for other colors (red/blue yellow/red green/red etc. did all not work so well).
I used Rick Companje's code and I also included the openCV libraries (included in the Code::blocks pack). Rick's code was only able to recognize 1 colored spot, so I modified the code, because I needed to track 2 spots for my project.
Two trackable spots on a circle make a perfect steering wheel. Why?
Imagine using 1 spot and using it's y-coordinate to steer. If you come closer or go further away from the camera, the difference in the y-coordinate will become bigger and you would have to keep still in the same position in front of the cam for consistent values. Also, it is possible to move the circle around while keeping the colored spot still.
When using 2 spots, you always have a virtual line inbetween them that has an angle compared to a straight line on the x axis. It does not matter how tilted the steering wheel is or how close/far you are from the camera, as long as both spots are visible. Look at the image below, it's an example of how steering leftward is calculated.
I've used the tangens of corner A to calculate the steering angle. The tangens of corner A is the length of side B divided by the length of side C. The circles are numbered 1 and 2.
The calculation is: (y(2) - y(1)) / (x(2) - x(1)).
I used the same principle to steer rightwards and I set some limits for extremely left/right (when x(1) = x(2)) and I used an interval for the neutral position (when y(1) = y(2)), so it wouldn't be too hard to keep moving forward when you move your hands just a little bit by accident.
I implemented this steering technique into a little "racing" game. The red car has to collect the gas tanks to stay alive. At the left side of the screen you can see the "Fuel Points" (yellow font). They decrease over time. When you drive over a fuel tank, you get a point boost (the counter goes upwards faster than it goes downwards). If the Fuel Points reach zero, your car disappears and it's game over. If the Fuel Points hit a certain high value, you have won the game.
The biggest points for improvement for the future should be:
- The color recognition algorithm. If the lighting on the colored spots changes a bit, (e.g. shadows of fingers holding the wheel, day/night, distance from the cam etc.), the tracking red dots become jumpy and mess up the steering.
- Smoothing out the steering. In this version, if you steer to quick from 1 side to the other, the car can stall and then jump to max speed too quickly. This probably has to do with if-statements for the steering that use the relation between the two spots.
Due to my "newbieness" to programming, I haven't been able to solve these two issues completely. Nevertheless, the concept of this steering technique can be very useful. Due to it's simplicity and low costs it can easily be implemented in many interactive environments, e.g. computer games, exhibitions, controlling electronic music.
The code used is in the subpages. You have to copy the ofxOpenCV addons example to your own project folder and paste the code in testApp.cpp and testApp.h.