|
import cv2 |
|
import matplotlib.pyplot as plt |
|
import numpy as np |
|
from skimage.filters import threshold_local |
|
import os |
|
from PIL import Image |
|
from rembg import remove |
|
|
|
def opencv_resize(image, ratio): |
|
width = int(image.shape[1] * ratio) |
|
height = int(image.shape[0] * ratio) |
|
dim = (width, height) |
|
return cv2.resize(image, dim, interpolation = cv2.INTER_AREA) |
|
|
|
def plot_rgb(image): |
|
plt.figure(figsize=(16,10)) |
|
return plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) |
|
|
|
def plot_gray(image): |
|
plt.figure(figsize=(16,10)) |
|
return plt.imshow(image, cmap='Greys_r') |
|
|
|
|
|
def approximate_contour(contour): |
|
peri = cv2.arcLength(contour, True) |
|
return cv2.approxPolyDP(contour, 0.032 * peri, True) |
|
|
|
def get_receipt_contour(contours): |
|
|
|
for c in contours: |
|
approx = approximate_contour(c) |
|
|
|
if len(approx) == 4: |
|
return approx |
|
|
|
def contour_to_rect(image, contour): |
|
resize_ratio = 1000 / image.shape[0] |
|
pts = contour.reshape(4, 2) |
|
rect = np.zeros((4, 2), dtype = "float32") |
|
|
|
|
|
s = pts.sum(axis = 1) |
|
rect[0] = pts[np.argmin(s)] |
|
rect[2] = pts[np.argmax(s)] |
|
|
|
|
|
|
|
diff = np.diff(pts, axis = 1) |
|
rect[1] = pts[np.argmin(diff)] |
|
rect[3] = pts[np.argmax(diff)] |
|
return rect / resize_ratio |
|
|
|
def wrap_perspective(img, rect): |
|
|
|
(tl, tr, br, bl) = rect |
|
|
|
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2)) |
|
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2)) |
|
|
|
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2)) |
|
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2)) |
|
|
|
|
|
maxWidth = max(int(widthA), int(widthB)) |
|
maxHeight = max(int(heightA), int(heightB)) |
|
|
|
dst = np.array([ |
|
[0, 0], |
|
[maxWidth - 1, 0], |
|
[maxWidth - 1, maxHeight - 1], |
|
[0, maxHeight - 1]], dtype = "float32") |
|
|
|
M = cv2.getPerspectiveTransform(rect, dst) |
|
|
|
return cv2.warpPerspective(img, M, (maxWidth, maxHeight)) |
|
|
|
def bw_scanner(image): |
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
T = threshold_local(gray, 21, offset = 5, method = "gaussian") |
|
return (gray > T).astype("uint8") * 255 |
|
|
|
def remove_bg(path): |
|
input = cv2.imread(path) |
|
output = remove(input) |
|
return output |
|
|
|
def processed_result(filename): |
|
name = os.path.basename(filename) |
|
head,sep,tail = name.partition('.') |
|
image = remove_bg(filename) |
|
|
|
resize_ratio = 1000 / image.shape[0] |
|
original = image.copy() |
|
image = opencv_resize(image, resize_ratio) |
|
|
|
|
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
|
|
|
|
blurred = cv2.GaussianBlur(gray, (5, 5), 1) |
|
blurred = cv2.medianBlur(blurred,7) |
|
|
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) |
|
erosion = cv2.erode(blurred,kernel,iterations = 1) |
|
|
|
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 50)) |
|
rectKernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 20)) |
|
dilated = cv2.dilate(erosion, rectKernel) |
|
|
|
opening = cv2.morphologyEx(dilated, cv2.MORPH_OPEN, rectKernel2) |
|
closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, rectKernel2) |
|
|
|
(thresh, blackAndWhiteImage) = cv2.threshold(closing, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) |
|
edged = cv2.Canny(blackAndWhiteImage, 30, 30, apertureSize=3) |
|
|
|
|
|
contours, hierarchy = cv2.findContours(blackAndWhiteImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
image_with_contours = cv2.drawContours(image.copy(), contours, -1, (0,255,0), 3) |
|
|
|
largest_contours = sorted(contours, key = cv2.contourArea, reverse = True)[:10] |
|
image_with_largest_contours = cv2.drawContours(image.copy(), largest_contours, -1, (0,255,0), 3) |
|
|
|
receipt_contour = get_receipt_contour(largest_contours) |
|
image_with_receipt_contour = cv2.drawContours(image.copy(), [receipt_contour], -1, (0, 255, 0), 2) |
|
|
|
scanned = wrap_perspective(original.copy(), contour_to_rect(original, receipt_contour)) |
|
|
|
temp_image = cv2.cvtColor(scanned.copy(), cv2.COLOR_BGR2RGB) |
|
|
|
blurred = cv2.GaussianBlur(temp_image, (5, 5), 1) |
|
|
|
blurred = cv2.medianBlur(blurred,7) |
|
|
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) |
|
erosion = cv2.erode(blurred,kernel,iterations = 1) |
|
|
|
|
|
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 50)) |
|
rectKernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 20)) |
|
dilated = cv2.dilate(erosion, rectKernel) |
|
|
|
|
|
opening = cv2.morphologyEx(dilated, cv2.MORPH_OPEN, rectKernel2) |
|
closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, rectKernel2) |
|
|
|
edged = cv2.Canny(opening, 30, 30, apertureSize=3) |
|
|
|
rho = 1 |
|
theta = np.pi / 600 |
|
threshold = 10 |
|
min_line_length = 50 |
|
max_line_gap = 20 |
|
|
|
line_image = np.copy(temp_image) * 0 |
|
|
|
minLineLength = 100 |
|
maxLineGap = 10 |
|
lines = cv2.HoughLinesP(edged, rho, theta, threshold, np.array([]), |
|
min_line_length, max_line_gap) |
|
for line in lines: |
|
for x1,y1,x2,y2 in line: |
|
cv2.line(line_image,(x1,y1),(x2,y2),(255,255,255),20) |
|
diff_x = abs(x1 - x2) |
|
diff_y = abs(y1 - y2) |
|
if(diff_y <= diff_x): |
|
cv2.line(line_image,(x1,y1),(x2,y1),(0,255,0),5) |
|
else: |
|
cv2.line(line_image,(x1,y1),(x1,y2),(0,0,255),5) |
|
|
|
lines_edges = cv2.addWeighted(temp_image, 0.8, line_image, 1, 0) |
|
|
|
result = bw_scanner(scanned) |
|
output = Image.fromarray(result) |
|
output.save("C:\\Users\\Amrit\\Btech_project\\Processed_img\\"+head+".png") |
|
|
|
|
|
def processed_image(img): |
|
image = remove(img) |
|
|
|
resize_ratio = 1000 / image.shape[0] |
|
original = image.copy() |
|
image = opencv_resize(image, resize_ratio) |
|
|
|
|
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
|
|
|
|
blurred = cv2.GaussianBlur(gray, (5, 5), 1) |
|
blurred = cv2.medianBlur(blurred,7) |
|
|
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) |
|
erosion = cv2.erode(blurred,kernel,iterations = 1) |
|
|
|
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 50)) |
|
rectKernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 20)) |
|
dilated = cv2.dilate(erosion, rectKernel) |
|
|
|
opening = cv2.morphologyEx(dilated, cv2.MORPH_OPEN, rectKernel2) |
|
closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, rectKernel2) |
|
|
|
(thresh, blackAndWhiteImage) = cv2.threshold(closing, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) |
|
edged = cv2.Canny(blackAndWhiteImage, 30, 30, apertureSize=3) |
|
|
|
|
|
contours, hierarchy = cv2.findContours(blackAndWhiteImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
image_with_contours = cv2.drawContours(image.copy(), contours, -1, (0,255,0), 3) |
|
|
|
largest_contours = sorted(contours, key = cv2.contourArea, reverse = True)[:10] |
|
image_with_largest_contours = cv2.drawContours(image.copy(), largest_contours, -1, (0,255,0), 3) |
|
|
|
receipt_contour = get_receipt_contour(largest_contours) |
|
image_with_receipt_contour = cv2.drawContours(image.copy(), [receipt_contour], -1, (0, 255, 0), 2) |
|
|
|
scanned = wrap_perspective(original.copy(), contour_to_rect(original, receipt_contour)) |
|
|
|
temp_image = cv2.cvtColor(scanned.copy(), cv2.COLOR_BGR2RGB) |
|
|
|
blurred = cv2.GaussianBlur(temp_image, (5, 5), 1) |
|
|
|
blurred = cv2.medianBlur(blurred,7) |
|
|
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) |
|
erosion = cv2.erode(blurred,kernel,iterations = 1) |
|
|
|
|
|
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 50)) |
|
rectKernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 20)) |
|
dilated = cv2.dilate(erosion, rectKernel) |
|
|
|
|
|
opening = cv2.morphologyEx(dilated, cv2.MORPH_OPEN, rectKernel2) |
|
closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, rectKernel2) |
|
|
|
edged = cv2.Canny(opening, 30, 30, apertureSize=3) |
|
|
|
rho = 1 |
|
theta = np.pi / 600 |
|
threshold = 10 |
|
min_line_length = 50 |
|
max_line_gap = 20 |
|
|
|
line_image = np.copy(temp_image) * 0 |
|
|
|
minLineLength = 100 |
|
maxLineGap = 10 |
|
lines = cv2.HoughLinesP(edged, rho, theta, threshold, np.array([]), |
|
min_line_length, max_line_gap) |
|
for line in lines: |
|
for x1,y1,x2,y2 in line: |
|
cv2.line(line_image,(x1,y1),(x2,y2),(255,255,255),20) |
|
diff_x = abs(x1 - x2) |
|
diff_y = abs(y1 - y2) |
|
if(diff_y <= diff_x): |
|
cv2.line(line_image,(x1,y1),(x2,y1),(0,255,0),5) |
|
else: |
|
cv2.line(line_image,(x1,y1),(x1,y2),(0,0,255),5) |
|
|
|
lines_edges = cv2.addWeighted(temp_image, 0.8, line_image, 1, 0) |
|
|
|
result = bw_scanner(scanned) |
|
output = Image.fromarray(result) |
|
return result |