From f8b2a0e1047c5b1760dba84c56ee391c96fbe8d1 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Fri, 9 Aug 2019 17:07:26 +0200 Subject: [PATCH 01/18] Working on image display --- src/Invert.png | Bin 0 -> 553 bytes src/ihm.py | 16 --- src/main.py | 277 +++++++++++++++++++++++++++++++++++++++++-- src/rotateLeft.png | Bin 0 -> 750 bytes src/rotateLeft1.png | Bin 0 -> 450 bytes src/rotateRight.png | Bin 0 -> 738 bytes src/rotateRight1.png | Bin 0 -> 428 bytes src/zoomIn.png | Bin 0 -> 772 bytes src/zoomIn20.png | Bin 0 -> 1245 bytes src/zoomIn50.png | Bin 0 -> 1217 bytes src/zoomOut.png | Bin 0 -> 735 bytes src/zoomOut20.png | Bin 0 -> 1013 bytes src/zoomOut50.png | Bin 0 -> 1147 bytes 13 files changed, 267 insertions(+), 26 deletions(-) create mode 100644 src/Invert.png create mode 100644 src/rotateLeft.png create mode 100644 src/rotateLeft1.png create mode 100644 src/rotateRight.png create mode 100644 src/rotateRight1.png create mode 100644 src/zoomIn.png create mode 100644 src/zoomIn20.png create mode 100644 src/zoomIn50.png create mode 100644 src/zoomOut.png create mode 100644 src/zoomOut20.png create mode 100644 src/zoomOut50.png diff --git a/src/Invert.png b/src/Invert.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b3fb3c11b40fe1cb64b936cdffe679868134d7 GIT binary patch literal 553 zcmV+^0@nSBP)@B~OuQCJj& zJO@t$Dc~7MYNSv*MG&IJk`r`7iIOcB(nY8WUbb?_Vy za==F-T66UX_jABQu~c$(7u_82LRAOuieBfc5Tn)_d=Hy*fDbUr0e3}Y=1j-ANTI)T zz_-O(T+0Ce!bdYUjae!4v-TEbpi7JytIP9eGR3^6n=@00000NkvXXu0mjfk&*I4 literal 0 HcmV?d00001 diff --git a/src/ihm.py b/src/ihm.py index e254cfe..59c9d25 100644 --- a/src/ihm.py +++ b/src/ihm.py @@ -32,7 +32,6 @@ import PIL.Image, PIL.ImageTk import logger # logger.py import globs # globs.py -import image # image.py controlKeys = ["Escape", "Right", "Left", "Up", "Down", "Home", "End", "BackSpace", "Delete", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"] @@ -178,21 +177,6 @@ class LauncherWindow(Tk): def exit(self): self.after(1000, self.destroy) -class AutoScrollbar(ttk.Scrollbar): - - def set(self, lo, hi): - if float(lo) <= 0.0: - if float(hi) >= 1.0: - self.grid_remove() - self.grid() - ttk.Scrollbar.set(self, lo, hi) - - def pack(self, **kw): - raise TclError('Cannot use pack with the widget ' + self.__class__.__name__) - - def place(self, **kw): - raise TclError('Cannot use place with the widget ' + self.__class__.__name__) - class ResizeableCanvas(Canvas): def __init__(self,parent,**kwargs): Canvas.__init__(self,parent,**kwargs) diff --git a/src/main.py b/src/main.py index fd53870..de45c84 100644 --- a/src/main.py +++ b/src/main.py @@ -41,7 +41,6 @@ import logger # logger.py import mrz # mrz.py import globs # globs.py import pytesseract # pytesseract.py -from image import * # image.py # Global handler logfile = logger.logCur @@ -57,6 +56,7 @@ class mainWindow(Tk): self.mrzDecided = False self.Tags = [] self.compliance = True + self.corners = [] # Hide during construction self.withdraw() @@ -146,16 +146,98 @@ class mainWindow(Tk): "INDIC" : self.indic, } - # The STATUS indicator + image display + # The STATUS indicator self.STATUT = ttk.Labelframe(self, text='Affichage de documents et statut') self.STATUT.grid_columnconfigure(0, weight=1) + self.STATUT.grid_columnconfigure(1, weight=0) self.STATUT.grid_rowconfigure(0, weight=1) + self.STATUT.grid_rowconfigure(1, weight=1) + self.STATUT.grid_rowconfigure(2, weight=1) self.STATUT.frame = Frame(self.STATUT) self.STATUT.frame.grid(column=0, row=0, sticky='NSEW') self.STATUT.frame.grid_columnconfigure(0, weight=1) self.STATUT.frame.grid_rowconfigure(0, weight=1) - self.STATUT.ZONE = ihm.ResizeableCanvas(self.STATUT.frame, bg=self["background"]) - self.STATUT.ZONE.pack(fill="both", expand=True) + # + toolbar + self.toolbar = ttk.Frame(self.STATUT) + self.toolbar.grid_columnconfigure(0, weight=1) + self.toolbar.grid_columnconfigure(1, weight=1) + self.toolbar.grid_columnconfigure(2, weight=1) + self.toolbar.grid_columnconfigure(3, weight=1) + self.toolbar.grid_columnconfigure(4, weight=1) + self.toolbar.grid_columnconfigure(5, weight=1) + self.toolbar.grid_columnconfigure(6, weight=1, minsize=10) + self.toolbar.grid_columnconfigure(7, weight=1) + self.toolbar.grid_columnconfigure(8, weight=1, minsize=10) + self.toolbar.grid_columnconfigure(9, weight=1) + self.toolbar.grid_columnconfigure(10, weight=1) + self.toolbar.grid_columnconfigure(11, weight=1) + self.toolbar.grid_columnconfigure(12, weight=1) + self.toolbar.grid_columnconfigure(13, weight=1, minsize=10) + self.toolbar.grid_columnconfigure(14, weight=1) + self.toolbar.grid_rowconfigure(0, weight=1) + + self.toolbar.zoomIn50Img = ImageTk.PhotoImage(PIL.Image.open("zoomIn50.png")) + self.toolbar.zoomIn50 = ttk.Button(self.toolbar, image=self.toolbar.zoomIn50Img, command=self.zoomInScan50) + self.toolbar.zoomIn50.grid(column=0, row=0) + + self.toolbar.zoomIn20Img = ImageTk.PhotoImage(PIL.Image.open("zoomIn20.png")) + self.toolbar.zoomIn20 = ttk.Button(self.toolbar, image=self.toolbar.zoomIn20Img, command=self.zoomInScan20) + self.toolbar.zoomIn20.grid(column=1, row=0) + + self.toolbar.zoomInImg = ImageTk.PhotoImage(PIL.Image.open("zoomIn.png")) + self.toolbar.zoomIn = ttk.Button(self.toolbar, image=self.toolbar.zoomInImg, command=self.zoomInScan) + self.toolbar.zoomIn.grid(column=2, row=0) + + self.toolbar.zoomOutImg = ImageTk.PhotoImage(PIL.Image.open("zoomOut.png")) + self.toolbar.zoomOut = ttk.Button(self.toolbar, image=self.toolbar.zoomOutImg, command=self.zoomOutScan) + self.toolbar.zoomOut.grid(column=3, row=0) + + self.toolbar.zoomOut20Img = ImageTk.PhotoImage(PIL.Image.open("zoomOut20.png")) + self.toolbar.zoomOut20 = ttk.Button(self.toolbar, image=self.toolbar.zoomOut20Img, command=self.zoomOutScan20) + self.toolbar.zoomOut20.grid(column=4, row=0) + + self.toolbar.zoomOut50Img = ImageTk.PhotoImage(PIL.Image.open("zoomOut50.png")) + self.toolbar.zoomOut50 = ttk.Button(self.toolbar, image=self.toolbar.zoomOut50Img, command=self.zoomOutScan50) + self.toolbar.zoomOut50.grid(column=5, row=0) + + self.toolbar.invertImg = ImageTk.PhotoImage(PIL.Image.open("invert.png")) + self.toolbar.invert = ttk.Button(self.toolbar, image=self.toolbar.invertImg, command=self.negativeScan) + self.toolbar.invert.grid(column=7, row=0) + + self.toolbar.rotateLeftImg = ImageTk.PhotoImage(PIL.Image.open("rotateLeft.png")) + self.toolbar.rotateLeft = ttk.Button(self.toolbar, image=self.toolbar.rotateLeftImg, command=self.rotateLeft) + self.toolbar.rotateLeft.grid(column=9, row=0) + + self.toolbar.rotateLeft1Img = ImageTk.PhotoImage(PIL.Image.open("rotateLeft1.png")) + self.toolbar.rotateLeft1 = ttk.Button(self.toolbar, image=self.toolbar.rotateLeft1Img, command=self.rotateLeft1) + self.toolbar.rotateLeft1.grid(column=10, row=0) + + self.toolbar.rotateRight1Img = ImageTk.PhotoImage(PIL.Image.open("rotateRight1.png")) + self.toolbar.rotateRight1 = ttk.Button(self.toolbar, image=self.toolbar.rotateRight1Img, command=self.rotateRight1) + self.toolbar.rotateRight1.grid(column=11, row=0) + + self.toolbar.rotateRightImg = ImageTk.PhotoImage(PIL.Image.open("rotateRight.png")) + self.toolbar.rotateRight = ttk.Button(self.toolbar, image=self.toolbar.rotateRightImg, command=self.rotateRight) + self.toolbar.rotateRight.grid(column=12, row=0) + + self.toolbar.goOCR = ttk.Button(self.toolbar, text="OCR", command=self.goOCRDetection) + self.toolbar.goOCR.grid(column=14, row=0) + + self.toolbar.grid(column=0, row=2, padx=0, pady=0) + + # + image with scrollbars + self.STATUT.hbar = ttk.Scrollbar(self.STATUT, orient='horizontal') + self.STATUT.vbar = ttk.Scrollbar(self.STATUT, orient='vertical') + self.STATUT.hbar.grid(row=1, column=0, sticky="NSEW") + self.STATUT.vbar.grid(row=0, column=1, sticky="NSEW") + + self.STATUT.ZONE = ihm.ResizeableCanvas(self.STATUT.frame, bg=self["background"], xscrollcommand=(self.STATUT.hbar.set), + yscrollcommand=(self.STATUT.vbar.set)) + self.STATUT.ZONE.grid(sticky="NSEW") + + self.STATUT.hbar.config(command=self.STATUT.ZONE.xview) + self.STATUT.vbar.config(command=self.STATUT.ZONE.yview) + self.STATUSimg = self.STATUT.ZONE.create_image(0,0, image=None) self.STATUStxt = self.STATUT.ZONE.create_text(0,0, text='', font='Times 24', fill='#FFBF00') @@ -191,7 +273,7 @@ class mainWindow(Tk): self.speed731.grid_columnconfigure(9, weight=1) self.speed731.grid_rowconfigure(0, weight=1) self.speed731text = Entry(self.speed731, font='Terminal 14') - self.speed731text.grid(column=0, row=0, sticky='NEW', padx=5) + self.speed731text.grid(column=0, row=0, sticky='NEW', padx=5, pady=5) self.speedResult = Text((self.speed731), state='disabled', width=1, height=1, wrap='none', font='Terminal 14') self.speedResult.grid(column=2, row=0, sticky='NEW') @@ -206,8 +288,8 @@ class mainWindow(Tk): self.monitor.grid_rowconfigure(0, weight=1) # All the items griding - 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.lecteur_ci.grid(column=2, row=0, sticky='EWNS', columnspan=1, padx=5, pady=5) + self.STATUT.grid(column=0, row=0, sticky='EWNS', columnspan=2, padx=5, pady=5) self.terminal.grid(column=0, row=2, sticky='EWNS', columnspan=2, padx=5, pady=5) self.terminal2.grid(column=0, row=1, sticky='EWNS', columnspan=2, padx=5, pady=5) self.monitor.grid(column=2, row=1, sticky='EWNS', columnspan=1, rowspan=2, padx=5, pady=5) @@ -260,12 +342,17 @@ class mainWindow(Tk): # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) self.statusUpdate("EN ATTENTE", "#FFBF00", photo, setplace=True) - + self.STATUT.imagePath = "background.png" + self.STATUT.imgZoom = 1 + self.STATUT.rotateCount = 0 + self.STATUT.blackhat = False # Some bindings self.termtext.bind('', self.entryValidation) self.termtext.bind('<>', self.pasteValidation) self.speed731text.bind('', self.speedValidation) + self.STATUT.ZONE.bind("", self.rectangleSelectScan) + logfile.printdbg('Initialization successful') def statusUpdate(self, msg, color, image=None, setplace=False): @@ -279,6 +366,8 @@ class mainWindow(Tk): self.STATUT.ZONE.move(self.STATUSimg, self.STATUT.ZONE.winfo_reqwidth() / 2, self.STATUT.ZONE.winfo_reqheight() / 2) self.STATUT.ZONE.move(self.STATUStxt, self.STATUT.ZONE.winfo_reqwidth() / 2, self.STATUT.ZONE.winfo_reqheight() / 2) + self.STATUT.ZONE.configure(scrollregion=self.STATUT.ZONE.bbox("all")) + def stringValidation(self, keysym): # analysis # If we must decide the type of the document @@ -433,6 +522,37 @@ class mainWindow(Tk): return "break" + def goOCRDetection(self): + cv_img = cv2.imread(self.STATUT.imagePath) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if self.STATUT.blackhat: + self.negativeScan() + if not self.STATUT.blackhat: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + else: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Rotate + rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.STATUT.rotateCount*90),1) + cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) + # Resize + dim = (int(width * (self.STATUT.imgZoom + 100) / 100), int(height * (self.STATUT.imgZoom + 100) / 100)) + cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) + + x0 = int(self.corners[0][0]) + self.STATUT.ZONE.coords(self.STATUSimg)[0] + x1 = int(self.corners[0][1]) + self.STATUT.ZONE.coords(self.STATUSimg)[0] + y0 = int(self.corners[1][0]) + self.STATUT.ZONE.coords(self.STATUSimg)[1] + y1 = int(self.corners[1][1]) + self.STATUT.ZONE.coords(self.STATUSimg)[1] + + crop_img = cv_img[y0:y1, x0:x1] + cv2.imshow("cropped", crop_img) + cv2.waitKey(0) + def speedValidation(self, event): """ Computation of the speed entry @@ -466,8 +586,145 @@ class mainWindow(Tk): ('TIF files', '*.tiff'), ('JPEG files', '*.jpg'), ('JPEG files', '*.jpeg'))) - self.mrzdetected = '' - self.mrzdict = {} + # Load an image using OpenCV + self.STATUT.imagePath = path + self.STATUT.imgZoom = 1 + self.STATUT.blackhat = False + self.STATUT.rotateCount = 0 + cv_img = cv2.imread(path) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage + photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) + self.statusUpdate("", "#FFBF00", photo) + + def zoomInScan50(self, quantity = 50): + self.STATUT.imgZoom += quantity + self.resizeScan() + + def zoomOutScan50(self, quantity = 50): + self.STATUT.imgZoom -= quantity + self.resizeScan() + + def zoomInScan20(self, quantity = 20): + self.STATUT.imgZoom += quantity + self.resizeScan() + + def zoomOutScan20(self, quantity = 20): + self.STATUT.imgZoom -= quantity + self.resizeScan() + + def zoomInScan(self, quantity = 1): + self.STATUT.imgZoom += quantity + self.resizeScan() + + def zoomOutScan(self, quantity = 1): + self.STATUT.imgZoom -= quantity + self.resizeScan() + + def rotateLeft(self): + self.STATUT.rotateCount -= 1 + if self.STATUT.rotateCount < 0: + self.STATUT.rotateCount = 4 + self.resizeScan() + + def rotateRight(self): + self.STATUT.rotateCount += 1 + if self.STATUT.rotateCount > 4: + self.STATUT.rotateCount = 0 + self.resizeScan() + + def rotateRight1(self): + self.STATUT.rotateCount += 0.1 + if self.STATUT.rotateCount > 4: + self.STATUT.rotateCount = 0 + self.resizeScan() + + def rotateLeft1(self): + self.STATUT.rotateCount -= 0.1 + if self.STATUT.rotateCount < 0: + self.STATUT.rotateCount = 4 + self.resizeScan() + + def rectangleSelectScan(self, event): + canvas = event.widget + self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)]) + if len(self.corners) == 2: + self.select = self.STATUT.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2) + print("y") + if len(self.corners) > 2: + self.corners = [] + self.STATUT.ZONE.delete(self.select) + + print(self.corners) + + def negativeScan(self): + # Load an image using OpenCV + cv_img = cv2.imread(self.STATUT.imagePath) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if not self.STATUT.blackhat: + self.STATUT.blackhat = True + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) + cv_img = cv2.bitwise_not(cv_img) + else: + self.STATUT.blackhat = False + self.resizeScan(cv_img) + + def resizeScan(self, cv_img = None): + try: + if not hasattr(cv_img, 'shape'): + # Load an image using OpenCV + cv_img = cv2.imread(self.STATUT.imagePath) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if self.STATUT.blackhat: + self.negativeScan() + + if not self.STATUT.blackhat: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + else: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Rotate + rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.STATUT.rotateCount*90),1) + cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) + # Resize + dim = (int(width * (self.STATUT.imgZoom + 100) / 100), int(height * (self.STATUT.imgZoom + 100) / 100)) + cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage + photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) + self.statusUpdate("", "#FFBF00", photo) + except Exception as e: + logfile.printerr("Error with opencv : {}".format(e)) + traceback.print_exc(file=sys.stdout) + try: + # Reload an image using OpenCV + path = self.STATUT.imagePath + self.STATUT.imgZoom = 1 + self.STATUT.blackhat = False + self.STATUT.rotateCount = 0 + cv_img = cv2.imread(path) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage + photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) + self.statusUpdate("", "#FFBF00", photo) + except Exception as e: + logfile.printerr("Critical error with opencv : ".format(e)) + traceback.print_exc(file=sys.stdout) + showerror("Erreur OpenCV (traitement d'images)", "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser") + self.initialize() def newEntry(self): self.initialize() diff --git a/src/rotateLeft.png b/src/rotateLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..7653faa8a5bc8290de02bb48c62838824d1e9e81 GIT binary patch literal 750 zcmVG*q7fe?mPL;JMTC%I?MwHW-jNP z=iYPAd+&2I%3~v1(23JHhITX|gKwC?D?GtCrm$E+?o@2Re%!!2%woBW{lze@Mib4f zh4=zKV!i^xq|IRr=c^&yhTAF0mhcOoh0?x{Y$6)_8Tlk*dZV1HB8NLd$>Irq;1Mq3 zFq+X2Su+ly2M;iWquwxCRd9+02@tot>mv>kezPWf~3`MhEFSaTy`y8&J zk-`}*LjA0-mB`j($#VcMA8m_fC$C}ZNnHa}S!nvAe z144t;0tYb}BYxJ1b0wS?h4Z==_#~Wqd9>FkZ&@^8RIIyewW6v~FXEhVujescFXCO; z6#G9>FX96VPr{e=AkN~Xl@-t8X&rcrj?59Xtrk#=YUJ=dMmmq{qDvwTEx3f8>mY3r zlt=Pf>?{?q8-s!pc`QhqYLSab;}U8KT}mj=WWRYG}ev#(#2lC3Y6w%L69#d5-bT4c2d}@(a6T5u^H*|wyzS> zIL->Xc`lKx5}S`E)Kv{(9vO7tvLFnSvbWR|W<>a8R(--$^0sLZ)JO-;;J9#~Zdd$h g8x*9@lrr+^AH8D$g%Bu!ZU6uP07*qoM6N<$f-&Pq{{R30 literal 0 HcmV?d00001 diff --git a/src/rotateLeft1.png b/src/rotateLeft1.png new file mode 100644 index 0000000000000000000000000000000000000000..922496343c9b7348fed9764e206cac015af02308 GIT binary patch literal 450 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3EX7WqAsj$Z!;#Vf2?- zqae&Edv@0fAVadmHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IX1_nlZPZ!4! zkIuJOt-V+r1&)23zetU19lyvyQ6BMw+!7jTYE{hdAB%?6%yqosEFrm~vyorGCG5I` z!9>#+ax$su=~r&%{4+RX5Lj#6-1ceKhh5JkC68M@KeqPJ-O_8;2?{GN%~or&RUw%lyDHi<##n#T3-3 zIa@lVM|9nvJLg8r>L2rdoj>-zDcDR*^`twhSW@Yo3w^L|dtK{C^(uJvdkE4u?UOUY+{}>UlUEuPKgxLRgQZ>F`8w-?xlF+DX7F_Nb6Mw<&;$T%>9xiH literal 0 HcmV?d00001 diff --git a/src/rotateRight.png b/src/rotateRight.png new file mode 100644 index 0000000000000000000000000000000000000000..3e008dc9f94ab9e85d4e7ed9d892663dd6fc697b GIT binary patch literal 738 zcmV<80v-K{P)IR6!I5@ZTnDBhi?c2tlw=G%Df?BBEA;*jt*y zh}QlIY9oRe8#_%3ZTtspjM_y+BZwd|G1`bC1mgo^-VckJC3kN&yPM4=9}IhEcIJF% z=AJp{yE&DSM+^4iEKXt%w#NU*@Ch&R1RpSp*(z+8L=O9K4X-hU#R_d2Z*c<$QCAD` zc?@Bu3c_@o#b;bz4Pg_yOBh?gIKE*7gRzaov43$+dfnY`PXRuSa0SM7Mlp^j;dR7Crp(kZ?2+yJu^1_u#MsL5`cA7>bo+}Q}`S`3& zxTncL>d1h!fCKohc;}0CXcsQKIQUq|K3QQ-$YjfKGvUcNx-ukf6#{8aYR7pY_ZIL6 z?=m875dw6V@cN377ZQE}6Zn!5aXoIu-;$WMbOeLtCT5A6sz+ADKN9^7D&*8GiANIs zjo7hX#4i&4MjTo%;yxjn6Lx%Bb(Lt%Xv2V|$R5M7^&qZSx=3u!z;?x3Q>rZXSX)`# zjw_XH~?ldOV=IPnb!(!c{@pT%c4+ZMugPcCmj8#aLg;>KU?1V UT6}_D=Kufz07*qoM6N<$f&y7XIsgCw literal 0 HcmV?d00001 diff --git a/src/rotateRight1.png b/src/rotateRight1.png new file mode 100644 index 0000000000000000000000000000000000000000..a7de8622c26497031a13c5d22bed69dd6fb922cf GIT binary patch literal 428 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3EX7WqAsj$Z!;#Vf2?- zqae&Edv@0fAVadmHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IX1_nk=PZ!4! zkIuJOz4cfEMUH)x50p)OaM!6t!e}Fd(6W}J5pAj+3U3aau=DZp2uQmm$E+;K_Fc_t z%d6G9l0yDJSvF}`{JEd+Udv=w2Z zmTQaTx5Z}1tMohDTaC|_#=R_GcA@K}c~{HdSf;bdE*6)c>)qn1&fqZrV|(z$`Zb*I z%7wSgOej(8JE-*0L4V!8k7|3KtL(}x)vlZFbzAdfyngu7C3ef%#8&&*^hO_LP2o|m zIFRLa!ARBk`{tB9uBor2taFQ}8t6_r>gW52vwemSZquFCq~#gd|DGkReHujFDs>Gvs0IYr1Ejy^qWNzMR^>?_TS-*YI8I z6r`hwt{90~7=s4X;2j>~JPzOno>j2b1cj96wOEKb3Fjhi;t4*XExKb^a-mPyg*|v# z%>{nNARNVY%tJSnQn; zU_`mYlBmL0_*~|^H`a)B5OP_E&3KzUyMoo4D%R`7X4#%D;hXf(y%7c1C?>VZ7hJ~E z)NkfxWWZq>Y$F?K60t#hhN4!7~bXFgJ^s6Z3HrJ@b&4i(x;s znNEj@k60{y(fAEDVnXd#LEI~#AhwZnSSLFjzo8D>M4wKm((x2gOdqARP!>93J?;rb z8jKE_7G5hq1!b-1@735MQZ`nFP^TRfF&zs;&h9I}>Y+J)9P4c`US`5$&-O(=a>Xwir5KCoah+PX830un7l+gtjQUVynpi z-)^sejc(#k!U-uG$^S$z>=xBu->L;2zrh*Iz@zVW8F{HLVEN1d0000EuGYds#dEX z2s%P7MMNngQVEfuL@q*tSW*c>D$ztq$C99;_R`u~w6vC5hGL?+Os6fkt(p7!aBkbt zx!1in{F66t-t+#?^PKbSL1`pt#7Im=3!2dnf8ZB0URe81ETg+)hrE0-#V}s1IF(eYgT>$)Spl~h z-xuWfL4pqPCJhw`s|JUNu3276aVP%75fupQ5zX3Nh8M(Qv_fCs??eW-ij5&DMJk{k z7hqr+-eA03;QlK{ivBpa9I-;2kGECWC~g#c>WKfSbOhQlO=X2fz1R|86o-Lo5inXz zwFgugtc{p0M&j5i6;HxSY!$m**;DS0fw&!K4IJc|Gp1R%M}q^fAtaVOmbJRT%ba^aD! z4QthPtv6Gm=n2Mry3lK*Pw?vU&ph?@5(|G@t>f@xjNO)VWJkNYmhp~l8Y;JVfyqnXGOuN# zd`*p$$4&O?hYKvmFkD}_M4!ns6KDwCW?h)RzrEi%#Vzj66qeLl28Ws&)NZ0}6X?6VvH=OclrDon}uqc6mJwmSni4p`R;j zSlh`ny-#=Q4E1{im!qRIXFjBa;x9wcV`?LXeZ}ijkgfAtm4Q&u-L(nc|S~q+TOaf>57x zlvEOeG|d- z?D4|%tmeSI^5*0dX~K-O+x5xszO%opaE0KZH1!4K6S>*9S~mSQlajnyJvFAM!MfTW zGgH3lT(TH4?g|yKi$*|Tg172EPnkPEulws`S8h~00000NkvXX Hu0mjf*Sb`T literal 0 HcmV?d00001 diff --git a/src/zoomIn50.png b/src/zoomIn50.png new file mode 100644 index 0000000000000000000000000000000000000000..21acbdcda6dadcb34bbb5ce0b248e3e60029af9c GIT binary patch literal 1217 zcmV;y1U~zTP)Ud6i1A+Fbp?h1gcSmzp(?~Vi`7JPdl5Pw)ZG?BLmI z)M6F-bmU+kEXRxJ*+Hc(7%aH^L%|az5n~~~5nTIU&>L$oNAV{*j&azEk!1)jDGb*X zln*IJh*60etSpe*LsvYEUL|-NgP7c9tP5 zKIPjUHVTnGu$Z8;u^0c8A*>_Vj>EX5t<9_uh5K==jr~D*Qg{wRx$KQaI8<2MfXAF( zu?`euwwcpeB#OK4pb&5^#iU2Ug7w&4Slc3$%u~@)j*}v?jTH(FpHMYvpOH2aE?vdH0mrPHKR=tSL0 z@Xi$a^u!W8m*H1TC`Bw2x1bIK${{}@H2VwxqtXimBc>`oXq<#9p+kMBo#NgOB4HX? zjpvkpj+4+EON2bVs)LHh3c++lkrZl;wp`I2kE5nrPjB8ZQEk^=C#qVW125-nLZ)V_ z!DsYvb;CvzHm`TxfkrPR&H7-p5Lop{+fv+CZ{3gkvHaYN+#hAl{JCCb6v=0@4mBOt zfY*BU)vrqz6LxJ=RXs%Auu*+7t%{&x9_P6n-7YSwQJc5Q3WxZ@YiX=32;YYp!=Sku?FZmj>z(ksSGGg;$?47YOA zYF`UM`XE*mj5)>PRChddN6vIK#>`6-Ymin{ITn-LHp7N2Yx7zAUdq`E7mxCm$hO_v z{Ze>?uVmD8uF?g63AJGW-otIeU~nAq-u+gjsSOp($tI?uvH6JCg~!>At(mM@Y1T6_ zi>EwlI7E@&qE?n<9E<1_SE?wi9KbzThi8QndP4C#3mk4fYJS9}aqQM+<}ZHQ!NSSa z4!f^{85!vyeN{! zse7jJmTLSB&j7J@xIuCyB>9ACgaaMcSfw+dSXCmja`^56qfmT zAkIW4rHT4RR_#lDoJ79Bbcpi?B;+D$qr~%KAM8J9F>H=~8nG~qEzDD!(%i(Nx?IuD fwG%Ut!DasfMX5d&IBhQ<00000NkvXXu0mjff^j%1 literal 0 HcmV?d00001 diff --git a/src/zoomOut.png b/src/zoomOut.png new file mode 100644 index 0000000000000000000000000000000000000000..0eca4be3d8530c66b778c182f961b882b90949ed GIT binary patch literal 735 zcmV<50wDc~P)6|e z>}*+SHkOnP!a^bo7E1?FNb`r!*+;TBHeA>Nl5s{^@|`-8C#E0dVpXu>;uM}LgMjO2m7 z;|Px9W0nW_lgT)bMy$q2RHVfA#^~fBn{ZIfQf4OMB2Hjv#=c{578g*JrDGM&U>AmD z6fIDLV>l^hqEqtNjT>TWyTb@!y3Nv;=r?tEj@oXD7Fd*sPfQEQqp#R5=Y)I9K?9y( zd8wdLxQh8@5-qSEH`5yP!bmxh5Xwn|aC&u`a1B17t<1vB_==gu8Y_egKjBA__Ho#z zw9^|;4;SiOYjyv#`JEAPQz1dkX~r~ML%&uofPMCR&t^mxrrSZkfrko?8jX!$SAy6 zIQUy~otZ({DUQi{;r4+#8n2hwhBL(*HYf3W@d)#jnCi5KJeFduShJU6{o5CN)06K; z92TcsZ)_FQz6tlT2p6andAb%0Fm$t_Th@ISFc@Wr1+C?NlHcXKdHu1vF=s9dQiAk)a}dg`WJL&ail7f RrCtC4002ovPDHLkV1h|nq)gvBe2eWET8?8ie#Cpu z|D9#=71kpjsMD+1oOiwu3>LEX{>eEsiOp7zT);g4hi2Z!yLM?93Zg5*;`sh|M|3=67_cfOA%8uR%o!+A+Vt zTAKnV&Z0}<7V5$`imOq3k+q)q{i0D2{Qm=gV`8Dj%W+yzu1ca_sGFkN{TuGCF!96K zRLUq3^tDomunSG43@^dIxT8YE58wc*24eh>F!=i||1xle(8JTparyw?3mG^cjKVK? zrCi4>*5GGBO3T3%A!Da;Rk_53!dQw^cpaCOupcL=+X+01XM}s$m8D1uVSK|pYisI^ z&SZ3U9JVjF+KPYv(uSHTcbPqAtchutsFmh;1rb{%QA?Nb}2!|HWz%b7O!F}2w$dpCaW*|zKjKiQWcDB8ycKxt1k9%}0#VNZN;`zk2D$9N{Zuygs=l~x_>}p9YIukB(FiMR$`_~8@?1z{z7ViJmY!ddh~HXlCt6OjsWyBBY;0L# jZ4qLEF5H>l#Pt6FC))G-mKAi`00000NkvXXu0mjfM8)CJ literal 0 HcmV?d00001 diff --git a/src/zoomOut50.png b/src/zoomOut50.png new file mode 100644 index 0000000000000000000000000000000000000000..f753234c5699ad9fb3ebab0a2c670a871bb21173 GIT binary patch literal 1147 zcmV->1cdvEP))KwJ6@z4K1Q%VtJsj^84E~p6jLO>#>q8LqB zL?1K|eIN=vxIL)Rs7*RPxL{O_k!Tvlia{PwBko%i2t?5!vL&dXL@g*7N{h5~n9kpa zJ8X5PQ0VVvGXH!2_j~TS_nve9ks>6&HZt=%TkpbS~E6F{QWYsII|Ij6Xx@ z5lzDPxUiH#jB?Dtrv>Bg&?fwhnVlI8#wuLVP0%B{QwVuc#pqx7{j;0F8*!d++KYmR zVINw$8T>n1F{apHS~!KxI9z1B3eV{LYW#={_IG%GK*(qVOM%;kl^0X9aK$P+0skVT z(T<7=^R|})?-usC9RGG0Z^Db6Ks(a_^gu(g!5F*H7iXO&pp?!>PvL461@9Ni+@;+J zjfASTRXDgM!E10AQr!d|fa|d2WQJq$D{k#3@GPvv&{HvfSV(iD&k%YUe#0F~HyS6X z9Ipti%*fLKMnaKUhlS|fm6y-KYeKras*B($!eMH|wI?&~c$ix7HAbMOXNAEdM%z8= z3S|?gDw|j>yj5lP%5qOj;$WNY`lh%qt%VOMyf6&ha8?nE$VTz zaAQsc&#(1_M9UwIo~^3X2buPE%VcedB1uJWjgzL^*4X6ZN?bCB!bSKHhg zuf%(7Pv{r3{m3LqUPBa{&|y&ra5omiZ>irWl_26 zB=$=}9yheJIz-l{IB(vZ8Xu<8$|J7EBPG|(9-#+YD1`mKIF&Ld;j8^yt&{aaM4x=S zab Date: Fri, 9 Aug 2019 17:07:51 +0200 Subject: [PATCH 02/18] Delete image.py --- src/image.py | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 src/image.py diff --git a/src/image.py b/src/image.py deleted file mode 100644 index 3afca8e..0000000 --- a/src/image.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -******************************************************************************** -* CNIRevelator * -* * -* Desc: Image calculation for CNI printing * -* * -* 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 . * -******************************************************************************** -""" - From b3f6e6337c7f001e4f850af530b2a4e1fc2f8c5b Mon Sep 17 00:00:00 2001 From: neox95 Date: Sat, 10 Aug 2019 16:59:17 +0200 Subject: [PATCH 03/18] Update .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index d0596f3..a3bf738 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ build/* dist/* +src/Tesseract-OCR4/* +src/downloads/* +src/config/* +src/logs/* From 0f952c8eff0954a83f4eed5a3e2d6554ff558e2d Mon Sep 17 00:00:00 2001 From: neox95 Date: Sat, 10 Aug 2019 19:59:16 +0200 Subject: [PATCH 04/18] OCR is now functionnal ! --- src/CNIRevelator.py | 2 +- src/globs.py | 1 + src/ihm.py | 40 +++++- src/main.py | 301 ++++++++++++++++++++++++++------------------ 4 files changed, 217 insertions(+), 127 deletions(-) diff --git a/src/CNIRevelator.py b/src/CNIRevelator.py index 9e9e088..3fe7fb0 100644 --- a/src/CNIRevelator.py +++ b/src/CNIRevelator.py @@ -31,7 +31,7 @@ import threading import traceback import psutil -import launcher # launcher.py +import launcher # launcher.py" import updater # updater.py import globs # globs.py import pytesseract # pytesseract.py diff --git a/src/globs.py b/src/globs.py index 674104c..295eb29 100644 --- a/src/globs.py +++ b/src/globs.py @@ -46,6 +46,7 @@ CNIRCryptoKey = '82Xh!efX3#@P~2eG' CNIRNewVersion = False CNIRConfig = CNIRFolder + '\\config\\conf.ig' +CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\' CNIRErrLog = CNIRFolder + '\\logs\\error.log' CNIRMainLog = CNIRFolder + '\\logs\\main.log' CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig' diff --git a/src/ihm.py b/src/ihm.py index 59c9d25..9c7622c 100644 --- a/src/ihm.py +++ b/src/ihm.py @@ -68,7 +68,45 @@ class DocumentAsk(Toplevel): self.choice = 1 def ok(self): self.destroy() + + +class OpenScanDialog(Toplevel): + def __init__(self, parent, text): + super().__init__(parent) + self.parent = parent + self.title('Validation de la MRZ détectée par OCR') + self.resizable(width=False, height=False) + self.termtext = Text(self, state='normal', width=45, height=2, wrap='none', font='Terminal 17', fg='#121f38') + self.termtext.grid(column=0, row=0, sticky='NEW', padx=5, pady=5) + self.termtext.insert('end', text + '\n') + self.button = Button(self, text='Valider', command=(self.valid)) + self.button.grid(column=0, row=1, sticky='S', padx=5, pady=5) + self.update() + hs = self.winfo_screenheight() + 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('%dx%d+%d+%d' % (w, h, x, y)) + if getattr(sys, 'frozen', False): + self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico') + else: + self.iconbitmap('id-card.ico') + + def valid(self): + self.parent.validatedtext = self.termtext.get('1.0', 'end') + texting = self.parent.validatedtext.replace(' ', '').replace('\r', '').split('\n') + for i in range(len(texting)): + for char in texting[i]: + if char not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789<': + showerror('Erreur de validation', 'La MRZ soumise contient des caractères invalides', parent=self) + self.parent.validatedtext = '' + + self.destroy() + class LoginDialog(Toplevel): def __init__(self, parent): @@ -192,7 +230,7 @@ class ResizeableCanvas(Canvas): self.height = event.height # rescale all the objects tagged with the "all" tag self.scale("all",0,0,wscale,hscale) - + ## Global Handler launcherWindowCur = LauncherWindow() diff --git a/src/main.py b/src/main.py index de45c84..558c6f9 100644 --- a/src/main.py +++ b/src/main.py @@ -35,6 +35,7 @@ import re import traceback import cv2 import PIL.Image, PIL.ImageTk +import os, shutil import ihm # ihm.py import logger # logger.py @@ -52,11 +53,12 @@ class mainWindow(Tk): self.initialize() def initialize(self): - self.mrzChar = '' + self.mrzChar = "" self.mrzDecided = False self.Tags = [] self.compliance = True self.corners = [] + self.validatedtext = "" # Hide during construction self.withdraw() @@ -89,6 +91,9 @@ class mainWindow(Tk): self.lecteur_ci.grid_rowconfigure(5, weight=1) # Fill the data sections + ttk.Label((self.lecteur_ci), text='Statut : ').grid(column=0, row=0, padx=5, pady=5) + self.STATUStxt = ttk.Label((self.lecteur_ci), text='EN ATTENTE', foreground="orange") + self.STATUStxt.grid(column=1, row=0, padx=5, pady=5) 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) @@ -146,19 +151,19 @@ class mainWindow(Tk): "INDIC" : self.indic, } - # The STATUS indicator - self.STATUT = ttk.Labelframe(self, text='Affichage de documents et statut') - self.STATUT.grid_columnconfigure(0, weight=1) - self.STATUT.grid_columnconfigure(1, weight=0) - self.STATUT.grid_rowconfigure(0, weight=1) - self.STATUT.grid_rowconfigure(1, weight=1) - self.STATUT.grid_rowconfigure(2, weight=1) - self.STATUT.frame = Frame(self.STATUT) - self.STATUT.frame.grid(column=0, row=0, sticky='NSEW') - self.STATUT.frame.grid_columnconfigure(0, weight=1) - self.STATUT.frame.grid_rowconfigure(0, weight=1) + # The the image viewer + self.imageViewer = ttk.Labelframe(self, text='Affichage et traitement de documents') + self.imageViewer.grid_columnconfigure(0, weight=1) + self.imageViewer.grid_columnconfigure(1, weight=0) + self.imageViewer.grid_rowconfigure(0, weight=1) + self.imageViewer.grid_rowconfigure(1, weight=1) + self.imageViewer.grid_rowconfigure(2, weight=1) + self.imageViewer.frame = Frame(self.imageViewer) + self.imageViewer.frame.grid(column=0, row=0, sticky='NSEW') + self.imageViewer.frame.grid_columnconfigure(0, weight=1) + self.imageViewer.frame.grid_rowconfigure(0, weight=1) # + toolbar - self.toolbar = ttk.Frame(self.STATUT) + self.toolbar = ttk.Frame(self.imageViewer) self.toolbar.grid_columnconfigure(0, weight=1) self.toolbar.grid_columnconfigure(1, weight=1) self.toolbar.grid_columnconfigure(2, weight=1) @@ -226,20 +231,20 @@ class mainWindow(Tk): self.toolbar.grid(column=0, row=2, padx=0, pady=0) # + image with scrollbars - self.STATUT.hbar = ttk.Scrollbar(self.STATUT, orient='horizontal') - self.STATUT.vbar = ttk.Scrollbar(self.STATUT, orient='vertical') - self.STATUT.hbar.grid(row=1, column=0, sticky="NSEW") - self.STATUT.vbar.grid(row=0, column=1, sticky="NSEW") + self.imageViewer.hbar = ttk.Scrollbar(self.imageViewer, orient='horizontal') + self.imageViewer.vbar = ttk.Scrollbar(self.imageViewer, orient='vertical') + self.imageViewer.hbar.grid(row=1, column=0, sticky="NSEW") + self.imageViewer.vbar.grid(row=0, column=1, sticky="NSEW") - self.STATUT.ZONE = ihm.ResizeableCanvas(self.STATUT.frame, bg=self["background"], xscrollcommand=(self.STATUT.hbar.set), - yscrollcommand=(self.STATUT.vbar.set)) - self.STATUT.ZONE.grid(sticky="NSEW") + self.imageViewer.ZONE = ihm.ResizeableCanvas(self.imageViewer.frame, bg=self["background"], xscrollcommand=(self.imageViewer.hbar.set), + yscrollcommand=(self.imageViewer.vbar.set)) + self.imageViewer.ZONE.grid(sticky="NSEW") - self.STATUT.hbar.config(command=self.STATUT.ZONE.xview) - self.STATUT.vbar.config(command=self.STATUT.ZONE.yview) + self.imageViewer.hbar.config(command=self.imageViewer.ZONE.xview) + self.imageViewer.vbar.config(command=self.imageViewer.ZONE.yview) - self.STATUSimg = self.STATUT.ZONE.create_image(0,0, image=None) - self.STATUStxt = self.STATUT.ZONE.create_text(0,0, text='', font='Times 24', fill='#FFBF00') + self.STATUSimg = self.imageViewer.ZONE.create_image(0,0, image=None, anchor="nw") + # The terminal to enter the MRZ self.terminal = ttk.Labelframe(self, text='Terminal de saisie de MRZ complète') @@ -289,7 +294,7 @@ class mainWindow(Tk): # All the items griding self.lecteur_ci.grid(column=2, row=0, sticky='EWNS', columnspan=1, padx=5, pady=5) - self.STATUT.grid(column=0, row=0, sticky='EWNS', columnspan=2, padx=5, pady=5) + self.imageViewer.grid(column=0, row=0, sticky='EWNS', columnspan=2, padx=5, pady=5) self.terminal.grid(column=0, row=2, sticky='EWNS', columnspan=2, padx=5, pady=5) self.terminal2.grid(column=0, row=1, sticky='EWNS', columnspan=2, padx=5, pady=5) self.monitor.grid(column=2, row=1, sticky='EWNS', columnspan=1, rowspan=2, padx=5, pady=5) @@ -341,32 +346,117 @@ class mainWindow(Tk): height, width = cv_img.shape # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate("EN ATTENTE", "#FFBF00", photo, setplace=True) - self.STATUT.imagePath = "background.png" - self.STATUT.imgZoom = 1 - self.STATUT.rotateCount = 0 - self.STATUT.blackhat = False + self.statusUpdate(photo, setplace=True) + self.imageViewer.imagePath = "background.png" + self.imageViewer.imgZoom = 1 + self.imageViewer.rotateCount = 0 + self.imageViewer.blackhat = False # Some bindings self.termtext.bind('', self.entryValidation) self.termtext.bind('<>', self.pasteValidation) self.speed731text.bind('', self.speedValidation) - self.STATUT.ZONE.bind("", self.rectangleSelectScan) + self.imageViewer.ZONE.bind("", self.rectangleSelectScan) logfile.printdbg('Initialization successful') - def statusUpdate(self, msg, color, image=None, setplace=False): + def statusUpdate(self, image=None, setplace=False): if image: - self.STATUT.image = image + self.imageViewer.image = image + self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image)) + self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all")) - self.STATUT.ZONE.itemconfigure(self.STATUSimg, image=(self.STATUT.image)) - self.STATUT.ZONE.itemconfigure(self.STATUStxt, text=(msg), fill=color) + def rectangleSelectScan(self, event): + canvas = event.widget + print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y)) + + self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)]) + if len(self.corners) == 2: + self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2) + print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1])) + if len(self.corners) > 2: + self.corners = [] + self.imageViewer.ZONE.delete(self.select) - if setplace: - self.STATUT.ZONE.move(self.STATUSimg, self.STATUT.ZONE.winfo_reqwidth() / 2, self.STATUT.ZONE.winfo_reqheight() / 2) - self.STATUT.ZONE.move(self.STATUStxt, self.STATUT.ZONE.winfo_reqwidth() / 2, self.STATUT.ZONE.winfo_reqheight() / 2) + def goOCRDetection(self): + cv_img = cv2.imread(self.imageViewer.imagePath) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if self.imageViewer.blackhat: + self.negativeScan() + if not self.imageViewer.blackhat: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + else: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Rotate + rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1) + cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) + # Resize + dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100)) + cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) + + x0 = int(self.corners[0][0]) + y0 = int(self.corners[0][1]) + x1 = int(self.corners[1][0]) + y1 = int(self.corners[1][1]) + + # print("crop at {}:{}, {}:{}".format(x0,y0,x1,y1)) + # print("real crop at {}:{}, {}:{}".format(x0+self.imageViewer.ZONE.winfo_height()/2, y0+self.imageViewer.ZONE.winfo_width()/2, x1+self.imageViewer.ZONE.winfo_height()/2, y1+self.imageViewer.ZONE.winfo_width()/2)) + + crop_img = cv_img[y0:y1, x0:x1] + + # Get the text by OCR + try: + os.environ['PATH'] = globs.CNIRTesser + os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata' + + image = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(crop_img)) + text = pytesseract.image_to_string(crop_img, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<') + + # manual validation + self.validatedtext = '' + invite = ihm.OpenScanDialog(self, text) + invite.transient(self) + invite.grab_set() + invite.focus_force() + self.wait_window(invite) + + print("text : {}".format(self.validatedtext)) + + self.mrzChar = "" + + # the regex + regex = re.compile("[^A-Z0-9<\n]") + self.validatedtext = re.sub(regex, '', self.validatedtext) + + # Get that + for char in self.validatedtext: + self.termtext.delete("1.0","end") + self.termtext.insert("1.0", self.mrzChar) + self.mrzChar = self.mrzChar + char + + self.stringValidation("") + print(self.mrzChar) + + # Reinstall tesseract + except pytesseract.TesseractNotFoundError as e: + try: + shutil.rmtree(globs.CNIRTesser) + except Exception: + pass + showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution'), parent=self) + logfile.printerr("Tesseract error : {}. Will be reinstallated".format(e)) + + # Tesseract error + except pytesseract.TesseractError as e: + logfile.printerr("Tesseract error : {}".format(e)) + showerror('Erreur de module OCR', ("Le module Tesseract a rencontré un problème : {}".format(e)), parent=self) - self.STATUT.ZONE.configure(scrollregion=self.STATUT.ZONE.bbox("all")) def stringValidation(self, keysym): # analysis @@ -516,43 +606,14 @@ class mainWindow(Tk): # Get that for char in lines: + self.termtext.delete("1.0","end") self.termtext.insert("1.0", self.mrzChar) self.mrzChar = self.mrzChar + char self.stringValidation("") + self.termtext.insert("1.0", self.mrzChar) return "break" - def goOCRDetection(self): - cv_img = cv2.imread(self.STATUT.imagePath) - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - if self.STATUT.blackhat: - self.negativeScan() - if not self.STATUT.blackhat: - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - else: - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Rotate - rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.STATUT.rotateCount*90),1) - cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) - # Resize - dim = (int(width * (self.STATUT.imgZoom + 100) / 100), int(height * (self.STATUT.imgZoom + 100) / 100)) - cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) - - x0 = int(self.corners[0][0]) + self.STATUT.ZONE.coords(self.STATUSimg)[0] - x1 = int(self.corners[0][1]) + self.STATUT.ZONE.coords(self.STATUSimg)[0] - y0 = int(self.corners[1][0]) + self.STATUT.ZONE.coords(self.STATUSimg)[1] - y1 = int(self.corners[1][1]) + self.STATUT.ZONE.coords(self.STATUSimg)[1] - - crop_img = cv_img[y0:y1, x0:x1] - cv2.imshow("cropped", crop_img) - cv2.waitKey(0) - def speedValidation(self, event): """ Computation of the speed entry @@ -587,10 +648,10 @@ class mainWindow(Tk): ('JPEG files', '*.jpg'), ('JPEG files', '*.jpeg'))) # Load an image using OpenCV - self.STATUT.imagePath = path - self.STATUT.imgZoom = 1 - self.STATUT.blackhat = False - self.STATUT.rotateCount = 0 + self.imageViewer.imagePath = path + self.imageViewer.imgZoom = 1 + self.imageViewer.blackhat = False + self.imageViewer.rotateCount = 0 cv_img = cv2.imread(path) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) # Get the image dimensions (OpenCV stores image data as NumPy ndarray) @@ -599,91 +660,79 @@ class mainWindow(Tk): height, width, channels_no = cv_img.shape # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate("", "#FFBF00", photo) + self.statusUpdate(photo) def zoomInScan50(self, quantity = 50): - self.STATUT.imgZoom += quantity + self.imageViewer.imgZoom += quantity self.resizeScan() def zoomOutScan50(self, quantity = 50): - self.STATUT.imgZoom -= quantity + self.imageViewer.imgZoom -= quantity self.resizeScan() def zoomInScan20(self, quantity = 20): - self.STATUT.imgZoom += quantity + self.imageViewer.imgZoom += quantity self.resizeScan() def zoomOutScan20(self, quantity = 20): - self.STATUT.imgZoom -= quantity + self.imageViewer.imgZoom -= quantity self.resizeScan() def zoomInScan(self, quantity = 1): - self.STATUT.imgZoom += quantity + self.imageViewer.imgZoom += quantity self.resizeScan() def zoomOutScan(self, quantity = 1): - self.STATUT.imgZoom -= quantity - self.resizeScan() - - def rotateLeft(self): - self.STATUT.rotateCount -= 1 - if self.STATUT.rotateCount < 0: - self.STATUT.rotateCount = 4 + self.imageViewer.imgZoom -= quantity self.resizeScan() def rotateRight(self): - self.STATUT.rotateCount += 1 - if self.STATUT.rotateCount > 4: - self.STATUT.rotateCount = 0 + self.imageViewer.rotateCount -= 1 + if self.imageViewer.rotateCount < 0: + self.imageViewer.rotateCount = 4 self.resizeScan() - def rotateRight1(self): - self.STATUT.rotateCount += 0.1 - if self.STATUT.rotateCount > 4: - self.STATUT.rotateCount = 0 + def rotateLeft(self): + self.imageViewer.rotateCount += 1 + if self.imageViewer.rotateCount > 4: + self.imageViewer.rotateCount = 0 self.resizeScan() def rotateLeft1(self): - self.STATUT.rotateCount -= 0.1 - if self.STATUT.rotateCount < 0: - self.STATUT.rotateCount = 4 + self.imageViewer.rotateCount += 0.01 + if self.imageViewer.rotateCount > 4: + self.imageViewer.rotateCount = 0 self.resizeScan() - def rectangleSelectScan(self, event): - canvas = event.widget - self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)]) - if len(self.corners) == 2: - self.select = self.STATUT.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2) - print("y") - if len(self.corners) > 2: - self.corners = [] - self.STATUT.ZONE.delete(self.select) - - print(self.corners) + def rotateRight1(self): + self.imageViewer.rotateCount -= 0.01 + if self.imageViewer.rotateCount < 0: + self.imageViewer.rotateCount = 4 + self.resizeScan() def negativeScan(self): # Load an image using OpenCV - cv_img = cv2.imread(self.STATUT.imagePath) + cv_img = cv2.imread(self.imageViewer.imagePath) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - if not self.STATUT.blackhat: - self.STATUT.blackhat = True + if not self.imageViewer.blackhat: + self.imageViewer.blackhat = True cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) cv_img = cv2.bitwise_not(cv_img) else: - self.STATUT.blackhat = False + self.imageViewer.blackhat = False self.resizeScan(cv_img) def resizeScan(self, cv_img = None): try: if not hasattr(cv_img, 'shape'): # Load an image using OpenCV - cv_img = cv2.imread(self.STATUT.imagePath) + cv_img = cv2.imread(self.imageViewer.imagePath) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - if self.STATUT.blackhat: + if self.imageViewer.blackhat: self.negativeScan() - if not self.STATUT.blackhat: + if not self.imageViewer.blackhat: # Get the image dimensions (OpenCV stores image data as NumPy ndarray) height, width, channels_no = cv_img.shape # Get the image dimensions (OpenCV stores image data as NumPy ndarray) @@ -694,23 +743,23 @@ class mainWindow(Tk): # Get the image dimensions (OpenCV stores image data as NumPy ndarray) height, width = cv_img.shape # Rotate - rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.STATUT.rotateCount*90),1) + rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1) cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) # Resize - dim = (int(width * (self.STATUT.imgZoom + 100) / 100), int(height * (self.STATUT.imgZoom + 100) / 100)) + dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100)) cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate("", "#FFBF00", photo) + self.statusUpdate( photo) except Exception as e: logfile.printerr("Error with opencv : {}".format(e)) traceback.print_exc(file=sys.stdout) try: # Reload an image using OpenCV - path = self.STATUT.imagePath - self.STATUT.imgZoom = 1 - self.STATUT.blackhat = False - self.STATUT.rotateCount = 0 + path = self.imageViewer.imagePath + self.imageViewer.imgZoom = 1 + self.imageViewer.blackhat = False + self.imageViewer.rotateCount = 0 cv_img = cv2.imread(path) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) # Get the image dimensions (OpenCV stores image data as NumPy ndarray) @@ -719,7 +768,7 @@ class mainWindow(Tk): height, width, channels_no = cv_img.shape # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate("", "#FFBF00", photo) + self.statusUpdate(photo) except Exception as e: logfile.printerr("Critical error with opencv : ".format(e)) traceback.print_exc(file=sys.stdout) @@ -837,9 +886,11 @@ class mainWindow(Tk): self.compliance = False if self.compliance == True: - self.statusUpdate("CONFORME", "chartreuse2") + self.STATUStxt["text"] = "CONFORME" + self.STATUStxt["foreground"] = "green" else: - self.statusUpdate("NON-CONFORME","red") + self.STATUStxt["text"] = "NON CONFORME" + self.STATUStxt["foreground"] = "red" return From 34625673a9b79d0f4011b90c394409b8a0053ad8 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sat, 10 Aug 2019 22:00:32 +0200 Subject: [PATCH 05/18] Some enhancements --- src/CNIRevelator.lnk | Bin 0 -> 893 bytes src/updater.py | 5 ++++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/CNIRevelator.lnk diff --git a/src/CNIRevelator.lnk b/src/CNIRevelator.lnk new file mode 100644 index 0000000000000000000000000000000000000000..3d7d4d0c9ccec41a54dc569ae9b19b23f8496634 GIT binary patch literal 893 zcmeZaU|?VrVFHp23W)KRQi-!P(CgG~=|4XZQM zGh<)~ftt_mzjGS9zy55H`P)~r0ZA5w(O}lW!~3A-2LVkj1L7Q@4J8cu3`Gpa40;R( zKnygHK?-P_5d$dP*!?$6Qvmq|Vw-D(D+5Ci+`e5v`!<37^BAjrQw09uv`-Icdj;5U zGC&)vfEYxB;s`{W05J$u0OHN zUW`*|QEFmo3@G3eld}`kQ$ft2)Uwo^#FG3XV?6^sGZYcM)CyqGIspBw#}I>sbYdt4 zhD$0igi3+(*y05yiZ3*AtAT|;0>pm{B7igq*{yE6r6fdtV8gyq#q%9V3Yx4jA4N#kTwhs2;L}`>$0}Dz+<_GgWeL` iiXK^@cm@zNcmT2XpSo{4b?%c_=}7jePILt6g#!R}q0#pM literal 0 HcmV?d00001 diff --git a/src/updater.py b/src/updater.py index b02ca37..7f8d54e 100644 --- a/src/updater.py +++ b/src/updater.py @@ -56,7 +56,7 @@ def createShortcut(path, target='', wDir='', icon=''): shortcut.close() else: shell = Dispatch('WScript.Shell') - shortcut = shell.CreateShortCut(path) + shortcut = shell.CreateShortCut(shell.SpecialFolders("Desktop") + r"\{}".format(path)) shortcut.Targetpath = target shortcut.WorkingDirectory = wDir if icon == '': @@ -284,6 +284,9 @@ def batch(credentials): shutil.rmtree(UPATH + 'temp') logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe') + # Make a shortcut + createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH) + launcherWindow.printmsg('Success !') # Cleanup From 9a7ab2e8eec1e0384fbd76c0599abffe43dfe23c Mon Sep 17 00:00:00 2001 From: neox95 Date: Sat, 10 Aug 2019 23:50:19 +0200 Subject: [PATCH 06/18] More enhancements for negative --- src/main.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main.py b/src/main.py index 558c6f9..1ce959e 100644 --- a/src/main.py +++ b/src/main.py @@ -382,7 +382,9 @@ class mainWindow(Tk): cv_img = cv2.imread(self.imageViewer.imagePath) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) if self.imageViewer.blackhat: - self.negativeScan() + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) + cv_img = cv2.bitwise_not(cv_img) if not self.imageViewer.blackhat: # Get the image dimensions (OpenCV stores image data as NumPy ndarray) height, width, channels_no = cv_img.shape @@ -405,20 +407,21 @@ class mainWindow(Tk): x1 = int(self.corners[1][0]) y1 = int(self.corners[1][1]) - # print("crop at {}:{}, {}:{}".format(x0,y0,x1,y1)) - # print("real crop at {}:{}, {}:{}".format(x0+self.imageViewer.ZONE.winfo_height()/2, y0+self.imageViewer.ZONE.winfo_width()/2, x1+self.imageViewer.ZONE.winfo_height()/2, y1+self.imageViewer.ZONE.winfo_width()/2)) - crop_img = cv_img[y0:y1, x0:x1] + + cv2.imshow("image", crop_img) # Get the text by OCR try: os.environ['PATH'] = globs.CNIRTesser os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata' - image = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(crop_img)) text = pytesseract.image_to_string(crop_img, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<') # manual validation + # the regex + regex = re.compile("[^A-Z0-9<\n]") + text = re.sub(regex, '', text) self.validatedtext = '' invite = ihm.OpenScanDialog(self, text) invite.transient(self) @@ -430,10 +433,6 @@ class mainWindow(Tk): self.mrzChar = "" - # the regex - regex = re.compile("[^A-Z0-9<\n]") - self.validatedtext = re.sub(regex, '', self.validatedtext) - # Get that for char in self.validatedtext: self.termtext.delete("1.0","end") @@ -730,7 +729,9 @@ class mainWindow(Tk): cv_img = cv2.imread(self.imageViewer.imagePath) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) if self.imageViewer.blackhat: - self.negativeScan() + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) + cv_img = cv2.bitwise_not(cv_img) if not self.imageViewer.blackhat: # Get the image dimensions (OpenCV stores image data as NumPy ndarray) From 576ad52a2dc81709b7c3bd7e5eb50e3e098c8e41 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 16:26:06 +0200 Subject: [PATCH 07/18] Finished OCR detection --- src/OCR.png | Bin 0 -> 512 bytes src/main.py | 473 +++++++++++++++++++++++++++++----------------------- 2 files changed, 260 insertions(+), 213 deletions(-) create mode 100644 src/OCR.png diff --git a/src/OCR.png b/src/OCR.png new file mode 100644 index 0000000000000000000000000000000000000000..6fc81ea2a85b09cf9473673458392d76071a1f04 GIT binary patch literal 512 zcmV+b0{{JqP)5uyY|TnpQaZFMgKfo)>`MY=0Ogk~Me^N$x%2PyL4^wc4M9P>4d4jq00+P> z(9nAm;0<^I?tw>O@zWpM2Cg;vvf%mvZnSS{)PYN2<{=*gkzTRKW~MpnMT71EBM;dV z5ITH9z31{7X-*LxAn_2~B5NW5h92KUb34%o=0c`+&`sb17?6t01ove=2YT6{CnzQQ z1Y?)?l+~(Cfpcp=6nN%9*BG{dPr-Pc$<%ceQ(()o^9gRLW9@^wgVObgEW*BEH?ZuY z9M0F8{#Xaf@C2aJmP#F44h`I;PEf~SkXP!KG3?@3bXHtvncxXZa0YFGXMqy(3VK3t z*LCV^A3M_;@a*AmUMB;ofeguSAa@>Lv4I$Tr)9Q>", self.goPageChoice) + self.toolbar.pageChooser['values'] = ('1') + self.toolbar.pageChooser.current(0) + self.toolbar.pageChooser.grid(column=16, row=0) self.toolbar.grid(column=0, row=2, padx=0, pady=0) @@ -309,6 +320,8 @@ class mainWindow(Tk): menubar.add_cascade(label='Fichier', menu=menu1) menu3 = Menu(menubar, tearoff=0) menu3.add_command(label='Commandes au clavier', command=(self.helpbox)) + menu3.add_command(label='Signaler un problème', command=(self.openIssuePage)) + menu3.add_separator() menu3.add_command(label='A propos de CNIRevelator', command=(self.infobox)) menubar.add_cascade(label='Aide', menu=menu3) self.config(menu=menubar) @@ -335,22 +348,14 @@ class mainWindow(Tk): self.update() self.deiconify() self.minsize(self.winfo_width(), self.winfo_height()) - - # Load an image using OpenCV - cv_img = cv2.imread("background.png") - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) - cv_img = cv2.blur(cv_img, (15, 15)) - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage - photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate(photo, setplace=True) - self.imageViewer.imagePath = "background.png" + + # Set image + self.imageViewer.image = None + self.imageViewer.imagePath = None self.imageViewer.imgZoom = 1 self.imageViewer.rotateCount = 0 self.imageViewer.blackhat = False + self.imageViewer.pagenumber = 0 # Some bindings self.termtext.bind('', self.entryValidation) @@ -363,98 +368,100 @@ class mainWindow(Tk): def statusUpdate(self, image=None, setplace=False): if image: self.imageViewer.image = image - self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image)) - self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all")) - - def rectangleSelectScan(self, event): - canvas = event.widget - print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y)) + self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image)) + self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all")) - self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)]) - if len(self.corners) == 2: - self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2) - print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1])) - if len(self.corners) > 2: - self.corners = [] - self.imageViewer.ZONE.delete(self.select) + def rectangleSelectScan(self, event): + if self.imageViewer.image: + canvas = event.widget + print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y)) + + self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)]) + if len(self.corners) == 2: + self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2) + print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1])) + if len(self.corners) > 2: + self.corners = [] + self.imageViewer.ZONE.delete(self.select) def goOCRDetection(self): - cv_img = cv2.imread(self.imageViewer.imagePath) - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - if self.imageViewer.blackhat: - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) - cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) - cv_img = cv2.bitwise_not(cv_img) - if not self.imageViewer.blackhat: - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - else: - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Rotate - rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1) - cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) - # Resize - dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100)) - cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) - - x0 = int(self.corners[0][0]) - y0 = int(self.corners[0][1]) - x1 = int(self.corners[1][0]) - y1 = int(self.corners[1][1]) - - crop_img = cv_img[y0:y1, x0:x1] - - cv2.imshow("image", crop_img) - - # Get the text by OCR - try: - os.environ['PATH'] = globs.CNIRTesser - os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata' - - text = pytesseract.image_to_string(crop_img, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<') - - # manual validation - # the regex - regex = re.compile("[^A-Z0-9<\n]") - text = re.sub(regex, '', text) - self.validatedtext = '' - invite = ihm.OpenScanDialog(self, text) - invite.transient(self) - invite.grab_set() - invite.focus_force() - self.wait_window(invite) - - print("text : {}".format(self.validatedtext)) - - self.mrzChar = "" - - # Get that - for char in self.validatedtext: - self.termtext.delete("1.0","end") - self.termtext.insert("1.0", self.mrzChar) - self.mrzChar = self.mrzChar + char - - self.stringValidation("") - print(self.mrzChar) - - # Reinstall tesseract - except pytesseract.TesseractNotFoundError as e: + if self.imageViewer.image: + cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber] + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if self.imageViewer.blackhat: + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) + cv_img = cv2.bitwise_not(cv_img) try: - shutil.rmtree(globs.CNIRTesser) - except Exception: - pass - showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution'), parent=self) - logfile.printerr("Tesseract error : {}. Will be reinstallated".format(e)) - - # Tesseract error - except pytesseract.TesseractError as e: - logfile.printerr("Tesseract error : {}".format(e)) - showerror('Erreur de module OCR', ("Le module Tesseract a rencontré un problème : {}".format(e)), parent=self) + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + except ValueError: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Rotate + rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1) + cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) + # Resize + dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100)) + cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) + + x0 = int(self.corners[0][0]) + y0 = int(self.corners[0][1]) + x1 = int(self.corners[1][0]) + y1 = int(self.corners[1][1]) + + crop_img = cv_img[y0:y1, x0:x1] + + cv2.imshow("image", crop_img) + + # Get the text by OCR + try: + os.environ['PATH'] = globs.CNIRTesser + os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata' + + text = pytesseract.image_to_string(crop_img, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<') + + # manual validation + # the regex + regex = re.compile("[^A-Z0-9<\n]") + text = re.sub(regex, '', text) + self.validatedtext = '' + invite = ihm.OpenScanDialog(self, text) + invite.transient(self) + invite.grab_set() + invite.focus_force() + self.wait_window(invite) + + print("text : {}".format(self.validatedtext)) + + self.mrzChar = "" + + # Get that + for char in self.validatedtext: + self.termtext.delete("1.0","end") + self.termtext.insert("1.0", self.mrzChar) + self.mrzChar = self.mrzChar + char + + self.stringValidation("") + print(self.mrzChar) + + # Reinstall tesseract + except pytesseract.TesseractNotFoundError as e: + try: + shutil.rmtree(globs.CNIRTesser) + except Exception: + pass + showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution'), parent=self) + logfile.printerr("Tesseract error : {}. Will be reinstallated".format(e)) + + # Tesseract error + except pytesseract.TesseractError as e: + logfile.printerr("Tesseract error : {}".format(e)) + showerror('Erreur de module OCR', ("Le module Tesseract a rencontré un problème : {}".format(e)), parent=self) def stringValidation(self, keysym): @@ -639,7 +646,10 @@ class mainWindow(Tk): self.speedResult.insert('end', text) self.speedResult['state'] = 'disabled' - + def goPageChoice(self, event): + self.imageViewer.pagenumber = int(self.toolbar.pageChooser.get()) - 1 + self.resizeScan() + def openingScan(self): path = '' path = filedialog.askopenfilename(parent=self, title='Ouvrir un scan de CNI...', filetypes=(('TIF files', '*.tif'), @@ -651,130 +661,160 @@ class mainWindow(Tk): self.imageViewer.imgZoom = 1 self.imageViewer.blackhat = False self.imageViewer.rotateCount = 0 - cv_img = cv2.imread(path) + self.imageViewer.pagenumber = 0 + + # Determine how many pages + self.toolbar.pageChooser['values'] = ('1') + total = len(cv2.imreadmulti(self.imageViewer.imagePath)[1]) + + for i in range(2, total + 1): + self.toolbar.pageChooser['values'] += tuple(str(i)) + + # Open the first page + cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber] cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape + + try: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + except ValueError: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) self.statusUpdate(photo) def zoomInScan50(self, quantity = 50): - self.imageViewer.imgZoom += quantity - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.imgZoom += quantity + self.resizeScan() def zoomOutScan50(self, quantity = 50): - self.imageViewer.imgZoom -= quantity - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.imgZoom -= quantity + self.resizeScan() def zoomInScan20(self, quantity = 20): - self.imageViewer.imgZoom += quantity - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.imgZoom += quantity + self.resizeScan() def zoomOutScan20(self, quantity = 20): - self.imageViewer.imgZoom -= quantity - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.imgZoom -= quantity + self.resizeScan() def zoomInScan(self, quantity = 1): - self.imageViewer.imgZoom += quantity - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.imgZoom += quantity + self.resizeScan() def zoomOutScan(self, quantity = 1): - self.imageViewer.imgZoom -= quantity - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.imgZoom -= quantity + self.resizeScan() def rotateRight(self): - self.imageViewer.rotateCount -= 1 - if self.imageViewer.rotateCount < 0: - self.imageViewer.rotateCount = 4 - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.rotateCount -= 1 + if self.imageViewer.rotateCount < 0: + self.imageViewer.rotateCount = 4 + self.resizeScan() def rotateLeft(self): - self.imageViewer.rotateCount += 1 - if self.imageViewer.rotateCount > 4: - self.imageViewer.rotateCount = 0 - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.rotateCount += 1 + if self.imageViewer.rotateCount > 4: + self.imageViewer.rotateCount = 0 + self.resizeScan() def rotateLeft1(self): - self.imageViewer.rotateCount += 0.01 - if self.imageViewer.rotateCount > 4: - self.imageViewer.rotateCount = 0 - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.rotateCount += 0.01 + if self.imageViewer.rotateCount > 4: + self.imageViewer.rotateCount = 0 + self.resizeScan() def rotateRight1(self): - self.imageViewer.rotateCount -= 0.01 - if self.imageViewer.rotateCount < 0: - self.imageViewer.rotateCount = 4 - self.resizeScan() + if self.imageViewer.image: + self.imageViewer.rotateCount -= 0.01 + if self.imageViewer.rotateCount < 0: + self.imageViewer.rotateCount = 4 + self.resizeScan() def negativeScan(self): - # Load an image using OpenCV - cv_img = cv2.imread(self.imageViewer.imagePath) - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - if not self.imageViewer.blackhat: - self.imageViewer.blackhat = True - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) - cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) - cv_img = cv2.bitwise_not(cv_img) - else: - self.imageViewer.blackhat = False - self.resizeScan(cv_img) + if self.imageViewer.image: + # Load an image using OpenCV + cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber] + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if not self.imageViewer.blackhat: + self.imageViewer.blackhat = True + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) + cv_img = cv2.bitwise_not(cv_img) + else: + self.imageViewer.blackhat = False + self.resizeScan(cv_img) def resizeScan(self, cv_img = None): - try: - if not hasattr(cv_img, 'shape'): - # Load an image using OpenCV - cv_img = cv2.imread(self.imageViewer.imagePath) - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - if self.imageViewer.blackhat: - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) - cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) - cv_img = cv2.bitwise_not(cv_img) - - if not self.imageViewer.blackhat: - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - else: - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width = cv_img.shape - # Rotate - rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1) - cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) - # Resize - dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100)) - cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) - # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage - photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate( photo) - except Exception as e: - logfile.printerr("Error with opencv : {}".format(e)) - traceback.print_exc(file=sys.stdout) + if self.imageViewer.image: try: - # Reload an image using OpenCV - path = self.imageViewer.imagePath - self.imageViewer.imgZoom = 1 - self.imageViewer.blackhat = False - self.imageViewer.rotateCount = 0 - cv_img = cv2.imread(path) - cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape - # Get the image dimensions (OpenCV stores image data as NumPy ndarray) - height, width, channels_no = cv_img.shape + if not hasattr(cv_img, 'shape'): + # Load an image using OpenCV + cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber] + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + if self.imageViewer.blackhat: + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0) + cv_img = cv2.bitwise_not(cv_img) + + try: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + except ValueError: + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Rotate + rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1) + cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height)) + # Resize + dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100)) + cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) - self.statusUpdate(photo) + self.statusUpdate( photo) except Exception as e: - logfile.printerr("Critical error with opencv : ".format(e)) + logfile.printerr("Error with opencv : {}".format(e)) traceback.print_exc(file=sys.stdout) - showerror("Erreur OpenCV (traitement d'images)", "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser") - self.initialize() + try: + # Reload an image using OpenCV + path = self.imageViewer.imagePath + self.imageViewer.imgZoom = 1 + self.imageViewer.blackhat = False + self.imageViewer.rotateCount = 0 + cv_img = cv2.imreadmulti(path) + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, channels_no = cv_img.shape + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage + photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) + self.statusUpdate(photo) + except Exception as e: + logfile.printerr("Critical error with opencv : ".format(e)) + traceback.print_exc(file=sys.stdout) + showerror("Erreur OpenCV (traitement d'images)", "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser") + self.initialize() def newEntry(self): self.initialize() @@ -784,24 +824,25 @@ class mainWindow(Tk): Tk().withdraw() showinfo('A propos de CNIRevelator', - ( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' + - "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer " + - "dans les termes de la GNU General Public License telle que publiée par " + - "la Free Software Foundation, dans sa version 3 ou " + - "ultérieure. " + "\n\n" + - "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois " + - "impliquer une quelconque garantie de " + - "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la " + - "GNU General Public License pour plus de détails à ce sujet. " + - "\n\n" + - "Vous devriez avoir reçu une copie de la GNU General Public License " + - "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à '. " + - "\n\n" + - "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004" + - "\n\n" + - "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019" + - "\n\n" + - "Le code source de ce programme est disponible sur Github à l'adresse .\n" + + ( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' + "Le fonctionnement de ce logiciel est conforme aux normes du document 9303 de l'OACI régissant les documents de voyages et d'identité" + '\n\n' + "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer " + "dans les termes de la GNU General Public License telle que publiée par " + "la Free Software Foundation, dans sa version 3 ou " + "ultérieure. " + "\n\n" + "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois " + "impliquer une quelconque garantie de " + "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la " + "GNU General Public License pour plus de détails à ce sujet. " + "\n\n" + "Vous devriez avoir reçu une copie de la GNU General Public License " + "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à '. " + "\n\n" + "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004" + "\n\n" + "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019" + "\n\n" + "Le code source de ce programme est disponible sur Github à l'adresse .\n" " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !" ), @@ -827,6 +868,12 @@ class mainWindow(Tk): ), parent=self) + + def openIssuePage(self): + self.openBrowser("https://github.com/neox95/CNIRevelator/issues") + + def openBrowser(self, url): + webbrowser.open_new(url) def computeSigma(self): """ From 44abeb9b0d76f87ad7621e39b02fe1463f9f4ed2 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 17:08:49 +0200 Subject: [PATCH 08/18] Preparing 3.0.7 release --- .gitignore | 1 + id-card.ico | Bin 1901 -> 0 bytes make.bat | 4 ++-- src/globs.py | 7 ++++--- src/mrz.py | 48 +++++++++++++++++++++++------------------------- 5 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 id-card.ico diff --git a/.gitignore b/.gitignore index a3bf738..93d25c3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ src/Tesseract-OCR4/* src/downloads/* src/config/* src/logs/* +signtool_8.1/* diff --git a/id-card.ico b/id-card.ico deleted file mode 100644 index efa86e4bc2d929c43599b2b48a2b3b15813b4f6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1901 zcmcgtYgE!_9De_RiVOtGL~CBU%*r*jZCP0XIh{5ytmUnlar@6ExfCkK^V z1wDQw(Ie;O8UU?r_$(GNlP{d+ zEkVc_bqjg#>|v5F0HrI(HD(84Q$+?4yy!Lf?98my=}}$L)>%Wpn+J##RW&EJZ`%p# z2qCr4D~hBb+5X&>`+>W+Lj6>4Wl?$hZOZB6wJI7hn@`U#UT^gLfLx81#MNpxx=!e) zVkgHIkYO!F6XmNc>uz1T7)mXUO_;<-J025vj?1B!{82Gssv=u_8x)_=c<7GXBd3CB zS;|aC!ymJ&*elW=KZd%}=??b4S;=unzS08jt}2Z(el3W{BB%`f%TQX!d7F{^U1&)s zE8Nh+?Ezf&ux8k%B;kI9Pw$vBuuyOkH;#3}4+?Ic(e}kZXh3&yoGO{prR&#@Nzf}0 zdZINXMd;sq&53Nq-A1cIr#aDCYcAKnyLk?gB7&3FsLx^bH%C{Z+Xn3gZ_WcLu1U)v zDSJ2)jx_iE!2>9%JYu2yZg8W<7bA>Wya0=MMG&}oZU>j$H&HP@8+mkRjUo7>-dNPo z3t@hV`5)aX2G;*nQ}cl0k;T)}X_g2s zp2JdK^fS#Y40`L^3Z2y#CXLs^2&tm3Fv!K~)fx^Gbq3Y8>$OI2SkH&;M6)|S!+J7n zt)9jiL2?w`KRJA7{KKR{7v|YrOf$d9d9B;`Jik<1bz&v@(2dlXTlER@u>cDEV0i{( z;q3A$uD~b(z9F|5@etDDmpxY zFc2fH*bVAjxy1txIaaEXHa#P!d;whVre0OMx9rO-2PEnf-n~P@=~DuajoX^->33tt zhsn9$)*gwzo?+$0Hr($YF&v)hF=M?SY0hnq9@pg-EkU=jb#nfOC}Z3L`1cHVGK+W_ zCE4G)x8~=o%YBc^O_b9NY~og^G$;RRg$E?z?;pHA?T@Vam6zaqu%t>h)bkQtxT8~@ zH%`ujMTK=?7iFbYmBMFl46z_sMv30^mJt>NXK(s}j{$b9z06 z+TfN9s4M7CpNC0;zj^2qlzMx-^im+eujYyafkDyZgj?D7r5WqtZ`akDx=_gWxh$tF z(=c40SzS&XN?GV8-s9_dZy__&JEVuxz^Asinl)c10G(7ogy2E!KN|H*h3)g?@y#G_ zT{rZ`$cG`FJGgeTNrHys`XI?WFg`m*X$5jK@o*$~ZIKN%XcAP~alTuoC($u1S4yn$ z2@fm*JgH|hbCcx?RGZ?VUDT)xjHNS}twZf4kPk@T{&BS`Y?{t|&z!I1$7V7Bbq2K< z_6!|te~MAJyIG@CWqFP#X!BrR*-}_^oAUo>%v_Gm0=?j3 Date: Sun, 11 Aug 2019 18:04:06 +0200 Subject: [PATCH 09/18] Update VERSIONS.LST --- VERSIONS.LST | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSIONS.LST b/VERSIONS.LST index 856ab09..e42db3d 100644 --- a/VERSIONS.LST +++ b/VERSIONS.LST @@ -1,2 +1,2 @@ # ver|url|checksum, and | as separator, one version per || -3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5|| +3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|ddb09d3de240bf4598f02146a9516c6ca149c9a4|| From da279e8f30dc58e591bf23337be220db210637ad Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 18:04:24 +0200 Subject: [PATCH 10/18] Update globs.py --- src/globs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/globs.py b/src/globs.py index 56622db..8f1c9a8 100644 --- a/src/globs.py +++ b/src/globs.py @@ -31,7 +31,7 @@ verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], v verstring = "{}.{}".format(version[0], version[1]) debug = True -changelog = "Version 3.0.7 \nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \ +changelog = "Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \ "Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ "Version 3.0.5 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'icône de l'exécutable afin de refléter le changement de version majeur accompli en 3.0\n\n" + \ "Version 3.0.4 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le système de mise-à-jour\n\n" + \ From 48b9045dc448fe895f318e0059a60937b9dd2533 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 19:02:01 +0200 Subject: [PATCH 11/18] Preparing 3.0.7 release --- make.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make.bat b/make.bat index bbe8cd2..5d6414b 100644 --- a/make.bat +++ b/make.bat @@ -10,7 +10,7 @@ call pyinstaller -w -D --exclude-module PyQt5 --bootloader-ignore-signals --add- copy LICENSE dist\CNIRevelator\LICENSE copy src\id-card.ico dist\CNIRevelator\id-card.ico -copy src\background.png dist\CNIRevelator\background.png +copy src\*.png dist\CNIRevelator\*.png signtool_8.1\signtool\signtool.exe sign /n "CNIRevelator by Adrien Bourmault (neox95)" dist\CNIRevelator\CNIRevelator.exe From b0274701dca8c3a15719092047ec2f24adfed2cb Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Sun, 11 Aug 2019 19:24:50 +0200 Subject: [PATCH 12/18] Update VERSIONS.LST --- VERSIONS.LST | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSIONS.LST b/VERSIONS.LST index e42db3d..eac2f9e 100644 --- a/VERSIONS.LST +++ b/VERSIONS.LST @@ -1,2 +1,2 @@ # ver|url|checksum, and | as separator, one version per || -3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|ddb09d3de240bf4598f02146a9516c6ca149c9a4|| +3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|9aea1627c0b75610225a02458d5705563ca0d6af|| From 767519b2a718b626dd5a15efa4647d76c9524c2c Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 19:44:16 +0200 Subject: [PATCH 13/18] Hotfix 3.0.8 --- src/globs.py | 8 +++++--- src/updater.py | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/globs.py b/src/globs.py index 8f1c9a8..4c16901 100644 --- a/src/globs.py +++ b/src/globs.py @@ -25,13 +25,15 @@ import os # CNIRevelator version -verType = "final release" -version = [3, 0, 7] +verType = "final release (hotfix)" +version = [3, 0, 8] verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType) verstring = "{}.{}".format(version[0], version[1]) debug = True -changelog = "Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \ +changelog = "Version 3.0.8 finale\nCorrection d'un bug du système de mise-à-jour'\n\n" + \ +"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ +"Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \ "Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ "Version 3.0.5 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'icône de l'exécutable afin de refléter le changement de version majeur accompli en 3.0\n\n" + \ "Version 3.0.4 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le système de mise-à-jour\n\n" + \ diff --git a/src/updater.py b/src/updater.py index 7f8d54e..940641b 100644 --- a/src/updater.py +++ b/src/updater.py @@ -369,13 +369,12 @@ def umain(): logfile.printerr(str(e)) launcherWindow.printmsg('Fail :{}'.format(e)) launcherWindow.printmsg('Starting...') - else: - tessInstall(globs.CNIRFolder, credentials) try: try: # EXECUTING THE UPDATE BATCH success = batch(credentials) + tessInstall(globs.CNIRFolder, credentials) except Exception as e: logfile.printerr("An error occured on the thread : " + str(traceback.format_exc())) launcherWindow.printmsg('ERROR : ' + str(e)) From 99aa337a4c49fd311d2776d31b4b24348cd2d8c6 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 21:16:20 +0200 Subject: [PATCH 14/18] Update system hotfix --- src/updater.py | 66 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/updater.py b/src/updater.py index 940641b..8ae9948 100644 --- a/src/updater.py +++ b/src/updater.py @@ -207,18 +207,24 @@ def tessInstall(PATH, credentials): logfile.printdbg('Preparing download of Tesseract OCR 4...') getTesseract = downloader.newdownload(credentials, tesseracturl, PATH + '\\downloads\\TsrtPackage.zip', "Tesseract 4 OCR Module").download() - # Unzip Tesseract - logfile.printdbg("Unzipping the package") - launcherWindow.printmsg('Installing the updates') - zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r') - zip_ref.extractall(PATH) - zip_ref.close() - - # Cleanup try: - os.remove(UPATH + '\\downloads\\TsrtPackage.zip') + # Unzip Tesseract + logfile.printdbg("Unzipping the package") + launcherWindow.printmsg('Installing the updates') + zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r') + zip_ref.extractall(PATH) + zip_ref.close() + # Cleanup + try: + os.remove(UPATH + '\\downloads\\TsrtPackage.zip') + except: + pass + return True + except: - pass + return False + else: + return True ## Main Batch Function def batch(credentials): @@ -374,7 +380,6 @@ def umain(): try: # EXECUTING THE UPDATE BATCH success = batch(credentials) - tessInstall(globs.CNIRFolder, credentials) except Exception as e: logfile.printerr("An error occured on the thread : " + str(traceback.format_exc())) launcherWindow.printmsg('ERROR : ' + str(e)) @@ -388,9 +393,39 @@ def umain(): else: logfile.printerr("An error occured. No effective update !") launcherWindow.printmsg('An error occured. No effective update !') - time.sleep(2) + time.sleep(2) + launcherWindow.exit() + return 0 + + if UPDATE_IS_MADE: + launcherWindow.exit() + return 0 + except: + logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc())) launcherWindow.exit() - return 0 + sys.exit(2) + return 2 + + try: + try: + # INSTALLING TESSERACT OCR + success = tessInstall(globs.CNIRFolder, credentials) + except Exception as e: + logfile.printerr("An error occured on the thread : " + str(traceback.format_exc())) + launcherWindow.printmsg('ERROR : ' + str(e)) + time.sleep(3) + launcherWindow.exit() + return 1 + + if success: + logfile.printdbg("Software is up-to-date !") + launcherWindow.printmsg('Software is up-to-date !') + else: + logfile.printerr("An error occured. No effective update !") + launcherWindow.printmsg('An error occured. No effective update !') + time.sleep(2) + launcherWindow.exit() + return 0 except: logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc())) @@ -398,5 +433,6 @@ def umain(): sys.exit(2) return 2 - return - + time.sleep(2) + launcherWindow.exit() + return 0 From 651ffd85f980c592db3ce1d1422b299ee0dada3f Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 21:27:33 +0200 Subject: [PATCH 15/18] Cosmetics --- src/globs.py | 2 +- src/main.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/globs.py b/src/globs.py index 4c16901..0757613 100644 --- a/src/globs.py +++ b/src/globs.py @@ -31,7 +31,7 @@ verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], v verstring = "{}.{}".format(version[0], version[1]) debug = True -changelog = "Version 3.0.8 finale\nCorrection d'un bug du système de mise-à-jour'\n\n" + \ +changelog = "Version 3.0.8 finale\nCorrectif : bug du système de mise-à-jour'\n\n" + \ "Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ "Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \ "Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ diff --git a/src/main.py b/src/main.py index 7ed55c6..27b0664 100644 --- a/src/main.py +++ b/src/main.py @@ -825,7 +825,7 @@ class mainWindow(Tk): showinfo('A propos de CNIRevelator', ( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' - "Le fonctionnement de ce logiciel est conforme aux normes du document 9303 de l'OACI régissant les documents de voyages et d'identité" + '\n\n' + "Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n" "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer " "dans les termes de la GNU General Public License telle que publiée par " "la Free Software Foundation, dans sa version 3 ou " @@ -836,14 +836,15 @@ class mainWindow(Tk): "GNU General Public License pour plus de détails à ce sujet. " "\n\n" "Vous devriez avoir reçu une copie de la GNU General Public License " - "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à '. " + "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à . " "\n\n" - "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004" + "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004." "\n\n" - "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019" + "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019." "\n\n" "Le code source de ce programme est disponible sur Github à l'adresse .\n" - " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !" + "Son fonctionnement est conforme aux normes et directives du document 9303 de l'OACI régissant les documents de voyages et d'identité." + '\n\n' + " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !\n\n" ), parent=self) From 45547df2606b5117f69a69d87fab95497793e410 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 21:30:51 +0200 Subject: [PATCH 16/18] Delete CNIRevelator.lnk --- src/CNIRevelator.lnk | Bin 893 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/CNIRevelator.lnk diff --git a/src/CNIRevelator.lnk b/src/CNIRevelator.lnk deleted file mode 100644 index 3d7d4d0c9ccec41a54dc569ae9b19b23f8496634..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 893 zcmeZaU|?VrVFHp23W)KRQi-!P(CgG~=|4XZQM zGh<)~ftt_mzjGS9zy55H`P)~r0ZA5w(O}lW!~3A-2LVkj1L7Q@4J8cu3`Gpa40;R( zKnygHK?-P_5d$dP*!?$6Qvmq|Vw-D(D+5Ci+`e5v`!<37^BAjrQw09uv`-Icdj;5U zGC&)vfEYxB;s`{W05J$u0OHN zUW`*|QEFmo3@G3eld}`kQ$ft2)Uwo^#FG3XV?6^sGZYcM)CyqGIspBw#}I>sbYdt4 zhD$0igi3+(*y05yiZ3*AtAT|;0>pm{B7igq*{yE6r6fdtV8gyq#q%9V3Yx4jA4N#kTwhs2;L}`>$0}Dz+<_GgWeL` iiXK^@cm@zNcmT2XpSo{4b?%c_=}7jePILt6g#!R}q0#pM From 79b0a21e0a5b18c51ea2b5ab29cc6ce444604b98 Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 21:54:28 +0200 Subject: [PATCH 17/18] Release 3.0.8 --- VERSIONS.LST | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSIONS.LST b/VERSIONS.LST index eac2f9e..64b66ab 100644 --- a/VERSIONS.LST +++ b/VERSIONS.LST @@ -1,2 +1,2 @@ # ver|url|checksum, and | as separator, one version per || -3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|9aea1627c0b75610225a02458d5705563ca0d6af|| +3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|9aea1627c0b75610225a02458d5705563ca0d6af||3.0.8|https://github.com/neox95/CNIRevelator/releases/download/3.0.8/CNIRevelator.zip|8e849f8fcb5c952c09bdd4eb3392456ec9c6cf8f|| From 89d95de3d8b2bc6e6d548d7d2c42f05d539306cd Mon Sep 17 00:00:00 2001 From: neox95 Date: Sun, 11 Aug 2019 23:57:30 +0200 Subject: [PATCH 18/18] Some cosmetics changes --- src/globs.py | 14 +++----------- src/main.py | 6 ++---- src/updater.py | 20 +++++++++++++++++++- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/globs.py b/src/globs.py index 0757613..42b1e6c 100644 --- a/src/globs.py +++ b/src/globs.py @@ -25,21 +25,13 @@ import os # CNIRevelator version -verType = "final release (hotfix)" -version = [3, 0, 8] +verType = "final release" +version = [3, 1, 0] verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType) verstring = "{}.{}".format(version[0], version[1]) debug = True -changelog = "Version 3.0.8 finale\nCorrectif : bug du système de mise-à-jour'\n\n" + \ -"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ -"Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \ -"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ -"Version 3.0.5 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'icône de l'exécutable afin de refléter le changement de version majeur accompli en 3.0\n\n" + \ -"Version 3.0.4 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le système de mise-à-jour\n\n" + \ -"Version 3.0.3 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le changelog\n- Correction d'une erreur avec la touche Suppr Arrière et Suppr causant une perte de données\n\n" + \ -"Version 3.0.2 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement d'icône de l'exécutable\n- Correction d'un bug affectant le logging\n- Correction d'un bug affectant la détection de documents\n- Et autres modifications mineures\n\n" + \ -"Version 3.0.1 \nMise-à-jour majeure avec les corrections suivantes :\n- Renouvellement de la signature numérique de l'exécutable\n- Amélioration de présentation du log en cas d'erreur\n- Refonte totale du code source et désobfuscation\n- Téléchargements en HTTPS fiables avec somme de contrôle\n- Nouveaux terminaux d'entrées : un rapide (731) et un complet\n- Détection des documents améliorée, possibilité de choix plus fin\nEt les regressions suivantes :\n- Suppression temporaire de la fonction de lecture OCR. Retour planifié pour une prochaine version" +changelog = "Version 3.1.0 \nMise-à-jour majeure avec les progressions suivantes :\n- Modifications cosmétiques de l'interface utilisateur\n- Stabilisation des changements effectués sur la version mineure 3.0 : interface utilisateur, OCR, VISA A et B, logging" CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8' CNIRFolder = os.getcwd() diff --git a/src/main.py b/src/main.py index 27b0664..b921838 100644 --- a/src/main.py +++ b/src/main.py @@ -93,7 +93,7 @@ class mainWindow(Tk): # Fill the data sections ttk.Label((self.lecteur_ci), text='Statut : ').grid(column=0, row=0, padx=5, pady=5) - self.STATUStxt = ttk.Label((self.lecteur_ci), text='EN ATTENTE', foreground="orange") + self.STATUStxt = ttk.Label((self.lecteur_ci), text='EN ATTENTE', font=("TkDefaultFont", 13, "bold"), foreground="orange", anchor=CENTER) self.STATUStxt.grid(column=1, row=0, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='Nom : ').grid(column=0, row=1, padx=5, pady=5) self.nom = ttk.Label((self.lecteur_ci), text=' ') @@ -291,7 +291,7 @@ class mainWindow(Tk): self.speed731text = Entry(self.speed731, font='Terminal 14') self.speed731text.grid(column=0, row=0, sticky='NEW', padx=5, pady=5) self.speedResult = Text((self.speed731), state='disabled', width=1, height=1, wrap='none', font='Terminal 14') - self.speedResult.grid(column=2, row=0, sticky='NEW') + self.speedResult.grid(column=2, row=0, sticky='NEW', padx=5, pady=5) # The monitor that indicates some useful infos self.monitor = ttk.Labelframe(self, text='Moniteur') @@ -415,8 +415,6 @@ class mainWindow(Tk): y1 = int(self.corners[1][1]) crop_img = cv_img[y0:y1, x0:x1] - - cv2.imshow("image", crop_img) # Get the text by OCR try: diff --git a/src/updater.py b/src/updater.py index 8ae9948..b41c16b 100644 --- a/src/updater.py +++ b/src/updater.py @@ -192,7 +192,6 @@ def getLatestVersion(credentials): return (finalver, finalurl, finalchecksum) -# XXX Warning : when tesseracturl is not found, it seems to hang and freeze def tessInstall(PATH, credentials): # Global Handlers logfile = logger.logCur @@ -208,6 +207,25 @@ def tessInstall(PATH, credentials): getTesseract = downloader.newdownload(credentials, tesseracturl, PATH + '\\downloads\\TsrtPackage.zip', "Tesseract 4 OCR Module").download() try: + # CHECKSUM + BUF_SIZE = 65536 # lets read stuff in 64kb chunks! + + sha1 = hashlib.sha1() + + with open(globs.CNIRFolder + '\\downloads\\TsrtPackage.zip', 'rb') as f: + while True: + data = f.read(BUF_SIZE) + if not data: + break + sha1.update(data) + + check = sha1.hexdigest() + logfile.printdbg("SHA1: {0}".format(check)) + + if not check == globs.CNIRTesserHash: + logfile.printerr("Checksum error") + return False + # Unzip Tesseract logfile.printdbg("Unzipping the package") launcherWindow.printmsg('Installing the updates')