|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import os |
|
import cv2 |
|
import argparse |
|
import numpy as np |
|
from alyn3.deskew import Deskew |
|
from alyn3.skew_detect import SkewDetect |
|
|
|
os.environ["OPENCV_IO_ENABLE_JASPER"] = "true" |
|
|
|
|
|
def deskew_image(input, output, r_angle=0, |
|
skew_max=4.0, acc_deg=0.5, roi_w=1.0, roi_h=1.0, |
|
method=1, gray=1.0, quality=100, short=None, |
|
log=None): |
|
|
|
image_name = os.path.basename(input) |
|
print('process: '+image_name) |
|
d = Deskew(input, output, |
|
r_angle=r_angle, |
|
skew_max=skew_max, |
|
acc_deg=acc_deg, |
|
method=method, |
|
gray=gray, |
|
quality=quality, |
|
short=short, |
|
roi_w=roi_w, |
|
roi_h=roi_h) |
|
res = d.run() |
|
|
|
if log: |
|
with open(log, mode='a') as f: |
|
line = '{}\t{:.6f}\n'.format( |
|
res['Image File'], (-res['Estimated Angle'])) |
|
f.write(line) |
|
|
|
|
|
def deskew_dir(input_dir_path, output_dir_path, r_angle=0, |
|
skew_max=4.0, acc_deg=0.5, roi_w=1.0, roi_h=1.0, |
|
method=1, gray=1.0, quality=100, short=None, |
|
log=None): |
|
image_list = os.listdir(input_dir_path) |
|
|
|
for image_name in image_list: |
|
input_path = os.path.join(input_dir_path, image_name) |
|
if(os.path.isdir(input_path)): |
|
continue |
|
print('process: '+str(image_name)) |
|
output_path = os.path.join(output_dir_path, image_name) |
|
d = Deskew(input_path, output_path, |
|
r_angle=r_angle, |
|
skew_max=skew_max, |
|
acc_deg=acc_deg, |
|
method=method, |
|
gray=gray, |
|
quality=quality, |
|
short=short, |
|
roi_w=roi_w, |
|
roi_h=roi_h) |
|
res = d.run() |
|
|
|
if log: |
|
with open(log, mode='a') as f: |
|
line = '{}\t{:.6f}\n'.format( |
|
res['Image File'], (-res['Estimated Angle'])) |
|
f.write(line) |
|
|
|
|
|
def add_detected_lines(input_path, output_path, |
|
skew_max=4.0, acc_deg=0.5, |
|
roi_w=1.0, roi_h=1.0, |
|
bgr=[0, 0, 255]): |
|
line_len = 4000 |
|
|
|
print("Add the detected lines to "+os.path.basename(input_path)) |
|
sd = SkewDetect(input_path, skew_max=skew_max, acc_deg=acc_deg, |
|
roi_w=roi_w, roi_h=roi_h) |
|
acc, ang_rad, distance = sd.determine_line(input_path) |
|
img = cv2.imread(input_path) |
|
if len(acc) == 0: |
|
print('Image file:{} has no lines detected'.format(input_path)) |
|
else: |
|
max_val = max(acc) |
|
for val, theta, rho in zip(acc[::-1], ang_rad[::-1], distance[::-1]): |
|
a = np.cos(theta) |
|
b = np.sin(theta) |
|
x0 = a * rho + int(img.shape[1] * (0.5-roi_w/2.0)) |
|
y0 = b * rho + int(img.shape[0] * (0.5-roi_h/2.0)) |
|
x1 = int(x0 + line_len*(-b)) |
|
y1 = int(y0 + line_len*(a)) |
|
x2 = int(x0 - line_len*(-b)) |
|
y2 = int(y0 - line_len*(a)) |
|
tmp_bgr = bgr.copy() |
|
tmp_bgr[0] = 255.0 * (1.0 - val / max_val) |
|
tmp_bgr[1] = tmp_bgr[0] |
|
|
|
cv2.line(img, (x1, y1), (x2, y2), tmp_bgr, 2) |
|
|
|
cv2.imwrite(output_path, img) |
|
|
|
|
|
def add_detected_lines_dir(input_dir_path, output_dir_path, |
|
skew_max=4.0, acc_deg=0.1, |
|
roi_w=1.0, roi_h=1.0, |
|
bgr=[0, 0, 255]): |
|
|
|
|
|
image_list = os.listdir(input_dir_path) |
|
|
|
for image_name in image_list: |
|
input_path = os.path.join(input_dir_path, image_name) |
|
if(os.path.isdir(input_path)): |
|
continue |
|
output_path = os.path.join(output_dir_path, image_name) |
|
add_detected_lines(input_path, output_path, |
|
skew_max=skew_max, acc_deg=acc_deg, |
|
roi_w=roi_w, roi_h=roi_h, |
|
bgr=[0, 0, 255]) |
|
|
|
|
|
def parse_args(): |
|
usage = 'python3 {} INPUT [-o OUTPUT] [-s SKEW_MAX] [-a ANGLE_ACC] [-m METHOD]'.format( |
|
__file__) |
|
argparser = argparse.ArgumentParser( |
|
usage=usage, |
|
description='Deskew image(when INPUT is an image) or images in INPUT(when INPUT is a directory).', |
|
formatter_class=argparse.RawTextHelpFormatter) |
|
argparser.add_argument( |
|
'input', |
|
help='input image file or directory path', |
|
type=str) |
|
argparser.add_argument( |
|
'-o', |
|
'--out', |
|
default='out.jpg', |
|
help='output file or directory path', |
|
type=str) |
|
argparser.add_argument( |
|
'-l', |
|
'--log', |
|
default=None, |
|
help='estimated skew log file path\n' |
|
'output format:\n' |
|
'Image_file_path <tab> Estimated_skew_angle[deg]') |
|
argparser.add_argument( |
|
'-s', |
|
'--skew_max', |
|
default=4.0, |
|
help='maximum expected skew angle[deg], default: 4.0', |
|
type=float) |
|
argparser.add_argument( |
|
'-a', |
|
'--angle_acc', |
|
default=0.5, |
|
help='estimated skew angle accuracy[deg], default: 0.5', |
|
type=float) |
|
argparser.add_argument( |
|
'-rw', |
|
'--roi_width', |
|
default=1.0, |
|
help='horizontal cropping ratio of the region of interest \n' |
|
'to the whole image. (0.0, 1.0] default: 1.0(whole image)', |
|
type=float) |
|
argparser.add_argument( |
|
'-rh', |
|
'--roi_height', |
|
default=1.0, |
|
help='vertical cropping ratio of the region of interest \n' |
|
'to the whole image. (0.0, 1.0] default: 1.0(whole image)', |
|
type=float) |
|
argparser.add_argument( |
|
'-m', |
|
'--method', |
|
default=1, |
|
help='interpolation method.\n' |
|
'0: Nearest-neighbor 1: Bi-linear(default)\n' |
|
'2: Bi-quadratic 3: Bi-cubic\n' |
|
'4: Bi-quartic 5: Bi-quintic\n', |
|
type=int) |
|
argparser.add_argument( |
|
'-g', |
|
'--gray', |
|
default=1.0, |
|
dest='gray', |
|
help='gray value outside the input image boundaries.\n' |
|
'[0.0(black), 1.0(white)], default: 1.0', |
|
type=float) |
|
argparser.add_argument( |
|
'-q', '--quality', |
|
default=100, |
|
dest='quality', |
|
help='output jpeg image quality.\n' |
|
'1 is worst quality and smallest file size,\n' |
|
'and 100 is best quality and largest file size.\n' |
|
'[1, 100], default: 100', |
|
type=int) |
|
argparser.add_argument( |
|
'--short', |
|
default=None, |
|
dest='short', |
|
help='the length of the short side of the output image.', |
|
type=int) |
|
argparser.add_argument( |
|
'-v', |
|
'--version', |
|
version='deskew version 1.0.0', |
|
action='version') |
|
argparser.add_argument( |
|
'--debug', |
|
action='store_true') |
|
|
|
return argparser.parse_args() |
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
args = parse_args() |
|
|
|
input = args.input |
|
output = args.out |
|
print('input directory/image: '+input) |
|
|
|
if(os.path.isdir(input)): |
|
if output[-4:] == '.jpg': |
|
output = output[:-4] |
|
print('output: '+output) |
|
os.makedirs(output, exist_ok=True) |
|
deskew_dir(input, output, |
|
r_angle=0, |
|
skew_max=args.skew_max, |
|
acc_deg=args.angle_acc, |
|
roi_w=args.roi_width, |
|
roi_h=args.roi_height, |
|
method=args.method, |
|
gray=args.gray, |
|
quality=args.quality, |
|
short=args.short, |
|
log=args.log) |
|
if args.debug: |
|
print('[Debug] Dump input images with detected lines') |
|
os.makedirs(output+'_withL', exist_ok=True) |
|
add_detected_lines_dir(input, output+'_withL', |
|
roi_w=args.roi_width, |
|
roi_h=args.roi_height, |
|
skew_max=args.skew_max, |
|
acc_deg=args.angle_acc) |
|
else: |
|
print('output: '+output) |
|
deskew_image(input, output, |
|
r_angle=0, |
|
skew_max=args.skew_max, |
|
acc_deg=args.angle_acc, |
|
roi_w=args.roi_width, |
|
roi_h=args.roi_height, |
|
method=args.method, |
|
gray=args.gray, |
|
quality=args.quality, |
|
short=args.short, |
|
log=args.log) |
|
if args.debug: |
|
print('[Debug] Dump input image with detected lines') |
|
add_detected_lines(input, output+'_withL.jpg', |
|
roi_w=args.roi_width, |
|
roi_h=args.roi_height, |
|
skew_max=args.skew_max, |
|
acc_deg=args.angle_acc) |
|
|