How to make a 3-dimensional distance scanner using image processing?

As a starter, it took a lot more time than expected to finish this. I expected to finish the project around the first week of February or so, but this stretched on till March. The entire thing is quite simple to make, and won’t take longer than 5 days to make once the chassis is complete.

Let me first jot down the things you’d require to make the hardware.

  • 1 x Servo Motor (Plastic geared ones would do. Buy anything above a 4 kg-cm torque rating)
  • 1 x Stepper Motor (BYJ48, it generally comes with a companion motor driver board, but I made my own.)
  • 1 x Raspberry Pi 2 (or any other microprocessor that has PWM functionality and is fast enough for image processing. No the Arduinos won’t do the job)
  • A webcam (640 x 480)
  • 1 x ULN2003A IC
  • Resistors [1k, 330 (for indicator LED)]
  • IC 7805
  • Capacitors (10u, 1u)
  • 12V adapter female jack
  • Berg Strips
  • Jumper Wires
  • 12V adapter or battery.
  • Cheap Laser Pointer

The entire circuit is just for powering on the stepper and servo motors (Your Raspberry Pi can’t provide power for them, and don’t even try to power them on using the Pi’s power pins).

I’m attaching the CAD diagram for the circuit, for those who wish to follow my pinout.

lasercircuit

The regulated 5V power from the 7805 is fed to the power pins of the stepper motor. The ULN2003 is a 7 transistor array that can be used as a current and voltage amplifier. It is necessary because the Pi delivers a low current 3.3V output from the GPIO pins. The Stepper motor requires a medium current 5V output, which just doesn’t make the cut with the Pi.

The LASER diode was salvaged from an old cheap LASER pointer that you can buy for around Rs. 100 (around $2). I de-soldered the push button, shorted it and replaced the battery connectors with berg strip pinouts. The 5V and GND were already available on my power circuit board, so I simply soldered another set of 5V and GND berg strips to connect via jumpers. The soldering was not that easy for the same, because the holes already are very small, and the size is cramped. The LASER worked well, and it was VERY bright, which was a good thing for me.

The Code

The image procesing code was pretty straight-forward, and using the numpy library. I’d like to thank Shane Ormonde for the same. It scans the numpy matrix for the pixels where the value of red is greater than a threshold, say 236 (optimal value for the same). Then the distance from the center pixel is calculated and converted to the distance via a formula as described in the link given above. I’m adding the code for the IP part again (because why not? Internet Bloatware is king!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
## program written by Shane Ormonde 7th sept 2013
## updated on 25th January 2014
## calculates the distance of a red dot in the field of view of the webcam.
 
import cv2
from numpy import *
import math
 
#variables
loop = 1
dot_dist = 0
 
cv2.namedWindow("preview")
vc = cv2.VideoCapture(1)
 
if vc.isOpened(): # try to get the first frame
    rval, frame = vc.read()
 
else:
    rval = False
    #print "failed to open webcam"
 
if rval == 1 :
 
    while loop == 1:
            cv2.imshow("preview", frame)
            rval, frame = vc.read()
            key = cv2.waitKey(20)
            if key == 27: # exit on ESC
                loop = 0
            num = (frame[...,...,2] > 236)
            xy_val =  num.nonzero()
 
            y_val = median(xy_val[0])
            x_val = median(xy_val[1])
 
            #dist = ((x_val - 320)**2 + (y_val - 240)**2 )**0.5 # distance of dot from center pixel
            dist = abs(x_val - 320) # distance of dot from center x_axis only
 
            print " dist from center pixel is " + str(dist)
 
            # work out distance using D = h/tan(theta)
 
            theta =0.0011450*dist + 0.0154
            tan_theta = math.tan(theta)
 
            if tan_theta > 0: # bit of error checking
                obj_dist =  int(5.33 / tan_theta)
 
            print "\033[12;0H" + "the dot is " + str(obj_dist) + "cm  away"
elif rval == 0:
        print " webcam error "

The stepper code and servo code are simply GPIO sequences and PWM duty cycle variation. The constants 0.0011450, 5.3 and 0.0154 as in the code are to be replaced by your own constants, depending upon the webcam and the separation between webcam and LASER. For the convenience of the reader, I’d add the link to the Github repository soon.

Here is the final image of the complete setup, sans the LASER. I’d put the working video soon.

IMG_20160308_181218

 

2 thoughts on “How to make a 3-dimensional distance scanner using image processing?

Leave a Reply

Your email address will not be published. Required fields are marked *