Skip to content

Instantly share code, notes, and snippets.

@santhalakshminarayana
Created September 27, 2019 14:21
Show Gist options
  • Save santhalakshminarayana/8017038cbaadf5fa5af8d943e4466189 to your computer and use it in GitHub Desktop.
Save santhalakshminarayana/8017038cbaadf5fa5af8d943e4466189 to your computer and use it in GitHub Desktop.
Convert Image documents to scanned PDF document in Python using OpenCv, PIL, Scikit-Image.
import numpy as np
import matplotlib.pyplot as plt
import cv2
from PIL import Image
from skimage.filters import threshold_local
import os
def plot_img(img,is_gray=True):
fig=plt.figure(figsize=(10,15))
ax=fig.add_subplot(111)
cp_img=None
if is_gray is False:
cp_img=img.copy()
cp_img[:,:,0]=img[:,:,2]
cp_img[:,:,2]=img[:,:,0]
ax.imshow({True:img,False:cp_img}[is_gray is True],
cmap={True:'gray',False:None}[is_gray is True])
plt.xticks([]),plt.yticks([])
plt.show()
files_in_dir=os.listdir()
curr_path=os.getcwd()
#get image file names in current directory
image_names=[]
conventions=['jpeg','png','jpg']
for file in files_in_dir:
ext=file.split('.')[-1]
if ext in conventions:
image_names.insert(0,file)
#Read images into opencv numpy arrays
images_read=[]
for name in image_names:
img=cv2.imread(name)
images_read.insert(0,img)
#Convert RGB images to Gray Scale
thsh_images=[]
for img in images_read:
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
clahe=cv2.createCLAHE(clipLimit=4.0,tileGridSize=(16,16))
img_gray=clahe.apply(img_gray)
ret,th=cv2.threshold(img_gray,130,255,cv2.THRESH_BINARY)
thsh_images.append(th)
#Find contours in image using (tree retrival method) for hierarchy
image_conts=[]
for img in thsh_images:
contours,_=cv2.findContours(img.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
image_conts.append(contours)
#Look for maximum area contour which describes page/rectangle structure in image
max_area_conts=[]
for contour in image_conts:
max_ind,max_area=None,0
for ind,cnt in enumerate(contour):
area=cv2.contourArea(cnt)
if area > max_area:
max_area=area
max_ind=ind
max_area_conts.append(max_ind)
#Fit contour of maximum area
for ind,contour in enumerate(image_conts):
img=images_read[ind].copy()
img=cv2.drawContours(img,contour,3,(0,255,0),4)
#plot_img(cv2.drawContours(img,contour,max_area_conts[ind],(0,235,0),10),False)
#Draw closest four sided shape around maximum contour which is our
#area of interest in image
approx_cont=[]
for ind in range(len(images_read)):
epsilon=0.02*cv2.arcLength(image_conts[ind][max_area_conts[ind]],True)
approx=cv2.approxPolyDP(image_conts[ind][max_area_conts[ind]],epsilon,True)
approx_cont.append(np.squeeze(approx))
#im=cv2.drawContours(images_read[ind].copy(),[approx],0,(0,19,150),-1)
#plot_img(im,False)
#Take out the four sided area of interest from image and
#project to rectangle shape which is usual shape of an image.
rect_images=[]
for ind in range(len(images_read)):
#top-left,bottom-left,bottom-right,top-right
tl,bl,br,tr=approx_cont[ind].tolist()
top_width=np.sqrt((tl[0]-tr[0])**2 + (tl[1]-tr[1])**2)
bottom_width=np.sqrt((bl[0]-br[0])**2 + (bl[1]-br[1])**2)
left_height=np.sqrt((tl[0]-bl[0])**2 + (tl[1]-bl[1])**2)
right_height=np.sqrt((tr[0]-br[0])**2 + (tr[1]-br[1])**2)
width=int(max(top_width,bottom_width))
height=int(max(left_height,right_height))
#order is tl,tr,br,bl
pres=np.array([tl,tr,br,bl],dtype='float32')
to=np.array([[0,0],[width-1,0],[width-1,height-1],[0,height-1]],dtype="float32")
M=cv2.getPerspectiveTransform(pres,to)
dst=cv2.warpPerspective(images_read[ind].copy(),M,(int(width),int(height)))
rect_images.append(dst)
#plot_img(dst,False)
#Digitise image in black and white as a scanned document
digitised_image_names=[]
for ind in range(len(rect_images)):
img_gray=cv2.cvtColor(rect_images[ind].copy(),cv2.COLOR_BGR2GRAY)
th=threshold_local(img_gray.copy(),101,offset=10,method="gaussian")
img_gray=(img_gray>th)
imgg=Image.fromarray(img_gray)
size=(images_read[ind].shape[0],images_read[ind].shape[1])
imgg.resize(size)
name=curr_path+"/digitised_"+image_names[ind].split('.')[0]+'.jpg'
digitised_image_names.append(name)
imgg.save(digitised_image_names[ind])
#Convert all digitised images to pdf format
digitised_images=[]
for name in digitised_image_names:
imgg=Image.open(name)
digitised_images.append(imgg)
name=curr_path+"/digitised_images"+'.pdf'
if len(digitised_images)>1:
digitised_images[0].save(name,save_all=True,append_images=digitised_images[1:],resolution=100.0)
else:
digitised_images[0].save(name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment