Plot 8X8 grid between corners on part of the image
Question:
I have a photo of a chessboard. I’ve detected the four corners of the board using YOLO, and I have their x, y coordinates.
Now I would like to plot a 8×8 grid between the four corners (along the chessboard lines).
That’s a image for example:
chessboard with corners and outer lines – original image
Here’s my plotting code so far (python):
from matplotlib.pyplot import figure
import matplotlib.pyplot as plt
import matplotlib.image as image
figure(figsize=(10, 10), dpi=80)
im = plt.imread('1.jpgresized.jpg')
implot = plt.imshow(im)
#Left
plt.plot([0.179167 * 480, 0.063542 * 480],
[0.203125 * 640, 0.644531 * 640],
'bo', linestyle="--")
#Bottom
plt.plot([0.063542 * 480, 0.934375 * 480],
[0.644531 * 640, 0.627344 * 640],
'bo', linestyle="--")
#Right
plt.plot([0.934375 * 480, 0.789583 * 480],
[0.627344 * 640, 0.191406 * 640],
'bo', linestyle="--")
#Up
plt.plot([0.789583 * 480, 0.179167 * 480],
[0.191406 * 640, 0.203125 * 640],
'bo', linestyle="--")
plt.show()
Answers:
This does what I describe. For each line, we create a set of 9 points evenly spaced. Then, we draw lines from the left set to the right set, and from the top set to the bottom set.
FOLLOWUP
I’ve added a hacky perspective correction on the Y coordinates. I just do a linear adjustment. It’s not mathematically defensible, but it does the job with this image. Doing it right would involve using the change in size from the top line to the bottom line to determine the perspective factor. I’ve just hard-coded it by experimentation.
from matplotlib.pyplot import figure
import matplotlib.pyplot as plt
import matplotlib.image as image
figure(figsize=(10, 10), dpi=80)
im = plt.imread('chessboard.jpg')
implot = plt.imshow(im)
W,H= 480,640
TL = (0.179167, 0.202125)
BL = (0.063542, 0.644531)
TR = (0.789583, 0.191406)
BR = (0.934375, 0.627344)
def interpolate(xy0, xy1, persp=0):
x0,y0 = xy0
x1,y1 = xy1
dx = (x1-x0) / 8
dy = (y1-y0 - persp*36) / 8
return [(x0+i*dx,y0+i*dy+(i*(i+1)/2)*persp) for i in range(9)]
ptsT = interpolate( TL, TR )
ptsL = interpolate( TL, BL, 0.005 )
ptsR = interpolate( TR, BR, 0.005 )
ptsB = interpolate( BL, BR )
for a,b in zip(ptsL, ptsR):
plt.plot( [a[0]*W, b[0]*W], [a[1]*H, b[1]*H], 'ro', linestyle="--" )
for a,b in zip(ptsT, ptsB):
plt.plot( [a[0]*W, b[0]*W], [a[1]*H, b[1]*H], 'ro', linestyle="--" )
plt.show()
I have a photo of a chessboard. I’ve detected the four corners of the board using YOLO, and I have their x, y coordinates.
Now I would like to plot a 8×8 grid between the four corners (along the chessboard lines).
That’s a image for example:
chessboard with corners and outer lines – original image
Here’s my plotting code so far (python):
from matplotlib.pyplot import figure
import matplotlib.pyplot as plt
import matplotlib.image as image
figure(figsize=(10, 10), dpi=80)
im = plt.imread('1.jpgresized.jpg')
implot = plt.imshow(im)
#Left
plt.plot([0.179167 * 480, 0.063542 * 480],
[0.203125 * 640, 0.644531 * 640],
'bo', linestyle="--")
#Bottom
plt.plot([0.063542 * 480, 0.934375 * 480],
[0.644531 * 640, 0.627344 * 640],
'bo', linestyle="--")
#Right
plt.plot([0.934375 * 480, 0.789583 * 480],
[0.627344 * 640, 0.191406 * 640],
'bo', linestyle="--")
#Up
plt.plot([0.789583 * 480, 0.179167 * 480],
[0.191406 * 640, 0.203125 * 640],
'bo', linestyle="--")
plt.show()
This does what I describe. For each line, we create a set of 9 points evenly spaced. Then, we draw lines from the left set to the right set, and from the top set to the bottom set.
FOLLOWUP
I’ve added a hacky perspective correction on the Y coordinates. I just do a linear adjustment. It’s not mathematically defensible, but it does the job with this image. Doing it right would involve using the change in size from the top line to the bottom line to determine the perspective factor. I’ve just hard-coded it by experimentation.
from matplotlib.pyplot import figure
import matplotlib.pyplot as plt
import matplotlib.image as image
figure(figsize=(10, 10), dpi=80)
im = plt.imread('chessboard.jpg')
implot = plt.imshow(im)
W,H= 480,640
TL = (0.179167, 0.202125)
BL = (0.063542, 0.644531)
TR = (0.789583, 0.191406)
BR = (0.934375, 0.627344)
def interpolate(xy0, xy1, persp=0):
x0,y0 = xy0
x1,y1 = xy1
dx = (x1-x0) / 8
dy = (y1-y0 - persp*36) / 8
return [(x0+i*dx,y0+i*dy+(i*(i+1)/2)*persp) for i in range(9)]
ptsT = interpolate( TL, TR )
ptsL = interpolate( TL, BL, 0.005 )
ptsR = interpolate( TR, BR, 0.005 )
ptsB = interpolate( BL, BR )
for a,b in zip(ptsL, ptsR):
plt.plot( [a[0]*W, b[0]*W], [a[1]*H, b[1]*H], 'ro', linestyle="--" )
for a,b in zip(ptsT, ptsB):
plt.plot( [a[0]*W, b[0]*W], [a[1]*H, b[1]*H], 'ro', linestyle="--" )
plt.show()