Skip to content

Instantly share code, notes, and snippets.

@loguntsov
Last active January 23, 2018 19:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save loguntsov/92f07b6c8303f92ef9fd5cee823db900 to your computer and use it in GitHub Desktop.
Save loguntsov/92f07b6c8303f92ef9fd5cee823db900 to your computer and use it in GitHub Desktop.
Stabilization of white paper inside image. It will reduce perspective distortion also. For all questions pls write me on email: loguntsov@gmail.com
import cv, cv2, numpy as np
import sys, math as m
import glob, os
def get_new(old):
new = np.ones(old.shape, np.uint8)
cv2.bitwise_not(new,new)
return new
def remove(contour, n):
if len(contour) <= n:
return contour
c = np.array([])
s = -1
for i, val in enumerate(contour):
c0 = np.copy(contour)
c0 = np.delete(c0, i, axis = 0)
s0 = m.fabs(cv2.contourArea(c0))
if s0 > s:
s = s0
c = c0
print c, s
return remove(c,n)
def resize(file):
cv2.namedWindow('result', cv2.WINDOW_NORMAL)
cv2.resizeWindow('result', 2000, 1000)
orig = cv2.imread(file)
cv2.imshow('result', orig)
# these constants are carefully picked
MORPH = 10
CANNY = 150
HOUGH = 15
HX = 1620
HY = 1080
gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5,5), 0)
img = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)[1]
cv2.imshow('result', img)
#cv2.waitKey(0)
# this is to recognize white on white
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(MORPH,MORPH))
dilated = cv2.dilate(img, kernel, iterations=1)
cv2.imshow('result', dilated)
edges = cv2.Canny(dilated, 0.4*CANNY, CANNY, apertureSize=3)
cv2.imshow('result', edges)
lines = cv2.HoughLinesP(edges, 1, 3.14/180, HOUGH)
for line in lines[0]:
cv2.line(edges, (line[0], line[1]), (line[2], line[3]),
(255,255,255), 2, 8)
# finding contours
contours, _ = cv2.findContours(edges.copy(), cv.CV_RETR_EXTERNAL,
cv.CV_CHAIN_APPROX_TC89_KCOS)
contours = filter(lambda cont: cv2.arcLength(cont, True) > 4000, contours)
#contours = filter(lambda cont: m.fabs(cv2.contourArea(cont)) > 50000, contours)
# simplify contours down to polygons
rects = []
new1 = get_new(img)
# simplify contours down to polygons
rects = []
for cont in contours:
rect = cv2.approxPolyDP(cont, 200, True).copy().reshape(-1, 2)
rects.append(rect)
c = cv2.convexHull(np.array([x for sublist in rects for x in sublist]))
# that's basically it
# show only contours
new = get_new(img)
for point in c :
print( point )
# new1 = cv2.preCornerDetect(new, 5)
# cv2.GaussianBlur(new, (9,9), 0, new)
# new = cv2.Canny(new, 0, CANNY, apertureSize=3)
p = remove(c, 4)
extBot = p[0][0]
extRight = p[1][0]
extLeft = p[2][0]
extTop = p[3][0]
cv2.circle(new, tuple(extLeft), 10, (0, 0, 0), -1)
cv2.circle(new, tuple(extRight), 10, (0, 0, 0), -1)
cv2.circle(new, tuple(extTop), 10, (0, 0, 0), -1)
cv2.circle(new, tuple(extBot), 10, (0, 0, 0), -1)
cv2.drawContours(orig, [p],-1,(255,255,255),1)
cv2.drawContours(new, [p],-1,(0,255,0),1)
pts1 = np.float32([extLeft,extTop,extRight, extBot])
pts2 = np.float32([[0,0],[HX,0],[0,HY],[HX,HY]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(orig,M,(HX,HY))
#cv2.waitKey(0)
#cv2.waitKey(0)
#cv2.waitKey(0)
cv2.imshow('result', new)
#cv2.waitKey(0)
cv2.imshow('result', dst)
#cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("result/" + os.path.basename(file), dst)
for file in glob.glob("./*.jpg"):
resize(file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment