Skip to content

Instantly share code, notes, and snippets.

@jmaroeder
Created March 25, 2014 23:14
Show Gist options
  • Select an option

  • Save jmaroeder/9773514 to your computer and use it in GitHub Desktop.

Select an option

Save jmaroeder/9773514 to your computer and use it in GitHub Desktop.
import cv2
import numpy as np
from math import *
from operator import add
# basis: http://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/
orig_imgs = ['test_imgs/01-IMG_0491.jpg',
'test_imgs/02-IMG_0492.jpg',
'test_imgs/03-IMG_0493.jpg',
'test_imgs/04-IMG_0494.jpg',
'test_imgs/05-IMG_0495.jpg',
'test_imgs/06-IMG_0496.jpg',
'test_imgs/07-IMG_0497.jpg',
'test_imgs/08-IMG_0498.jpg',
'test_imgs/09-IMG_0499.jpg',
'test_imgs/10-IMG_0500.jpg']
#ratio = 3
kernel_size = 3
def compute_intersection(line1, line2):
x1, y1, x2, y2 = line1
x3, y3, x4, y4 = line2
d = (x1-x2) * (y3-y4) - (y1-y2)*(x3-x4)
if d == 0:
return None
x = ((x1*y2 - y1*x2) * (x3-x4) - (x1-x2) * (x3*y4 - y3*x4)) / d
y = ((x1*y2 - y1*x2) * (y3-y4) - (y1-y2) * (x3*y4 - y3*x4)) / d
return (x, y)
def sort_corners(corners):
"""sorts a list of corners in top left, top right, bottom right, bottom left order"""
# determine mass center
# points that have lower y than mass center are top points, otherwise they are bottom points
# of two points, lower x is left, other is right
center_x, center_y = (0, 0)
for pt in corners:
center_x += pt[0]
center_y += pt[1]
center_x /= len(corners)
center_y /= len(corners)
center = (center_x, center_y)
top = []
bot = []
for pt in corners:
if pt[1] < center[1]:
top.append(pt)
else:
bot.append(pt)
top.sort(key=lambda pt: pt[0])
bot.sort(key=lambda pt: pt[0], reverse=True)
return top + bot
def canny_onchange(x):
img = cv2.imread(orig_imgs[cv2.getTrackbarPos('img', 'canny')])
img = cv2.resize(img, (640, 480))
cv2.imshow('pre', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
hi_threshold = cv2.getTrackbarPos('hi_threshold', 'canny')
low_threshold = cv2.getTrackbarPos('low_threshold', 'canny')
blur = cv2.GaussianBlur(gray, (7,7), 0)
#canny_edges = cv2.Canny(blur, low_threshold, low_threshold * ratio, apertureSize=kernel_size)
canny_edges = cv2.Canny(blur, low_threshold, hi_threshold, apertureSize=kernel_size)
#cv2.putText(canny_edges, "Low: %d, Ratio: %d" % (low_threshold, ratio), (5, 20), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0))
#canny_edges_display = canny_edges.copy()
canny_edges_display = cv2.cvtColor(canny_edges, cv2.COLOR_GRAY2BGR)
cv2.putText(canny_edges_display, "Low: %d, High: %d" % (low_threshold, hi_threshold), (5, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, 255)
hough_lines = cv2.HoughLinesP(canny_edges, rho=1, theta=pi/180, threshold=70, minLineLength=30, maxLineGap=10)
hough_lines = hough_lines[0] # flatten extra dimension
for y in hough_lines:
cv2.line(canny_edges_display, (y[0], y[1]), (y[2], y[3]), (0, 0, 255), 3, 8)
corners = []
for i in range(len(hough_lines)):
for j in range(i + 1, len(hough_lines)):
pt = compute_intersection(hough_lines[i], hough_lines[j])
if pt != None:
corners.append(pt)
# discard points that are way out there
corners = filter(lambda p: p[0] > 0 and p[0] < 640 and p[1] > 0 and p[1] < 480, corners)
for pt in corners:
cv2.circle(canny_edges_display, pt, radius=5, color=(255, 0, 0), thickness=3)
if len(corners) == 4:
print "found a quadrilateral"
corners = sort_corners(corners)
# apply perspective transform
h = np.array([ [0,0], [200,0], [200, 300], [0, 300] ], np.float32)
transform = cv2.getPerspectiveTransform(np.array([corners], np.float32), h)
warp = cv2.warpPerspective(img, transform, (200, 300))
cv2.imshow('warp', warp)
print corners
cv2.imshow('canny', canny_edges_display)
cv2.namedWindow('canny')
cv2.createTrackbar('img', 'canny', 0, len(orig_imgs), canny_onchange)
cv2.createTrackbar('hi_threshold', 'canny', 350, 1000, canny_onchange)
cv2.createTrackbar('low_threshold', 'canny', 175, 1000, canny_onchange)
cv2.waitKey()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment