""" Group image in sections. Order the sections and save as separate images.
"""
import cv2
import imutils
import os
import shutil
import sys
def sort_contours(cnts, method="left-to-right"):
# initialize the reverse flag and sort index
reverse = False
i = 0
# handle if we need to sort in reverse
if method == "right-to-left" or method == "bottom-to-top":
reverse = True
# handle if we are sorting against the y-coordinate rather than
# the x-coordinate of the bounding box
if method == "top-to-bottom" or method == "bottom-to-top":
i = 1
# construct the list of bounding boxes and sort them from top to
# bottom
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
for boundingbox in boundingBoxes:
print(boundingbox)
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
key=lambda b:b[1][i], reverse=reverse))
# return the list of sorted contours and bounding boxes
return (cnts, boundingBoxes)
def draw_contour(image, c, i):
#print(i)
# compute the center of the contour area and draw a circle
# representing the center
M = cv2.moments(c)
if not M.get("m10", ''):
return image
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
# draw the countour number on the image
cv2.putText(image, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,
1.0, (0, 0, 255), 2)
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
# return the image with the contour number drawn on it
return image
def image_contour(img, cnt, i):
#area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
im_out = img[y:y+h, x:x+w]
sorted_filename = os.path.join(dest_dir, 'img_sorted_{}.png'.format(i+1))
cv2.imwrite(sorted_filename, im_out)
try:
filename = sys.argv[1]
except:
print('Please provide a filename')
sys.exit()
file_base = os.path.basename(filename)
dest_dir = file_base.rsplit('.', 1)[0]
os.mkdir(dest_dir)
img_location = os.path.join(dest_dir, file_base)
shutil.copy(filename, img_location)
# Load the image
img = cv2.imread(img_location)
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# smooth the image to avoid noises
gray = cv2.medianBlur(gray,1)
# Apply adaptive threshold
thresh = cv2.adaptiveThreshold(gray,255,1,1,11,2)
thresh_color = cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR)
# apply some dilation and erosion to join the gaps - change iteration to detect more or less area's
thresh = cv2.dilate(thresh,None,iterations = 8)
thresh = cv2.erode(thresh,None,iterations = 8)
cnts = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv2.contourArea, reverse=False)
(cnts, boundingBoxes) = sort_contours(cnts, method="top-to-bottom")
# loop over the (now sorted) contours and draw them
contour_numbered = thresh_color
print(len(cnts))
for (i, c) in enumerate(cnts):
#print(i+1, ':', c)
contour_numbered = draw_contour(contour_numbered, c, i)
image_contour(img, c, i)
cv2.imwrite(os.path.join(dest_dir, 'sorted.jpg'), contour_numbered)