2019-07-09 23:01:09 +02:00
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* CNIRevelator *
* *
* Desc : Application IHM & work main class *
* *
* Copyright © 2018 - 2019 Adrien Bourmault ( neox95 ) *
* *
* This file is part of CNIRevelator . *
* *
* CNIRevelator is free software : you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation , either version 3 of the License , or *
* any later version . *
* *
* CNIRevelator is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY * without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with CNIRevelator . If not , see < https : * www . gnu . org / licenses / > . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
from PIL import Image , ImageFont , ImageDraw , ImageTk , ImageEnhance , ImageFilter
import math , warnings , string
2019-07-11 11:16:41 +02:00
from tkinter import *
from tkinter . messagebox import *
from tkinter import filedialog
from tkinter import ttk
2019-07-12 16:12:44 +02:00
import threading
from datetime import datetime
2019-07-17 17:12:21 +02:00
import re
2019-07-09 23:01:09 +02:00
2019-07-19 17:17:30 +02:00
import ihm # ihm.py
2019-07-12 16:12:44 +02:00
import logger # logger.py
2019-07-09 23:01:09 +02:00
import mrz # mrz.py
2019-07-12 10:57:03 +02:00
import globs # globs.py
2019-07-12 16:12:44 +02:00
import pytesseract # pytesseract.py
from image import * # image.py
# Global handler
logfile = logger . logCur
2019-07-09 23:01:09 +02:00
class mainWindow ( Tk ) :
2019-07-12 16:12:44 +02:00
def __init__ ( self ) :
2019-07-09 23:01:09 +02:00
Tk . __init__ ( self )
2019-07-12 16:12:44 +02:00
self . initialize ( )
2019-07-09 23:01:09 +02:00
2019-07-12 16:12:44 +02:00
def initialize ( self ) :
2019-07-18 15:37:58 +02:00
self . mrzChar = ' '
self . mrzDecided = False
2019-07-19 17:17:30 +02:00
self . Tags = [ ]
2019-07-09 23:01:09 +02:00
2019-07-12 16:12:44 +02:00
# Get the screen size
2019-07-09 23:01:09 +02:00
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
2019-07-12 16:12:44 +02:00
logfile . printdbg ( ' mainWindow() : Launching main window with resolution ' + str ( ws ) + ' x ' + str ( hs ) )
2019-07-09 23:01:09 +02:00
self . grid ( )
2019-07-12 16:12:44 +02:00
# Configuring the size of each part of the window
2019-07-09 23:01:09 +02:00
self . grid_columnconfigure ( 0 , weight = 1 , minsize = ( ws / 2 * 0.3333333333333333 ) )
self . grid_columnconfigure ( 1 , weight = 1 , minsize = ( ws / 2 * 0.3333333333333333 ) )
self . grid_columnconfigure ( 2 , weight = 1 , minsize = ( ws / 2 * 0.3333333333333333 ) )
self . grid_rowconfigure ( 0 , weight = 1 , minsize = ( hs / 2 * 0.5 ) )
self . grid_rowconfigure ( 1 , weight = 1 , minsize = ( hs / 2 * 0.5 ) )
2019-07-12 16:12:44 +02:00
# Prepare the data sections
2019-07-09 23:01:09 +02:00
self . lecteur_ci = ttk . Labelframe ( self , text = " Informations sur la pièce d ' identité " )
self . lecteur_ci . grid_columnconfigure ( 0 , weight = 1 )
self . lecteur_ci . grid_columnconfigure ( 1 , weight = 1 )
self . lecteur_ci . grid_columnconfigure ( 2 , weight = 1 )
self . lecteur_ci . grid_columnconfigure ( 3 , weight = 1 )
self . lecteur_ci . grid_columnconfigure ( 4 , weight = 1 )
self . lecteur_ci . grid_columnconfigure ( 5 , weight = 1 )
self . lecteur_ci . grid_rowconfigure ( 1 , weight = 1 )
self . lecteur_ci . grid_rowconfigure ( 2 , weight = 1 )
self . lecteur_ci . grid_rowconfigure ( 3 , weight = 1 )
self . lecteur_ci . grid_rowconfigure ( 4 , weight = 1 )
self . lecteur_ci . grid_rowconfigure ( 5 , weight = 1 )
2019-07-12 16:12:44 +02:00
# Fill the data sections
2019-07-09 23:01:09 +02:00
ttk . Label ( ( self . lecteur_ci ) , text = ' Nom : ' ) . grid ( column = 0 , row = 1 , padx = 5 , pady = 5 )
self . nom = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . nom . grid ( column = 1 , row = 1 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Nom (2) : ' ) . grid ( column = 0 , row = 2 , padx = 5 , pady = 5 )
self . prenom = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . prenom . grid ( column = 1 , row = 2 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Date de naissance : ' ) . grid ( column = 0 , row = 3 , padx = 5 , pady = 5 )
self . bdate = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . bdate . grid ( column = 1 , row = 3 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Date de délivrance : ' ) . grid ( column = 0 , row = 4 , padx = 5 , pady = 5 )
self . ddate = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . ddate . grid ( column = 1 , row = 4 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = " Date d ' expiration : " ) . grid ( column = 0 , row = 5 , padx = 5 , pady = 5 )
self . edate = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . edate . grid ( column = 1 , row = 5 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Sexe du porteur : ' ) . grid ( column = 4 , row = 1 , padx = 5 , pady = 5 )
self . sex = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . sex . grid ( column = 5 , row = 1 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Pays de délivrance : ' ) . grid ( column = 4 , row = 2 , padx = 5 , pady = 5 )
self . pays = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . pays . grid ( column = 5 , row = 2 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Nationalité du porteur : ' ) . grid ( column = 4 , row = 3 , padx = 5 , pady = 5 )
self . nat = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . nat . grid ( column = 5 , row = 3 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Immatriculation : ' ) . grid ( column = 4 , row = 4 , padx = 5 , pady = 5 )
self . indic = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . indic . grid ( column = 5 , row = 4 , padx = 5 , pady = 5 )
ttk . Label ( ( self . lecteur_ci ) , text = ' Numéro de document : ' ) . grid ( column = 4 , row = 5 , padx = 5 , pady = 5 )
self . no = ttk . Label ( ( self . lecteur_ci ) , text = ' ' )
self . no . grid ( column = 5 , row = 5 , padx = 5 , pady = 5 )
2019-07-12 16:12:44 +02:00
2019-07-09 23:01:09 +02:00
self . nom [ ' text ' ] = ' Inconnu(e) '
self . prenom [ ' text ' ] = ' Inconnu(e) '
self . bdate [ ' text ' ] = ' Inconnu(e) '
self . ddate [ ' text ' ] = ' Inconnu(e) '
self . edate [ ' text ' ] = ' Inconnu(e) '
self . no [ ' text ' ] = ' Inconnu(e) '
self . sex [ ' text ' ] = ' Inconnu(e) '
self . nat [ ' text ' ] = ' Inconnu(e) '
self . pays [ ' text ' ] = ' Inconnu(e) '
self . indic [ ' text ' ] = ' Inconnu(e) '
2019-07-12 16:12:44 +02:00
# The STATUS indicator
2019-07-09 23:01:09 +02:00
self . STATUT = ttk . Labelframe ( self , text = ' Statut ' )
self . STATUT . grid_columnconfigure ( 0 , weight = 1 )
self . STATUT . grid_rowconfigure ( 0 , weight = 1 )
self . STATUStxt = Label ( ( self . STATUT ) , text = ' ' , font = ' Times 24 ' , fg = ' #FFBF00 ' )
self . STATUStxt . grid ( column = 0 , row = 0 , padx = 0 , pady = 0 , sticky = ' EWNS ' )
self . STATUStxt [ ' text ' ] = ' EN ATTENTE '
2019-07-12 16:12:44 +02:00
# The terminal to enter the MRZ
2019-07-09 23:01:09 +02:00
self . terminal = ttk . Labelframe ( self , text = ' Terminal de saisie ' )
self . terminal . grid_columnconfigure ( 0 , weight = 1 )
self . terminal . grid_rowconfigure ( 0 , weight = 1 )
self . termframe = Frame ( self . terminal )
self . termframe . grid ( column = 0 , row = 0 , sticky = ' EW ' )
self . termframe . grid_columnconfigure ( 0 , weight = 1 )
self . termframe . grid_rowconfigure ( 0 , weight = 1 )
2019-07-17 17:12:21 +02:00
self . termtext = Text ( ( self . termframe ) , state = ' normal ' , width = 60 , height = 4 , wrap = ' none ' , font = ' Terminal 17 ' , fg = ' #121f38 ' )
2019-07-09 23:01:09 +02:00
self . termtext . grid ( column = 0 , row = 0 , sticky = ' NEW ' , padx = 5 )
2019-07-12 16:12:44 +02:00
# The monitor that indicates some useful infos
2019-07-09 23:01:09 +02:00
self . monitor = ttk . Labelframe ( self , text = ' Moniteur ' )
self . monlog = Text ( ( self . monitor ) , state = ' disabled ' , width = 60 , height = 10 , wrap = ' word ' )
self . monlog . grid ( column = 0 , row = 0 , sticky = ' EWNS ' , padx = 5 , pady = 5 )
self . scrollb = ttk . Scrollbar ( ( self . monitor ) , command = ( self . monlog . yview ) )
self . scrollb . grid ( column = 1 , row = 0 , sticky = ' EWNS ' , padx = 5 , pady = 5 )
self . monlog [ ' yscrollcommand ' ] = self . scrollb . set
self . monitor . grid_columnconfigure ( 0 , weight = 1 )
self . monitor . grid_rowconfigure ( 0 , weight = 1 )
2019-07-12 16:12:44 +02:00
# All the items griding
2019-07-09 23:01:09 +02:00
self . lecteur_ci . grid ( column = 0 , row = 0 , sticky = ' EWNS ' , columnspan = 2 , padx = 5 , pady = 5 )
self . STATUT . grid ( column = 2 , row = 0 , sticky = ' EWNS ' , columnspan = 1 , padx = 5 , pady = 5 )
self . terminal . grid ( column = 0 , row = 1 , sticky = ' EWNS ' , columnspan = 2 , padx = 5 , pady = 5 )
self . monitor . grid ( column = 2 , row = 1 , sticky = ' EWNS ' , columnspan = 1 , padx = 5 , pady = 5 )
2019-07-12 16:12:44 +02:00
self . update ( )
# What is a window without a menu bar ?
2019-07-09 23:01:09 +02:00
menubar = Menu ( self )
menu1 = Menu ( menubar , tearoff = 0 )
menu1 . add_command ( label = ' Nouveau ' , command = ( self . newEntry ) )
menu1 . add_command ( label = ' Ouvrir scan... ' , command = ( self . openingScan ) )
menu1 . add_separator ( )
menu1 . add_command ( label = ' Quitter ' , command = ( self . destroy ) )
menubar . add_cascade ( label = ' Fichier ' , menu = menu1 )
menu3 = Menu ( menubar , tearoff = 0 )
menu3 . add_command ( label = ' A propos ' , command = ( self . infobox ) )
menubar . add_cascade ( label = ' Aide ' , menu = menu3 )
self . config ( menu = menubar )
2019-07-12 16:12:44 +02:00
# The title
2019-07-12 10:57:03 +02:00
self . wm_title ( globs . CNIRName )
2019-07-12 16:12:44 +02:00
# The icon
2019-07-09 23:01:09 +02:00
if getattr ( sys , ' frozen ' , False ) :
self . iconbitmap ( sys . _MEIPASS + ' \\ id-card.ico \\ id-card.ico ' )
else :
self . iconbitmap ( ' id-card.ico ' )
2019-07-12 16:12:44 +02:00
# Make this window resizable and set her size
2019-07-09 23:01:09 +02:00
self . resizable ( width = True , height = True )
self . minsize ( self . winfo_width ( ) , self . winfo_height ( ) )
w = int ( self . winfo_width ( ) )
h = int ( self . winfo_height ( ) )
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self . geometry ( ' %d x %d + %d + %d ' % ( w , h , x , y ) )
2019-07-12 16:12:44 +02:00
# Some bindings
2019-07-17 17:12:21 +02:00
self . termtext . bind ( ' <Key> ' , self . entryValidation )
2019-07-18 15:37:58 +02:00
self . termtext . bind ( ' <<Paste>> ' , self . pasteValidation )
2019-07-09 23:01:09 +02:00
self . update ( )
2019-07-17 17:12:21 +02:00
logfile . printdbg ( ' Initialization successful ' )
2019-07-09 23:01:09 +02:00
def onTabPressed ( self , event ) :
return ' break '
2019-07-19 17:17:30 +02:00
def stringValidation ( self ) :
# analysis
# If we must decide the type of the document
if not self . mrzDecided :
# Get the candidates
candidates = mrz . allDocMatch ( self . mrzChar . split ( " \n " ) )
if len ( candidates ) == 2 and len ( self . mrzChar ) > = 8 :
# Parameters for the choice invite
invite = ihm . DocumentAsk ( self , [ candidates [ 0 ] [ 2 ] , candidates [ 1 ] [ 2 ] ] )
invite . transient ( self )
invite . grab_set ( )
invite . focus_force ( )
self . wait_window ( invite )
self . logOnTerm ( " Document detecté : {} " . format ( candidates [ invite . choice ] [ 2 ] ) )
self . mrzDecided = candidates [ invite . choice ]
elif len ( candidates ) == 1 :
self . logOnTerm ( " Document detecté : {} " . format ( candidates [ 0 ] [ 2 ] ) )
self . mrzDecided = candidates [ 0 ]
else :
print ( " LEN mrzChar {} VS {} " . format ( len ( self . mrzChar ) - 2 , len ( self . mrzDecided [ 0 ] [ 0 ] ) ) )
# break the line
if len ( self . mrzChar ) - 2 == len ( self . mrzDecided [ 0 ] [ 0 ] ) :
self . termtext . delete ( " 1.0 " , " end " )
self . termtext . insert ( " 1.0 " , self . mrzChar )
2019-07-17 17:12:21 +02:00
def entryValidation ( self , event ) :
"""
On the fly validation with regex
"""
2019-07-18 15:37:58 +02:00
controlled = False
2019-07-09 23:01:09 +02:00
2019-07-18 15:37:58 +02:00
# verifying that there is no Ctrl-C/Ctrl-V and others
if event . state & 0x0004 and ( event . keysym == " c " or
event . keysym == " v " or
event . keysym == " a " or
event . keysym == " z " or
event . keysym == " y " ) :
controlled = True
2019-07-12 16:12:44 +02:00
2019-07-18 15:37:58 +02:00
# If not a control char
2019-07-19 17:17:30 +02:00
if not controlled and not event . keysym in ihm . controlKeys :
2019-07-18 15:37:58 +02:00
# the regex
regex = re . compile ( " [A-Z]|<|[0-9] " )
# match !
if not regex . fullmatch ( event . char ) :
self . logOnTerm ( " Caractère non accepté ! \n " )
return " break "
2019-07-19 17:17:30 +02:00
# Adds the entry
2019-07-18 15:37:58 +02:00
self . mrzChar = self . termtext . get ( " 1.0 " , " end " ) [ : - 1 ] + event . char + ' \n '
2019-07-19 17:17:30 +02:00
self . stringValidation ( )
2019-07-18 15:37:58 +02:00
def pasteValidation ( self , event ) :
"""
On the fly validation of pasted text
"""
# cleanup
self . termtext . delete ( " 1.0 " , " end " )
# get the clipboard content
lines = self . clipboard_get ( )
2019-07-19 17:17:30 +02:00
self . mrzChar = " "
2019-07-18 15:37:58 +02:00
# the regex
regex = re . compile ( " [^A-Z0-9<] " )
lines = re . sub ( regex , ' ' , lines )
2019-07-19 17:17:30 +02:00
# Get that
for char in lines :
self . termtext . insert ( " 1.0 " , self . mrzChar )
self . mrzChar = self . mrzChar + char
self . stringValidation ( )
2019-07-18 15:37:58 +02:00
return " break "
2019-07-17 17:12:21 +02:00
2019-07-09 23:01:09 +02:00
def logOnTerm ( self , text ) :
self . monlog [ ' state ' ] = ' normal '
self . monlog . insert ( ' end ' , text )
self . monlog [ ' state ' ] = ' disabled '
self . monlog . yview ( END )
def openingScan ( self ) :
2019-07-17 17:12:21 +02:00
pass
2019-07-12 16:12:44 +02:00
# OPEN A SCAN
2019-07-09 23:01:09 +02:00
def newEntry ( self ) :
2019-07-12 16:12:44 +02:00
self . initialize ( )
2019-07-09 23:01:09 +02:00
self . logOnTerm ( ' \n \n Entrez la première ligne de MRZ svp \n ' )
def infobox ( self ) :
Tk ( ) . withdraw ( )
2019-07-12 16:12:44 +02:00
showinfo ( ' A propos du logiciel ' ,
( ' Version du logiciel : CNIRevelator ' + globs . verstring_full + ' \n \n ' +
" CNIRevelator is free software: you can redistribute it and/or modify " +
" it under the terms of the GNU General Public License as published by " +
" the Free Software Foundation, either version 3 of the License, or " +
" any later version. " + " \n \n " +
" CNIRevelator is distributed in the hope that it will be useful, " +
" but without even the implied warranty of " +
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " +
" GNU General Public License for more details. " +
" \n \n " +
" You should have received a copy of the GNU General Public License " +
" along with CNIRevelator. If not, see <https://www.gnu.org/licenses/>. " +
" \n \n " +
" Tesseract 4.0 est soumis à l ' Apache License 2004 " +
" \n \n " +
" Anaconda 3 est soumis à la licence BSD 2018-2019 " +
" \n \n " +
" En cas de problèmes, ouvrez une issue sur le github de CNIRevelator " +
" <https://github.com/neox95/CNIRevelator>, ou bien envoyez un mail à neox@os-k.eu! "
) ,
parent = self )
2019-07-09 23:01:09 +02:00
def calculSigma ( self , MRZtxt , numtype ) :
2019-07-17 17:12:21 +02:00
pass
2019-07-12 16:12:44 +02:00
# CALCUL DE TOUTES LES SOMMES DE LA CARTE CONFORMEMENT A SON TYPE
2019-07-09 23:01:09 +02:00
class OpenScan ( ttk . Frame ) :
def __init__ ( self , mainframe , fileorig , type , nframe = 1 , pagenum = 0 , file = None ) :
""" Initialize the main Frame """
if file == None :
file = fileorig
self . file = file
self . fileorig = fileorig
self . nframe = nframe
self . pagenum = pagenum
self . parent = mainframe . parent
ttk . Frame . __init__ ( self , master = mainframe )
self . master . title ( ' Ouvrir un scan... (Utilisez la roulette pour zoomer, clic gauche pour déplacer et clic droit pour sélectionner la MRZ) ' )
self . master . resizable ( width = False , height = False )
hs = self . winfo_screenheight ( )
w = int ( self . winfo_screenheight ( ) / 1.5 )
h = int ( self . winfo_screenheight ( ) / 2 )
ws = self . winfo_screenwidth ( )
hs = self . winfo_screenheight ( )
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self . master . geometry ( ' %d x %d + %d + %d ' % ( w , h , x , y ) )
if getattr ( sys , ' frozen ' , False ) :
self . master . iconbitmap ( sys . _MEIPASS + ' \\ id-card.ico \\ id-card.ico ' )
else :
self . master . iconbitmap ( ' id-card.ico ' )
self . master . rowconfigure ( 0 , weight = 1 )
self . master . columnconfigure ( 0 , weight = 1 )
self . cadre = CanvasImage ( self . master , self . file , type )
self . cadre . grid ( row = 0 , column = 0 )
self . master . menubar = Menu ( self . master )
if type == 1 :
self . master . menubar . add_command ( label = ' Page précédente ' , command = ( self . pagep ) )
self . master . menubar . add_command ( label = ' Pivoter -90° ' , command = ( self . cadre . rotatemm ) )
self . master . menubar . add_command ( label = ' Pivoter -1° ' , command = ( self . cadre . rotatem ) )
self . master . menubar . add_command ( label = ' Pivoter +1° ' , command = ( self . cadre . rotatep ) )
self . master . menubar . add_command ( label = ' Pivoter +90° ' , command = ( self . cadre . rotatepp ) )
if type == 1 :
self . master . menubar . add_command ( label = ' Page suivante ' , command = ( self . pages ) )
self . master . config ( menu = ( self . master . menubar ) )
self . cadre . canvas . bind ( ' <ButtonPress-3> ' , self . motionprep )
self . cadre . canvas . bind ( ' <B3-Motion> ' , self . motionize )
self . cadre . canvas . bind ( ' <ButtonRelease-3> ' , self . motionend )
def pages ( self ) :
if self . pagenum + 1 < self . nframe :
im = Image . open ( self . fileorig )
im . seek ( self . pagenum + 1 )
2019-07-12 10:57:03 +02:00
newpath = globs . CNIREnv + ' \\ temp ' + str ( random . randint ( 11111 , 99999 ) ) + ' .tif '
2019-07-09 23:01:09 +02:00
im . save ( newpath )
im . close ( )
self . cadre . destroy ( )
self . __init__ ( self . master , self . fileorig , 1 , self . nframe , self . pagenum + 1 , newpath )
def pagep ( self ) :
if self . pagenum - 1 > = 0 :
im = Image . open ( self . fileorig )
im . seek ( self . pagenum - 1 )
2019-07-12 10:57:03 +02:00
newpath = globs . CNIREnv + ' \\ temp ' + str ( random . randint ( 11111 , 99999 ) ) + ' .tif '
2019-07-09 23:01:09 +02:00
im . save ( newpath )
im . close ( )
self . cadre . destroy ( )
self . __init__ ( self . master , self . fileorig , 1 , self . nframe , self . pagenum - 1 , newpath )
def motionprep ( self , event ) :
if hasattr ( self , ' rect ' ) :
self . begx = event . x
self . begy = event . y
self . ix = self . cadre . canvas . canvasx ( event . x )
self . iy = self . cadre . canvas . canvasy ( event . y )
self . cadre . canvas . coords ( self . rect , self . cadre . canvas . canvasx ( event . x ) , self . cadre . canvas . canvasy ( event . y ) , self . ix , self . iy )
else :
self . begx = event . x
self . begy = event . y
self . ix = self . cadre . canvas . canvasx ( event . x )
self . iy = self . cadre . canvas . canvasy ( event . y )
self . rect = self . cadre . canvas . create_rectangle ( ( self . cadre . canvas . canvasx ( event . x ) ) , ( self . cadre . canvas . canvasy ( event . y ) ) , ( self . ix ) , ( self . iy ) , outline = ' red ' )
def motionize ( self , event ) :
event . x
event . y
self . cadre . canvas . coords ( self . rect , self . ix , self . iy , self . cadre . canvas . canvasx ( event . x ) , self . cadre . canvas . canvasy ( event . y ) )
def motionend ( self , event ) :
self . endx = event . x
self . endy = event . y
self . imtotreat = self . cadre . resizedim . crop ( ( min ( self . begx , self . endx ) , min ( self . begy , self . endy ) , max ( self . endx , self . begx ) , max ( self . endy , self . begy ) ) )
im = self . imtotreat
import CNI_pytesseract as pytesseract
try :
2019-07-12 10:57:03 +02:00
os . environ [ ' PATH ' ] = globs . CNIREnv + ' \\ Tesseract-OCR4 \\ '
os . environ [ ' TESSDATA_PREFIX ' ] = globs . CNIREnv + ' \\ Tesseract-OCR4 \\ tessdata '
2019-07-09 23:01:09 +02:00
self . text = pytesseract . image_to_string ( im , lang = ' ocrb ' , boxes = False , config = ' --psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890< ' )
except pytesseract . TesseractNotFoundError as e :
try :
2019-07-12 10:57:03 +02:00
os . remove ( globs . CNIREnv + ' \\ Tesseract-OCR4 \\ *.* ' )
2019-07-09 23:01:09 +02:00
except Exception :
pass
showerror ( ' Erreur de module OCR ' , ( ' Le module OCR localisé en ' + str ( os . environ [ ' PATH ' ] ) + ' est introuvable. Il sera réinstallé à la prochaine exécution ' ) , parent = self )
except pytesseract . TesseractError as e :
pass
self . master . success = False
dialogconf = OpenScanDialog ( self . master , self . text )
dialogconf . transient ( self )
dialogconf . grab_set ( )
self . wait_window ( dialogconf )
if self . master . success :
self . master . destroy ( )