app4Stoma.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. # https://www.notabug.org/Tonypythony/
  2. # conda create -n STOMAAPP ### C:\Users\123\miniconda3\envs
  3. ### conda activate STOMAAPP
  4. # pip install matplotlib
  5. # pip install Pillow
  6. # pip install --upgrade cx_Freeze
  7. ### conda deactivate
  8. from pathlib import Path
  9. from tkinter import filedialog
  10. from tkinter import *
  11. from PIL import ImageTk, Image
  12. from time import time
  13. from pylab import imshow, array, ginput, close # Matplotlib по умолчанию использует формат RGB
  14. d = 10 # mm
  15. def get_d():
  16. while True:
  17. try:
  18. d = int(input("Please input d = "))
  19. return d
  20. except ValueError:
  21. print("It's not a number!")
  22. mes = input("Size of scale = 10 mm = 1 cm? If 'yes' press 'Enter', if 'not' print 'not'? ")
  23. if mes == 'not':
  24. get_d()
  25. d_sqr = d**2
  26. root = Tk()
  27. current_dir = Path.cwd() # путь текущей директории
  28. filename = filedialog.askopenfilename(initialdir = current_dir, # initialdir = "/run/media/rick/DATA/Kazahi"
  29. title = "Select imagefile", filetypes = (("JPG files", "*.JPG"),("jpeg files", "*.jpeg"),
  30. ("jpg files", "*.jpg"),("png files", "*.png"),
  31. ("bmp files", "*.bmp"),("all files", "*.*")))
  32. x_size_screen = int(root.winfo_screenwidth()/3)
  33. y_size_screen = int(root.winfo_screenheight()/3)
  34. image = Image.open(filename).convert('RGB')
  35. def color_of_points(img):
  36. im = array(image)
  37. imshow(im)
  38. print('\nPlease click 2 points to determine the scale of the image')
  39. x = ginput(2)
  40. y = [(int(p), int(q)) for p, q in x]
  41. a = [y[0][0], y[0][1], y[1][0], y[1][1]]
  42. clr1 = img.getpixel(y[0])
  43. clr2 = img.getpixel(y[1])
  44. print('Color 1 point {} is'.format((a[0],a[1])), clr1) # color of the first selected pixel
  45. print('Color 2 point {} is'.format((a[2],a[3])), clr2) # color of the second selected pixel
  46. global D_sqr
  47. D_sqr = int((a[0]-a[2])**2+(a[1]-a[3])**2) # distance^2 between selected pixels
  48. print('\nPlease click 2 points to crop colors: (left, upper, right, lower)')
  49. x = ginput(2)
  50. y = [(int(p), int(q)) for p, q in x]
  51. a = [y[0][0], y[0][1], y[1][0], y[1][1]]
  52. print(a)
  53. im_crop = image.crop((a[0], a[1], a[2], a[3]))
  54. global x_crop, y_crop
  55. x_crop, y_crop = im_crop.size[0], im_crop.size[1]
  56. imshow(im_crop)
  57. print('\nPlease click 2 points to for detect colors')
  58. x = ginput(2)
  59. y = [(int(p), int(q)) for p, q in x]
  60. clr1 = image.getpixel(y[0])
  61. clr2 = image.getpixel(y[1])
  62. close() # закрыть окно с выбором точек
  63. print('Color 1 point is', clr1) # color of the first selected pixel
  64. print('Color 2 point is', clr2) # color of the second selected pixel
  65. return im_crop
  66. image = color_of_points(image)
  67. k = d_sqr / D_sqr # коэффициент масштаба для перевода пикселей в мм
  68. s_1 = image.size[0]*image.size[1]
  69. image = image.resize((x_size_screen,y_size_screen))
  70. s_resize = image.size[0]*image.size[1]
  71. x_size_root = int(x_size_screen*1.5)
  72. y_size_root = int(y_size_screen*2.1)
  73. root.geometry('{}x{}'.format(x_size_root,y_size_root))
  74. canvas = Canvas(root,width=x_size_screen,height=y_size_screen)
  75. canvas.pack()
  76. pilimage = ImageTk.PhotoImage(image)
  77. imagesprite = canvas.create_image(0,0,image=pilimage, anchor=NW)
  78. container = Frame() # создаём контейнер на главном окне для расположения кнопок и полей ввода
  79. container.pack(side='top', fill='both', expand=True)
  80. redM = 255 # max
  81. redL = 0 # min
  82. greenM = 255 # max
  83. greenL = 0 # min
  84. blueM = 255 # max
  85. blueL = 0 # min
  86. ########################################################################
  87. lbl1 = Label(container, text="RedMax = ")
  88. lbl1.grid(column=6, row=1)
  89. def get_val_motion1(event):
  90. global redM
  91. redM = scal1.get()
  92. scal1 = Scale(container, orient=HORIZONTAL, length=int(image.size[0]), from_=0, to=255,
  93. tickinterval=20, resolution=1)
  94. scal1.bind("<B1-Motion>", get_val_motion1)
  95. scal1.grid(column=7, row=1)
  96. ########################################################################
  97. lbl2 = Label(container, text="RedMin = ")
  98. lbl2.grid(column=6, row=2)
  99. def get_val_motion2(event_1):
  100. global redL
  101. redL = scal2.get()
  102. scal2 = Scale(container, orient=HORIZONTAL, length=int(image.size[0]), from_=0, to=255,
  103. tickinterval=20, resolution=1)
  104. scal2.bind("<B1-Motion>", get_val_motion2)
  105. scal2.grid(column=7, row=2)
  106. ########################################################################
  107. lbl3 = Label(container, text="GreenMax = ")
  108. lbl3.grid(column=6, row=3)
  109. def get_val_motion3(event):
  110. global greenM
  111. greenM = sca3.get()
  112. sca3 = Scale(container, orient=HORIZONTAL, length=int(image.size[0]), from_=0, to=255,
  113. tickinterval=20, resolution=1)
  114. sca3.bind("<B1-Motion>", get_val_motion3)
  115. sca3.grid(column=7, row=3)
  116. ########################################################################
  117. lbl4 = Label(container, text="GreenMin = ")
  118. lbl4.grid(column=6, row=4)
  119. def get_val_motion4(event_1):
  120. global greenL
  121. greenL = scal4.get()
  122. scal4 = Scale(container, orient=HORIZONTAL, length=int(image.size[0]), from_=0, to=255,
  123. tickinterval=20, resolution=1)
  124. scal4.bind("<B1-Motion>", get_val_motion4)
  125. scal4.grid(column=7, row=4)
  126. ########################################################################
  127. lbl5 = Label(container, text="BlueMax = ")
  128. lbl5.grid(column=6, row=5)
  129. def get_val_motion5(event):
  130. global blueM
  131. blueM = scal5.get()
  132. scal5 = Scale(container, orient=HORIZONTAL, length=int(image.size[0]), from_=0, to=255,
  133. tickinterval=20, resolution=1)
  134. scal5.bind("<B1-Motion>", get_val_motion5)
  135. scal5.grid(column=7, row=5)
  136. ########################################################################
  137. lbl6 = Label(container, text="BlueMin = ")
  138. lbl6.grid(column=6, row=6)
  139. def get_val_motion6(event_1):
  140. global blueL
  141. blueL = scal6.get()
  142. scal6 = Scale(container, orient=HORIZONTAL, length=int(image.size[0]), from_=0, to=255,
  143. tickinterval=20, resolution=1)
  144. scal6.bind("<B1-Motion>", get_val_motion6)
  145. scal6.grid(column=7, row=6)
  146. ########################################################################
  147. def my_callback3(): # показывает исходную фотографию
  148. global pilimage
  149. pilimage = ImageTk.PhotoImage(image)
  150. global imagesprite
  151. imagesprite = canvas.create_image(0,0,image=pilimage, anchor=NW)
  152. button3 = Button(container , text="Source" , command=my_callback3)
  153. button3.grid(row=3 ,column=0)
  154. ########################################################################
  155. def my_callback6(): # открыть новое изображение
  156. global filename
  157. filename = filedialog.askopenfilename(initialdir = current_dir,
  158. title = "Select imagefile", filetypes = (("JPG files", "*.JPG"),("jpeg files", "*.jpeg"),
  159. ("jpg files", "*.jpg"),("png files", "*.png"),
  160. ("bmp files", "*.bmp"),("all files", "*.*")))
  161. global image
  162. image = Image.open(filename).convert('RGB')
  163. image = color_of_points(image)
  164. image = image.resize((x_size_screen,y_size_screen))
  165. global pilimage
  166. pilimage = ImageTk.PhotoImage(image)
  167. global imagesprite
  168. imagesprite = canvas.create_image(0,0,image=pilimage, anchor=NW)
  169. button6 = Button(container , text="Open New Image" , command=my_callback6)
  170. button6.grid(row=4 ,column=0)
  171. ########################################################################
  172. def my_callback7(): # главная функция - для расчёта изображения
  173. N = 0 # счётчик
  174. new_im = []
  175. start = time() # для тестирования скорости работы
  176. for i in range(image.size[0]):
  177. for j in range(image.size[1]):
  178. if (image.getpixel((i,j))[0] >= redL) and (image.getpixel((i,j))[0] <= redM) \
  179. and (image.getpixel((i,j))[1] >= greenL) and (image.getpixel((i,j))[1] <= greenM) \
  180. and (image.getpixel((i,j))[2] >= blueL) and (image.getpixel((i,j))[2] <= blueM):
  181. N += 1
  182. new_im.append((i,j,image.getpixel((i,j))))
  183. area = N*s_1/s_resize
  184. print("\nApproximate result: {:.2} mm^2 = {:.3} cm^2".format(s_1*k, s_1*k*0.01))
  185. print("\nAccurate result: {:.2} mm^2 = {:.3} cm^2\n".format(area*k, area*k*0.01))
  186. print("RedL = {}; RedM = {}, \nGreenL = {}; GreenM = {},\
  187. \nBlueL = {}; BlueM = {}".format(redL, redM, greenL, greenM, blueL, blueM))
  188. print("Time: {0:.3f} s".format(float(round((time()-start)*1e3)/1e3))) # для тестирования скорости работы
  189. global new_image # нужно для возможности сохранения в дальнейшем
  190. new_image = Image.new("RGB", (image.size[0], image.size[1]))
  191. for i in range(len(new_im)):
  192. new_image.putpixel((new_im[i][0], new_im[i][1]), new_im[i][2])
  193. global pilimage
  194. pilimage = ImageTk.PhotoImage(new_image)
  195. global imagesprite
  196. imagesprite = canvas.create_image(0,0,image=pilimage, anchor=NW)
  197. button7 = Button(container , text="Result" , command=my_callback7)
  198. button7.grid(row=1 ,column=0)
  199. ########################################################################
  200. def my_callback4(): # сохраняет результат
  201. file_name = filedialog.asksaveasfilename(initialdir = current_dir,
  202. filetypes = (("png files", "*.png"),
  203. ("jpg files", "*.jpg"),
  204. ("bmp files", "*.bmp"),("all files", "*.*")), defaultextension="")
  205. global new_image
  206. new_image = new_image.resize((x_crop, y_crop)) # сохраняем с исходным размером вырезанного кусочка
  207. new_image.save(file_name)
  208. button4 = Button(container , text="Save Result" , command=my_callback4)
  209. button4.grid(row=2 ,column=0)
  210. ########################################################################
  211. root.mainloop()