Vision · University · about 30 min
One pixel is one ray. What that buys you, and what it does not.
[1 mark]The BugBot's camera is 320 pixels wide with a 120 degree field of view. What does this print?
import math f = (320 / 2) / math.tan(math.radians(120 / 2)) bearing = math.degrees(math.atan((240 - 160) / f)) print(round(f, 1), round(bearing, 1))
92.4 40.9
f = 160 / tan(60 degrees) = 92.4 px, and column 240 is atan(80 / 92.4) = 40.9 degrees right of the nose.
[1 mark]Which line works out the focal length in pixels correctly?
[1 mark]A blob's centre is at column 200. What is its bearing from straight ahead, in degrees to 1 decimal place, using f = 92.4?
[1 mark]The linear guess bearing = (u - 160) x 0.375 degrees is used instead of the pinhole formula. How many degrees wrong is it at column 200? Give 1 decimal place.
[1 mark]Why can a single pixel not tell you where an object is?
[1 mark]Which of these add the second constraint needed to get depth from a camera?
Tick every answer that is true.
[1 mark]A tag is seen at column 220 and the detector reports it 50 cm away. What does this print?
import math F = 92.4 bearing = math.degrees(math.atan((220 - 160) / F)) print(round(bearing, 1), round(50 * math.sin(math.radians(bearing)), 1), round(50 * math.cos(math.radians(bearing)), 1))
33.0 27.2 41.9
The bearing is atan(60 / 92.4) = 33.0 degrees, so the tag is 50 sin 33.0 = 27.2 cm right and 50 cos 33.0 = 41.9 cm ahead.
Tag 7 is on the mat and the robot is standing still, facing along +y. Print bearing:, the angle from straight ahead to the tag in degrees, and across:, how far to the right of the robot's nose line the tag actually is in centimetres.
from bugbot import *
import math
connect()
F = 92.4
set_cv("apriltag")
wait(0.3)The hint students can ask for: The detector gives you a column in the picture and a range. The column is an angle: the camera is 320 pixels wide across 120 degrees, and the relation between a pixel offset from the centre and an angle is a tangent, not a straight line. The sideways offset needs the range as well, because a bearing on its own is a whole ray of possible places.
from bugbot import *
import math
connect()
F = 92.4 # focal length in pixels: 160 / tan(60 degrees)
set_cv("apriltag")
wait(0.3)
tags = [t for t in apriltags() if t[0] == 7]
tag_id, cx, cy, dist = tags[0]
bearing = math.degrees(math.atan((cx - 160) / F))
across = dist * math.sin(math.radians(bearing))
print("bearing:", round(bearing, 2))
print("across:", round(across, 1))
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.