Mikroskop mit Tkinter-GUi

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
kaytec
User
Beiträge: 540
Registriert: Dienstag 13. Februar 2007, 21:57

Re: Mikroskop mit Tkinter-GUi

Beitragvon kaytec » Sonntag 15. April 2018, 20:47

Hallo,

mit der Maus kann das Bild verschoben werden.

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8
  3. from __future__ import division
  4.  
  5. import tkinter as tk
  6. import os
  7. import datetime
  8. import cv2
  9. from PIL import Image, ImageTk
  10. from functools import partial
  11. from itertools import cycle
  12. import numpy as np
  13.  
  14. WIDTH = 640
  15. HEIGHT = 480
  16. VIDEO_CODEC = "XVID"
  17. DEFAULT_CAM_ID = 0
  18.  
  19.  
  20. class Microscope(object):
  21.  
  22.     PROPID_WIDTH = 3
  23.     PROPID_HEIGHT = 4
  24.     INTERPOLATION_METHODS= {"NEAREST" : cv2.INTER_NEAREST,
  25.                             "LINEAR" : cv2.INTER_LINEAR,
  26.                             "AREA" : cv2.INTER_AREA,
  27.                             "CUBIC" : cv2.INTER_CUBIC,
  28.                             "LANCZOS4" : cv2.INTER_LANCZOS4}
  29.  
  30.     def __init__(self, cam_id=DEFAULT_CAM_ID, number_of_imgs=10,
  31.         series_time_interval=1, image_path=".", video_path=".",
  32.         series_img_path=".", img_format=".tiff"):
  33.         self.cam = cv2.VideoCapture(cam_id)
  34.         if not self.cam.isOpened():
  35.             raise RuntimeError("can not open camera {0!r}".format(
  36.                 cam_id))
  37.         self.img_format = img_format
  38.         self.inter_frame = None
  39.         self.last_frame = None
  40.         self.take_series = False
  41.         self.recording = False
  42.         self.number_of_imgs = number_of_imgs
  43.         self.series_counter = None
  44.         self.series_time_counter = None
  45.         self.series_time_interval = series_time_interval
  46.         self.image_path = image_path
  47.         self.video_path = video_path
  48.         self.series_img_path = series_img_path
  49.         self.series_dir = None
  50.         self.interpolation_methods_keys = cycle(
  51.             self.INTERPOLATION_METHODS.keys())
  52.         self.interpolation_method = self.interpolation_methods_keys.next()
  53.         self.cam_width = self.zoom_width = int(self.cam.get(self.PROPID_WIDTH))
  54.         self.cam_height = self.zoom_height = int(self.cam.get(self.PROPID_HEIGHT))
  55.        
  56.     def __enter__(self):
  57.         return self
  58.  
  59.     def __exit__(self, *args):
  60.         self.release()
  61.  
  62.     @property
  63.     def size(self):
  64.         return self.cam_width, self.cam_height
  65.        
  66.     @property
  67.     def zoom_size(self):
  68.         return self.zoom_width, self.zoom_height
  69.        
  70.     @property
  71.     def interpolation(self):
  72.         return self.interpolation_method
  73.  
  74.     def get_image(self):
  75.         state, frame = self.cam.read()
  76.        
  77.         if state and np.array_equal(self.last_frame, frame):
  78.             self.release()
  79.             state = False
  80.         if not state:
  81.             raise RuntimeError("could not read image")
  82.  
  83.         self.last_frame = frame
  84.         self.inter_frame = cv2.resize(frame, self.zoom_size,
  85.         interpolation = self.INTERPOLATION_METHODS[
  86.             self.interpolation_method])
  87.            
  88.         if self.take_series:
  89.             self.series_time_counter += 1
  90.             if self.series_time_counter > self.series_time_interval:
  91.                 self.series_counter += 1
  92.                 self.series_time_counter = 0
  93.                 if self.series_counter <= self.number_of_imgs:
  94.                     img_name = "{0}{1}".format(self.series_counter,
  95.                         self.img_format)
  96.                     cv2.imwrite(os.path.join(self.series_img_path,
  97.                         self.series_dir, img_name), self.inter_frame)
  98.                 else:
  99.                     self.take_series = False
  100.         if self.recording:
  101.             self.video_writer.write(self.inter_frame)
  102.         return self.inter_frame
  103.  
  104.     def recording_start_stop(self, name = None):
  105.         if self.recording:
  106.             self.recording = False
  107.         else:
  108.             self.recording = True
  109.             self.video_writer = cv2.VideoWriter(os.path.join(
  110.                 self.video_path, name if name else
  111.                 "{0:%d%b%Y_%H_%M_%S.%f}.avi".format(datetime.datetime.utcnow()
  112.                 )), cv2.cv.CV_FOURCC(* VIDEO_CODEC), 24, self.zoom_size)
  113.                
  114.     def take_series_picture(self):
  115.         if not self.take_series:        
  116.             self.series_dir = "{0:%d%b%Y_%H_%M_%S.%f}".format(
  117.                 datetime.datetime.utcnow())
  118.             os.makedirs(self.series_dir)
  119.             self.series_time_counter = 0
  120.             self.series_counter = 0
  121.             self.take_series = True
  122.  
  123.     def take_picture(self, name = None):
  124.         if not name:
  125.             name = "{0:%d%b%Y_%H_%M_%S.%f}{1}".format(
  126.                 datetime.datetime.utcnow(), self.img_format)
  127.         cv2.imwrite(os.path.join(self.image_path, name), self.inter_frame)
  128.        
  129.     def series_up_down(self, step):
  130.         if not self.take_series:
  131.             if self.number_of_imgs > -step:
  132.                 self.number_of_imgs += step
  133.        
  134.     def set_time_interval(self, step):
  135.         if not self.take_series:
  136.             if self.series_time_interval > -step:
  137.                 self.series_time_interval += step
  138.        
  139.     def zoom_image(self, step):
  140.         height = int(self.zoom_height + step)
  141.         width = int(height * self.cam_width / self.cam_height)
  142.         if width > 0 and height > 0:
  143.             self.zoom_width = width
  144.             self.zoom_height = height
  145.  
  146.     def reset_zoom(self):
  147.         self.zoom_width, self.zoom_height = self.size
  148.        
  149.     def next_interpolation_method(self):
  150.         self.interpolation_method = self.interpolation_methods_keys.next()
  151.        
  152.     def release(self):
  153.         self.cam.release()
  154.  
  155. class MicroscopeUI(tk.Frame):
  156.  
  157.     UPDATE_INTERVAL = 10
  158.     REC_ON = 5
  159.    
  160.     def __init__(self, parent, microscope, width, height, zoom_step=10):
  161.         tk.Frame.__init__(self, parent)
  162.         self.parent = parent
  163.         self.width = width
  164.         self.height = height
  165.         self.tk_image = None
  166.         self.rec_on = cycle(x for x in xrange(self.REC_ON))
  167.         self.text_on = False
  168.         self.microscope = microscope
  169.         self.text_colour_index = cycle(["white", "green", "black", "red",
  170.             "magenta", "green", "brown", "yellow", "blue", "orange", "gray"])
  171.         self.text_colour = self.text_colour_index.next()
  172.         self.canvas = tk.Canvas(self, width=width, height=height)
  173.         self.canvas.grid(column=0, row=0)
  174.         self.canvas.bind("<ButtonPress-1>", self.start_slide)
  175.         self.canvas.bind("<B1-Motion>", self.slide_image)
  176.         self.vscrollbar = tk.Scrollbar(self)
  177.         self.vscrollbar.grid(column=1, row=0, sticky=tk.N+tk.S)
  178.         self.canvas.config(yscrollcommand=self.vscrollbar.set)
  179.         self.vscrollbar.config(command=self.canvas.yview)
  180.         self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
  181.         self.hscrollbar.grid(column=0, row=1, columnspan=5, sticky=tk.E+tk.W)
  182.         self.canvas.config(xscrollcommand=self.hscrollbar.set)
  183.         self.hscrollbar.config(command=self.canvas.xview)
  184.         button_frame = tk.Frame(self)
  185.         button_frame.grid(column=0, row=3, columnspan=2)
  186.         self.buttons = list()
  187.         for column, (text, width, command, var)in enumerate(
  188.             (("||", 2, self.capture_start_stop, ()),
  189.              ("Z+", 2, self.microscope.zoom_image, (zoom_step,)),
  190.              ("Z-", 2, self.microscope.zoom_image, (-zoom_step,)),
  191.              ("Z+/-", 2, self.microscope.reset_zoom, ()),
  192.              ("[1]", 2, self.microscope.take_picture, ()),
  193.              ("REC", 2, self.recording_start_stop, ()),
  194.              ("[S]]]", 2, self.microscope.take_series_picture, ()),
  195.              ("INTPOL", 5, self.next_interpolation_method, ()),
  196.              ("S+", 2, self.series_up_down, (1,)),
  197.              ("S-", 2, self.series_up_down, (-1,)),
  198.              ("T+", 2, self.time_interval_up_down, (
  199.               self.microscope.series_time_interval,)),
  200.              ("T-", 2, self.time_interval_up_down, (
  201.               -self.microscope.series_time_interval,)),
  202.              ("ON", 2, self.set_text_on_off, ()),
  203.              ("C", 2, self.change_text_colour, ()))):
  204.             button = tk.Button(button_frame, text=text, width=width,
  205.                 relief="raised", font="Arial 10 bold",
  206.                 command=partial(command, *var))
  207.             button.grid(column=column, row=0)
  208.             self.buttons.append(button)
  209.  
  210.     def slide_image(self, event):
  211.         self.canvas.scan_dragto(event.x, event.y, gain=-1)
  212.        
  213.     def start_slide(self, event):
  214.         self.canvas.scan_mark(event.x, event.y)
  215.        
  216.     def capture_start_stop(self):
  217.         if self.after_id is None:
  218.             self.buttons[0].config(text = "||")
  219.             self.run()
  220.         else:
  221.             self.buttons[0].config(text = ">")
  222.             self.after_cancel(self.after_id)
  223.             self.after_id = None
  224.  
  225.     def run(self):
  226.         try:
  227.             tk_image = Image.frombytes("RGB",  self.microscope.zoom_size,
  228.                 self.microscope.get_image(), "raw", "BGR")
  229.         except RuntimeError:
  230.             self.raise_cam_id_error()
  231.             return
  232.  
  233.         self.canvas.delete("img", "rec", "txt")
  234.         self.tk_image = ImageTk.PhotoImage(tk_image)
  235.         self.canvas.create_image((0,0), anchor=tk.NW,
  236.             image=self.tk_image, tag="img")
  237.         width, height = self.microscope.zoom_size
  238.         if self.text_on:        
  239.             rec_text = " "
  240.             if self.microscope.recording and not self.rec_on.next():
  241.                 rec_text = "O"
  242.             self.canvas.create_text(width / 2, height / 2,
  243.                 text="+", font="Courier 30", fill=self.text_colour,
  244.                 tag="txt")
  245.             self.canvas.create_text(width / 2,
  246.                 10 + height/2 - self.height / 2,
  247.                 font="Courier 13 bold",
  248.                 text = "REC:{0}  FILTER:{1}  SERIES:{2}  TIME:{3}  RES:{4}:{5}"
  249.                 .format(rec_text,
  250.                     self.microscope.interpolation,
  251.                     self.microscope.number_of_imgs,                            
  252.                     self.microscope.series_time_interval,
  253.                     width, height),
  254.                 anchor="center",
  255.                 fill = self.text_colour,
  256.                 tag = "txt")
  257.  
  258.         state = tk.DISABLED if self.microscope.take_series else tk.NORMAL
  259.         for button in (1, 2, 3, 7, 8, 9, 10, 11):
  260.             self.buttons[button].config(state=state)
  261.                
  262.         width, height = self.microscope.zoom_size
  263.         self.canvas.config(scrollregion = (0, 0, width, height))
  264.         self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
  265.            
  266.     def change_text_colour(self):      
  267.         self.set_text_on_off(True)
  268.         self.text_colour = self.text_colour_index.next()
  269.        
  270.     def set_text_on_off(self, force_on=False):
  271.         self.text_on = force_on or not self.text_on
  272.         self.buttons[12].config(text="OFF" if self.text_on else "ON")
  273.        
  274.     def raise_cam_id_error(self):
  275.         self.canvas.delete("img", "rec", "txt")
  276.         self.canvas.create_text((self.width / 2, self.height / 2),
  277.             text='NO CAM', font='Arial 40')
  278.         for button in self.buttons:
  279.             button.config(state="disabled")
  280.            
  281.     def recording_start_stop(self):
  282.         self.set_text_on_off(True)
  283.         self.microscope.recording_start_stop()
  284.        
  285.     def series_up_down(self, step):
  286.         self.set_text_on_off(True)
  287.         self.microscope.series_up_down(step)
  288.        
  289.     def time_interval_up_down(self, step):
  290.         self.set_text_on_off(True)
  291.         self.microscope.set_time_interval(step)
  292.        
  293.     def next_interpolation_method(self):
  294.         self.set_text_on_off(True)
  295.         self.microscope.next_interpolation_method()
  296.  
  297.     def release(self):
  298.         self.parent.destroy()
  299.  
  300. def main():
  301.     root = tk.Tk()
  302.     root.title('MICROSCOPE')
  303.    
  304.     try:
  305.         with Microscope(series_time_interval=1) as microscope:
  306.             def take_picture(e):
  307.                 microscope_ui.take_picture()
  308.             microscope_ui = MicroscopeUI(
  309.                 root, microscope, WIDTH, HEIGHT)
  310.             microscope_ui.pack(expand=tk.YES)
  311.             microscope_ui.run()
  312.             root.protocol("WM_DELETE_WINDOW", microscope_ui.release)
  313.             #root.bind("<Key" + chr(10) + ">", take_picture)
  314.             root.mainloop()
  315.            
  316.     except RuntimeError:
  317.         tk.Label(root, text = 'can not open camera {0!r}'.format(
  318.                 DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
  319.         root.mainloop()
  320.    
  321. if __name__ == '__main__':
  322.     main()


Gruß

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder