Dieses Projekt dient der digitalen Umwandlung von Bildern in simulierte Darstellung aus Sicht eines rot-grün-blinden Menschen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Dyschromasie-Applikation.py 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. from PIL import Image, ImageTk
  2. import PIL
  3. import tkinter as tk
  4. from tkinter import filedialog, messagebox
  5. import cv2
  6. import numpy as np
  7. from Farbaenderung import gammaCorrection, reverseGammaCorrection
  8. root = tk.Tk()
  9. simGrad = tk.IntVar(root)
  10. class Dyschromasie:
  11. cb_image = np.array([]).astype('float64')
  12. sim_image = np.array([]).astype('uint8')
  13. def __init__(self, img_mat=np.array([]), rows=0, cols=0, kanaele=0,sim_faktor=0, sim_kind='d'):
  14. self.rows = rows
  15. self.cols = cols
  16. self.kanaele = kanaele
  17. self.img_mat = img_mat
  18. self.sim_faktor = sim_faktor
  19. self.sim_kind = sim_kind
  20. T = np.array([[0.31399022, 0.63951294, 0.04649755],
  21. [0.15537241, 0.75789446, 0.08670142],
  22. [0.01775239, 0.10944209, 0.87256922]])
  23. T_reversed = np.array([[5.47221206, -4.6419601, 0.16963708],
  24. [-1.1252419, 2.29317094, -0.1678952],
  25. [0.02980165, -0.19318073, 1.16364789]])
  26. def Simulate(self):
  27. if self.sim_kind == 'p':
  28. sim_mat = np.array([[(1 - self.sim_faktor), 1.05118294 * self.sim_faktor, -0.05116099 * self.sim_faktor],
  29. [0, 1, 0],
  30. [0, 0, 1]])
  31. elif self.sim_kind == 'd':
  32. sim_mat = np.array([[1, 0, 0],
  33. [0.9513092 * self.sim_faktor, (1 - self.sim_faktor), 0.04866992 * self.sim_faktor],
  34. [0, 0, 1]])
  35. else:
  36. sim_mat = np.array([[1, 0, 0],
  37. [0, 1, 0],
  38. [-0.86744736 * self.sim_faktor, 1.86727089 * self.sim_faktor, (1 - self.sim_faktor)]])
  39. # Gammakorrektur durchfuehren
  40. self.cb_image = np.copy(self.img_mat).astype('float64')
  41. for i in range(self.rows):
  42. for j in range(self.cols):
  43. for x in range(3):
  44. self.cb_image[i, j, x] = gammaCorrection(self.img_mat[i, j, x])
  45. # Einzelne Pixelwertberechnung
  46. for i in range(self.rows):
  47. for j in range(self.cols):
  48. self.cb_image[i, j] = self.T_reversed.dot(sim_mat).dot(self.T).dot(self.cb_image[i, j])
  49. self.sim_image = np.copy(self.cb_image)
  50. self.sim_image = self.sim_image.astype('uint8')
  51. # Rücktransformation der Gammawerte
  52. for i in range(self.rows):
  53. for j in range(self.cols):
  54. for x in range(3):
  55. self.sim_image[i, j, x] = reverseGammaCorrection(self.cb_image[i, j, x])
  56. return self.sim_image
  57. class AutoScrollbar(tk.Scrollbar):
  58. # A scrollbar that hides itself if it's not needed.
  59. # Only works if you use the grid geometry manager!
  60. def set(self, lo, hi):
  61. if float(lo) <= 0.0 and float(hi) >= 1.0:
  62. # grid_remove is currently missing from Tkinter!
  63. self.tk.call("grid", "remove", self)
  64. else:
  65. self.grid()
  66. tk.Scrollbar.set(self, lo, hi)
  67. def pack(self, **kw):
  68. raise TclError("cannot use pack with this widget")
  69. def place(self, **kw):
  70. raise TclError("cannot use place with this widget")
  71. class ScrollFrame:
  72. def __init__(self, master):
  73. self.vscrollbar = AutoScrollbar(master)
  74. self.vscrollbar.grid(row=0, column=1, sticky='ns')
  75. self.hscrollbar = AutoScrollbar(master, orient='horizontal')
  76. self.hscrollbar.grid(row=1, column=0, sticky='ew')
  77. self.canvas = tk.Canvas(master, yscrollcommand=self.vscrollbar.set,
  78. xscrollcommand=self.hscrollbar.set)
  79. self.canvas.grid(row=0, column=0, sticky='nsew')
  80. self.vscrollbar.config(command=self.canvas.yview)
  81. self.hscrollbar.config(command=self.canvas.xview)
  82. # make the canvas expandable
  83. master.grid_rowconfigure(0, weight=1)
  84. master.grid_columnconfigure(0, weight=1)
  85. # create frame inside canvas
  86. self.frame = tk.Frame(self.canvas)
  87. self.frame.rowconfigure(1, weight=1)
  88. self.frame.columnconfigure(1, weight=1)
  89. # update the frame
  90. self.frame.bind("<Configure>", self.reset_scrollregion)
  91. def reset_scrollregion(self, event):
  92. self.canvas.configure(scrollregion=self.canvas.bbox('all'))
  93. def update(self):
  94. self.canvas.create_window(0, 0, anchor='nw', window=self.frame)
  95. self.frame.update_idletasks()
  96. self.canvas.config(scrollregion=self.canvas.bbox("all"))
  97. if self.frame.winfo_reqwidth() != self.canvas.winfo_width():
  98. # update the canvas's width to fit the inner frame
  99. self.canvas.config(width = self.frame.winfo_reqwidth())
  100. if self.frame.winfo_reqheight() != self.canvas.winfo_height():
  101. # update the canvas's width to fit the inner frame
  102. self.canvas.config(height = self.frame.winfo_reqheight())
  103. root.title("Projekt Dyschromasie")
  104. SB = ScrollFrame(root)
  105. img = np.array([])
  106. rows = 0
  107. cols = 0
  108. kanaele = 0
  109. sim_pro = tk.IntVar(root)
  110. sim_deut = tk.IntVar(root)
  111. sim_tri = tk.IntVar(root)
  112. simulationsGradient = tk.Scale(SB.frame, from_=0, to_=100, variable=simGrad, orient='horizontal')
  113. simulationsGradient.grid(column= 0, row = 1, columnspan=10)
  114. def browse():
  115. # Auswahl des FilePaths
  116. try:
  117. path = tk.filedialog.askopenfilename(filetypes=[("Image File", '.jpg')])
  118. im = Image.open(path)
  119. except:
  120. tk.messagebox.showerror(title='Datenfehler', message='Kein Bild gefunden/ausgewählt')
  121. global simulateButton
  122. if len(path) > 0:
  123. simulateButton.config(state='active')
  124. # Anzeigen des Bildes
  125. tkimage = ImageTk.PhotoImage(im)
  126. myvar = tk.Label(SB.frame, image=tkimage)
  127. myvar.image = tkimage
  128. myvar.grid(columnspan=5)
  129. # Einspeichern der Path-Informationen
  130. global img, rows, cols, kanaele
  131. img = cv2.imread(path)
  132. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  133. rows, cols, kanaele = img.shape
  134. def simulate():
  135. global img, rows, cols, kanaele, sim_pro, sim_deut, sim_tri
  136. if sim_deut.get():
  137. d = Dyschromasie(img, rows, cols, kanaele, simGrad.get()/100, 'd')
  138. display_array_deut = np.copy(d.Simulate()).astype('uint8')
  139. T = tk.Text(SB.frame, height=1, width=15)
  140. T.grid(columnspan=5)
  141. print_string = "Deutranop(" + str(round(d.sim_faktor*100)) + "%)"
  142. T.insert('current', print_string)
  143. conv_SimulationPic_deut = ImageTk.PhotoImage(image=PIL.Image.fromarray(display_array_deut))
  144. sim_pic_deut = tk.Label(SB.frame, image=conv_SimulationPic_deut)
  145. sim_pic_deut.Image = conv_SimulationPic_deut
  146. sim_pic_deut.grid(columnspan=5)
  147. elif sim_tri.get():
  148. t = Dyschromasie(img, rows, cols, kanaele, simGrad.get()/100, 't')
  149. display_array_tri = np.copy(t.Simulate()).astype('uint8')
  150. T = tk.Text(SB.frame, height=1, width=15)
  151. T.grid(columnspan=5)
  152. print_string = "Tritanop(" + str(round(t.sim_faktor * 100)) + "%)"
  153. T.insert('current', print_string)
  154. conv_SimulationPic_tri = ImageTk.PhotoImage(image=PIL.Image.fromarray(display_array_tri))
  155. sim_pic_tri = tk.Label(SB.frame, image=conv_SimulationPic_tri)
  156. sim_pic_tri.Image = conv_SimulationPic_tri
  157. sim_pic_tri.grid(columnspan=5)
  158. elif sim_pro.get():
  159. p = Dyschromasie(img, rows, cols, kanaele, simGrad.get()/100, 'p')
  160. display_array_pro = np.copy(p.Simulate()).astype('uint8')
  161. T = tk.Text(SB.frame, height=1, width=15)
  162. T.grid(columnspan=5)
  163. print_string = "Protanop(" + str(round(p.sim_faktor * 100)) + "%)"
  164. T.insert('current', print_string)
  165. conv_SimulationPic_pro = ImageTk.PhotoImage(image=PIL.Image.fromarray(display_array_pro))
  166. sim_pic_pro = tk.Label(SB.frame, image=conv_SimulationPic_pro)
  167. sim_pic_pro.Image = conv_SimulationPic_pro
  168. sim_pic_pro.grid(columnspan=5)
  169. btn = tk.Button(SB.frame, text="Browse", width=25, command=browse, bg='light blue')
  170. btn.grid(column=0, row=0, columnspan=2)
  171. simulateButton = tk.Button(SB.frame, text="Simulate", width=25, command=simulate, bg='light blue')
  172. simulateButton.grid(column=1, row=0, columnspan=2)
  173. simulateButton.config(state='disabled')
  174. checkButton_p = tk.Checkbutton(SB.frame, text="Protanop", variable=sim_pro, onvalue=1, offvalue=0, height=5, width=20)
  175. checkButton_d = tk.Checkbutton(SB.frame, text="Deutanop", variable=sim_deut, onvalue=1, offvalue=0, height=5, width=20)
  176. checkButton_t = tk.Checkbutton(SB.frame, text="Tritanop", variable=sim_tri, onvalue=1, offvalue=0, height=5, width=20)
  177. checkButton_p.grid(column=0, row=2)
  178. checkButton_d.grid(column=1, row=2)
  179. checkButton_t.grid(column=2, row=2)
  180. SB.update()
  181. root.mainloop()