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 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. class Dyschromasie:
  8. global simGrad
  9. cb_image = np.array([]).astype('float64')
  10. sim_image = np.array([]).astype('uint8')
  11. def __init__(self, img_mat=np.array([]), rows=0, cols=0, kanaele=0):
  12. self.rows = rows
  13. self.cols = cols
  14. self.kanaele = kanaele
  15. self.img_mat = img_mat
  16. T = np.array([[0.31399022, 0.63951294, 0.04649755],
  17. [0.15537241, 0.75789446, 0.08670142],
  18. [0.01775239, 0.10944209, 0.87256922]])
  19. T_reversed = np.array([[5.47221206, -4.6419601, 0.16963708],
  20. [-1.1252419, 2.29317094, -0.1678952],
  21. [0.02980165, -0.19318073, 1.16364789]])
  22. def gammaCorrection(self, v):
  23. if v <= 0.04045 * 255:
  24. return float(((v / 255) / 12.92))
  25. elif v > 0.04045 * 255:
  26. return float((((v / 255) + 0.055) / 1.055) ** 2.4)
  27. def reverseGammaCorrection(self, v_reverse):
  28. if v_reverse <= 0.0031308:
  29. return int(255 * (12.92 * v_reverse))
  30. elif v_reverse > 0.0031308:
  31. return int(255 * (1.055 * v_reverse ** 0.41666 - 0.055))
  32. class Protanopie(Dyschromasie):
  33. sim_mat = np.array([[0, 1.05118294, -0.05116099],
  34. [0, 1, 0],
  35. [0, 0, 1]])
  36. def Simulate(self):
  37. # Gammakorrektur durchfuehren
  38. self.cb_image = np.copy(self.img_mat).astype('float64')
  39. for i in range(self.rows):
  40. for j in range(self.cols):
  41. for x in range(3):
  42. self.cb_image[i, j, x] = self.gammaCorrection(self.img_mat[i, j, x])
  43. # Einzelne Pixelwertberechnung
  44. for i in range(self.rows):
  45. for j in range(self.cols):
  46. self.cb_image[i, j] = np.flipud(
  47. self.T_reversed.dot(self.sim_mat).dot(self.T).dot(np.flipud(self.cb_image[i, j])))
  48. self.sim_image = np.copy(self.cb_image)
  49. self.sim_image = self.sim_image.astype('uint8')
  50. # Rücktransformation der Gammawerte
  51. for i in range(self.rows):
  52. for j in range(self.cols):
  53. for x in range(3):
  54. self.sim_image[i, j, x] = self.reverseGammaCorrection(self.cb_image[i, j, x])
  55. # Anpassung fuer den Slider
  56. if(simGrad.get() != 0):
  57. for i in range(rows):
  58. for j in range(cols):
  59. for x in range(3):
  60. if self.sim_image[i, j, x] > img[i, j, x]:
  61. self.sim_image[i, j, x] = img[i, j, x] + abs(self.sim_image[i, j, x] - img[i, j, x])* (simGrad.get()/100)
  62. elif self.sim_image[i, j, x] < img[i, j, x]:
  63. self.sim_image[i, j, x] = self.sim_image[i, j, x] + abs(img[i, j, x] - self.sim_image[i, j, x])* (simGrad.get()/100)
  64. return self.sim_image
  65. class Deuteranopie(Dyschromasie):
  66. sim_mat = np.array([[1, 0, 0],
  67. [0.9513092, 0, 0.04866992],
  68. [0, 0, 1]])
  69. def Simulate(self):
  70. # Gammakorrektur durchfuehren
  71. self.cb_image = np.copy(self.img_mat).astype('float64')
  72. for i in range(self.rows):
  73. for j in range(self.cols):
  74. for x in range(3):
  75. self.cb_image[i, j, x] = self.gammaCorrection(self.img_mat[i, j, x])
  76. # Einzelne Pixelwertberechnung
  77. for i in range(self.rows):
  78. for j in range(self.cols):
  79. self.cb_image[i, j] = np.flipud(
  80. self.T_reversed.dot(self.sim_mat).dot(self.T).dot(np.flipud(self.cb_image[i, j])))
  81. self.sim_image = np.copy(self.cb_image)
  82. self.sim_image = self.sim_image.astype('uint8')
  83. # Rücktransformation der Gammawerte
  84. for i in range(self.rows):
  85. for j in range(self.cols):
  86. for x in range(3):
  87. self.sim_image[i, j, x] = self.reverseGammaCorrection(self.cb_image[i, j, x])
  88. # Anpassung fuer den Slider
  89. if (simGrad.get() != 0):
  90. for i in range(rows):
  91. for j in range(cols):
  92. for x in range(3):
  93. if self.sim_image[i, j, x] > img[i, j, x]:
  94. self.sim_image[i, j, x] = img[i, j, x] + abs(self.sim_image[i, j, x] - img[i, j, x]) * (simGrad.get() / 100)
  95. elif self.sim_image[i, j, x] < img[i, j, x]:
  96. self.sim_image[i, j, x] = self.sim_image[i, j, x] + abs(img[i, j, x] - self.sim_image[i, j, x]) * (simGrad.get() / 100)
  97. return self.sim_image
  98. class Tritanopie(Dyschromasie):
  99. sim_mat = np.array([[1, 0, 0],
  100. [0, 1, 0],
  101. [-0.86744736, 1.86727089, 0]])
  102. def Simulate(self):
  103. # Gammakorrektur durchfuehren
  104. self.cb_image = np.copy(self.img_mat).astype('float64')
  105. for i in range(self.rows):
  106. for j in range(self.cols):
  107. for x in range(3):
  108. self.cb_image[i, j, x] = self.gammaCorrection(self.img_mat[i, j, x])
  109. # Einzelne Pixelwertberechnung
  110. for i in range(self.rows):
  111. for j in range(self.cols):
  112. self.cb_image[i, j] = np.flipud(
  113. self.T_reversed.dot(self.sim_mat).dot(self.T).dot(np.flipud(self.cb_image[i, j])))
  114. self.sim_image = np.copy(self.cb_image)
  115. self.sim_image = self.sim_image.astype('uint8')
  116. # Rücktransformation der Gammawerte
  117. for i in range(self.rows):
  118. for j in range(self.cols):
  119. for x in range(3):
  120. self.sim_image[i, j, x] = self.reverseGammaCorrection(self.cb_image[i, j, x])
  121. # Anpassung fuer den Slider
  122. if (simGrad.get() != 0):
  123. for i in range(rows):
  124. for j in range(cols):
  125. for x in range(3):
  126. if self.sim_image[i, j, x] > img[i, j, x]:
  127. self.sim_image[i, j, x] = img[i, j, x] + abs(self.sim_image[i, j, x] - img[i, j, x]) * (simGrad.get() / 100)
  128. elif self.sim_image[i, j, x] < img[i, j, x]:
  129. self.sim_image[i, j, x] = self.sim_image[i, j, x] + abs(img[i, j, x] - self.sim_image[i, j, x]) * (simGrad.get() / 100)
  130. return self.sim_image
  131. root = tk.Tk()
  132. root.title("Projekt Dyschromasie")
  133. img = np.array([])
  134. rows = 0
  135. cols = 0
  136. kanaele = 0
  137. sim_pro = tk.IntVar(root)
  138. sim_deut = tk.IntVar(root)
  139. sim_tri = tk.IntVar(root)
  140. simGrad = tk.IntVar(root)
  141. simulationsGradient = tk.Scale(root, from_=0, to_=100, variable=simGrad, orient='horizontal')
  142. simulationsGradient.grid(column= 0, row = 1, columnspan=10)
  143. def browse():
  144. # Auswahl des FilePaths
  145. try:
  146. path = tk.filedialog.askopenfilename(filetypes=[("Image File", '.jpg')])
  147. im = Image.open(path)
  148. except:
  149. tk.messagebox.showerror(title='Datenfehler', message='Kein Bild gefunden/ausgewählt')
  150. global simulateButton
  151. if len(path) > 0:
  152. simulateButton.config(state='active')
  153. # Anzeigen des Bildes
  154. tkimage = ImageTk.PhotoImage(im)
  155. myvar = tk.Label(root, image=tkimage)
  156. myvar.image = tkimage
  157. myvar.grid(columnspan=5)
  158. # Einspeichern der Path-Informationen
  159. global img, rows, cols, kanaele
  160. img = cv2.imread(path)
  161. rows, cols, kanaele = img.shape
  162. def simulate():
  163. global img, rows, cols, kanaele, sim_pro, sim_deut, sim_tri
  164. if sim_deut.get():
  165. d = Deuteranopie(img, rows, cols, kanaele)
  166. display_array_deut = cv2.cvtColor(np.copy(d.Simulate()), cv2.COLOR_BGR2RGB)
  167. T = tk.Text(root, height=1, width=15)
  168. T.grid(columnspan=5)
  169. T.insert('current', "Deutranopie:")
  170. conv_SimulationPic_deut = ImageTk.PhotoImage(image=PIL.Image.fromarray(display_array_deut))
  171. sim_pic_deut = tk.Label(root, image=conv_SimulationPic_deut)
  172. sim_pic_deut.Image = conv_SimulationPic_deut
  173. sim_pic_deut.grid(columnspan=5)
  174. elif sim_tri.get():
  175. t = Tritanopie(img, rows, cols, kanaele)
  176. display_array_tri = cv2.cvtColor(np.copy(t.Simulate()), cv2.COLOR_BGR2RGB)
  177. T = tk.Text(root, height=1, width=15)
  178. T.grid(columnspan=5)
  179. T.insert('current', "Tritanopie:")
  180. conv_SimulationPic_tri = ImageTk.PhotoImage(image=PIL.Image.fromarray(display_array_tri))
  181. sim_pic_tri = tk.Label(root, image=conv_SimulationPic_tri)
  182. sim_pic_tri.Image = conv_SimulationPic_tri
  183. sim_pic_tri.grid(columnspan=5)
  184. elif sim_pro.get():
  185. p = Protanopie(img, rows, cols, kanaele)
  186. display_array_pro = cv2.cvtColor(np.copy(p.Simulate()), cv2.COLOR_BGR2RGB)
  187. T = tk.Text(root, height=1, width=15)
  188. T.grid(columnspan=5)
  189. T.insert('current', "Protanopie:")
  190. conv_SimulationPic_pro = ImageTk.PhotoImage(image=PIL.Image.fromarray(display_array_pro))
  191. sim_pic_pro = tk.Label(root, image=conv_SimulationPic_pro)
  192. sim_pic_pro.Image = conv_SimulationPic_pro
  193. sim_pic_pro.grid(columnspan=5)
  194. btn = tk.Button(root, text="Browse", width=25, command=browse, bg='light blue')
  195. btn.grid(column=0, row=0, columnspan=2)
  196. simulateButton = tk.Button(root, text="Simulate", width=25, command=simulate, bg='light blue')
  197. simulateButton.grid(column=1, row=0, columnspan=2)
  198. simulateButton.config(state='disabled')
  199. checkButton_p = tk.Checkbutton(root, text="Protanop", variable=sim_pro, onvalue=1, offvalue=0, height=5, width=20)
  200. checkButton_d = tk.Checkbutton(root, text="Deutanop", variable=sim_deut, onvalue=1, offvalue=0, height=5, width=20)
  201. checkButton_t = tk.Checkbutton(root, text="Tritanop", variable=sim_tri, onvalue=1, offvalue=0, height=5, width=20)
  202. checkButton_p.grid(column=0, row=2)
  203. checkButton_d.grid(column=1, row=2)
  204. checkButton_t.grid(column=2, row=2)
  205. root.mainloop()