Chequerboard Corner Detection
25 Sep 2011
Camera calibration is a fundamental problem in computer vision. In the third episode of the Computer Vision for the Robotic Age podcast I am demonstrating a robust algorithm for identifying the corners of a chequerboard pattern. Identifying the corners of a calibration grid is the initial step for camera calibration.
require 'rubygems'
require 'hornetseye_ffmpeg'
require 'hornetseye_xorg'
include Hornetseye
class Node
# Non-maxima suppression for corners
def nms ( threshold )
# compare image with dilated image and threshold
self >= dilate . major ( threshold )
end
# Find a component with 'n' corners
def have ( n , corners )
# compute number of corners for each component
hist = mask ( corners ). histogram max + 1
# compare number of corners with desired number
msk = hist . eq n
if msk . inject :or
# get label of connected component
id = argmax { | i | msk . to_ubyte [ i ] }. first
# get component mask
eq id
else
# return nil
nil
end
end
def corners ( sigma = 5.0 , size = 21 )
size2 = size / 2
# generate chequer pattern
f1 = finalise ( size , size ) do | i , j |
x , y = i - size2 , j - size2
x * y * Math . exp ( - ( x ** 2 + y ** 2 ) / sigma ** 2 )
end
# generate chequer pattern rotated by 45°
f2 = finalise ( size , size ) do | i , j |
x , y = i - size2 , j - size2
0.5 * ( x ** 2 - y ** 2 ) * Math . exp ( - ( x ** 2 + y ** 2 ) / sigma ** 2 )
end
# apply filter pair and compute corner strength
Math . hypot convolve ( f1 ), convolve ( f2 )
end
end
# relative threshold for corner image
CORNERS = 0.6
# absolute threshold for greylevel image
THRESHOLD = 90
# width and height of calibration grid
W , H = 8 , 5
W2 , H2 = 0.5 * ( W - 1 ), 0.5 * ( H - 1 )
N = W * H
# dilation constant
GRID = 7
# open input video
input = AVInput . new 'calibration.avi'
width , height = input . width , input . height
X11Display . show do
# read colour image
img = input . read_ubytergb
# convert to greyscale
grey = img . to_ubyte
# call method for computing corner image
corners = grey . corners
# call method for non-maxima suppression
nms = corners . nms CORNERS * corners . max
# threshold image
binary = grey > THRESHOLD
# find edges using dilation and erosion
edges = binary . dilate ( GRID ). and binary . erode ( GRID ). not
# find connected edges
components = edges . components
# check for edge region with 'N' corners
grid = components . have N , nms
if grid
# visualise calibration grid
grid . and ( nms ). dilate . conditional RGB ( 255 , 255 , 0 ), img
else
# visualise detected corners
nms . dilate . conditional RGB ( 255 , 0 , 0 ), img
end
end
You can download a better quality version of the video here
See also: