Loading openflexure_microscope/plugins/default/api.py +23 −2 Original line number Diff line number Diff line import numpy as np from openflexure_microscope.api.v1.views import MicroscopeViewPlugin from openflexure_microscope.api.utilities import JsonPayload from flask import request, Response, escape from flask import request, Response, escape, jsonify import logging Loading @@ -17,3 +20,21 @@ class IdentifyAPI(MicroscopeViewPlugin): """ data = self.microscope.plugin.default.identify() # Call a method from our plugin, using the full route return Response(escape(data)) class MeasureSharpnessAPI(MicroscopeViewPlugin): def post(self): payload = JsonPayload(request) return jsonify({'sharpness': self.plugin.measure_sharpness()}) class AutofocusAPI(MicroscopeViewPlugin): def post(self): payload = JsonPayload(request) # Figure out the range of z values to use dz = payload.param("dz", default=np.linspace(-300,300,7), convert=np.array) print("Running autofocus...") task = self.microscope.task.start(self.plugin.autofocus, dz) # return a handle on the autofocus task return jsonify(task.state, 202) openflexure_microscope/plugins/default/focus_utils.py 0 → 100644 +21 −0 Original line number Diff line number Diff line import numpy as np from scipy import ndimage def decimate_to(shape, image): """Decimate an image to reduce its size if it's too big.""" decimation = np.max(np.ceil(np.array(image.shape, dtype=np.float)[:len(shape)]/np.array(shape))) return image[::int(decimation), ::int(decimation), ...] def sharpness_sum_lap2(rgb_image): """Return an image sharpness metric: sum(laplacian(image)**")""" #image_bw=np.mean(decimate_to((1000,1000), rgb_image),2) image_bw=np.mean(rgb_image, 2) image_lap=ndimage.filters.laplace(image_bw) return np.mean(image_lap.astype(np.float)**4) def sharpness_edge(image): """Return a sharpness metric optimised for vertical lines""" gray = np.mean(image.astype(float), 2) n = 20 edge = np.array([[-1]*n + [1]*n]) return np.sum([np.sum(ndimage.filters.convolve(gray,W)**2) for W in [edge, edge.T]]) openflexure_microscope/plugins/default/plugin.py +38 −2 Original line number Diff line number Diff line import time import numpy as np from openflexure_microscope.plugins import MicroscopePlugin from openflexure_microscope.utilities import set_properties from .api import IdentifyAPI from .focus_utils import sharpness_sum_lap2 from .api import IdentifyAPI, MeasureSharpnessAPI, AutofocusAPI class Plugin(MicroscopePlugin): Loading @@ -10,6 +15,8 @@ class Plugin(MicroscopePlugin): api_views = { '/identify': IdentifyAPI, '/measure_sharpness': MeasureSharpnessAPI, '/autofocus': AutofocusAPI, } def identify(self): Loading @@ -18,5 +25,34 @@ class Plugin(MicroscopePlugin): """ response = "My parent camera is {}, and my parent stage is {}.".format(self.microscope.camera, self.microscope.stage) print(response) return response def autofocus(self, dz, settle=0.5, metric_fn=sharpness_sum_lap2): """Perform a simple autofocus routine. The stage is moved to z positions (relative to current position) in dz, and at each position an image is captured and the sharpness function evaulated. We then move back to the position where the sharpness was highest. No interpolation is performed. dz is assumed to be in ascending order (starting at -ve values) """ camera = self.microscope.camera stage = self.microscope.stage with set_properties(stage, backlash=256), stage.lock, camera.lock: sharpnesses = [] positions = [] camera.annotate_text = "" for i in stage.scan_z(dz, return_to_start=False): positions.append(stage.position[2]) time.sleep(settle) sharpnesses.append(self.measure_sharpness(metric_fn)) newposition = positions[np.argmax(sharpnesses)] stage.focus_rel(newposition - stage.position[2]) return positions, sharpnesses def measure_sharpness(self, metric_fn=sharpness_sum_lap2): """Measure the sharpness of the camera's current view.""" return metric_fn(self.microscope.camera.array(use_video_port=True, resize=(640,480))) Loading
openflexure_microscope/plugins/default/api.py +23 −2 Original line number Diff line number Diff line import numpy as np from openflexure_microscope.api.v1.views import MicroscopeViewPlugin from openflexure_microscope.api.utilities import JsonPayload from flask import request, Response, escape from flask import request, Response, escape, jsonify import logging Loading @@ -17,3 +20,21 @@ class IdentifyAPI(MicroscopeViewPlugin): """ data = self.microscope.plugin.default.identify() # Call a method from our plugin, using the full route return Response(escape(data)) class MeasureSharpnessAPI(MicroscopeViewPlugin): def post(self): payload = JsonPayload(request) return jsonify({'sharpness': self.plugin.measure_sharpness()}) class AutofocusAPI(MicroscopeViewPlugin): def post(self): payload = JsonPayload(request) # Figure out the range of z values to use dz = payload.param("dz", default=np.linspace(-300,300,7), convert=np.array) print("Running autofocus...") task = self.microscope.task.start(self.plugin.autofocus, dz) # return a handle on the autofocus task return jsonify(task.state, 202)
openflexure_microscope/plugins/default/focus_utils.py 0 → 100644 +21 −0 Original line number Diff line number Diff line import numpy as np from scipy import ndimage def decimate_to(shape, image): """Decimate an image to reduce its size if it's too big.""" decimation = np.max(np.ceil(np.array(image.shape, dtype=np.float)[:len(shape)]/np.array(shape))) return image[::int(decimation), ::int(decimation), ...] def sharpness_sum_lap2(rgb_image): """Return an image sharpness metric: sum(laplacian(image)**")""" #image_bw=np.mean(decimate_to((1000,1000), rgb_image),2) image_bw=np.mean(rgb_image, 2) image_lap=ndimage.filters.laplace(image_bw) return np.mean(image_lap.astype(np.float)**4) def sharpness_edge(image): """Return a sharpness metric optimised for vertical lines""" gray = np.mean(image.astype(float), 2) n = 20 edge = np.array([[-1]*n + [1]*n]) return np.sum([np.sum(ndimage.filters.convolve(gray,W)**2) for W in [edge, edge.T]])
openflexure_microscope/plugins/default/plugin.py +38 −2 Original line number Diff line number Diff line import time import numpy as np from openflexure_microscope.plugins import MicroscopePlugin from openflexure_microscope.utilities import set_properties from .api import IdentifyAPI from .focus_utils import sharpness_sum_lap2 from .api import IdentifyAPI, MeasureSharpnessAPI, AutofocusAPI class Plugin(MicroscopePlugin): Loading @@ -10,6 +15,8 @@ class Plugin(MicroscopePlugin): api_views = { '/identify': IdentifyAPI, '/measure_sharpness': MeasureSharpnessAPI, '/autofocus': AutofocusAPI, } def identify(self): Loading @@ -18,5 +25,34 @@ class Plugin(MicroscopePlugin): """ response = "My parent camera is {}, and my parent stage is {}.".format(self.microscope.camera, self.microscope.stage) print(response) return response def autofocus(self, dz, settle=0.5, metric_fn=sharpness_sum_lap2): """Perform a simple autofocus routine. The stage is moved to z positions (relative to current position) in dz, and at each position an image is captured and the sharpness function evaulated. We then move back to the position where the sharpness was highest. No interpolation is performed. dz is assumed to be in ascending order (starting at -ve values) """ camera = self.microscope.camera stage = self.microscope.stage with set_properties(stage, backlash=256), stage.lock, camera.lock: sharpnesses = [] positions = [] camera.annotate_text = "" for i in stage.scan_z(dz, return_to_start=False): positions.append(stage.position[2]) time.sleep(settle) sharpnesses.append(self.measure_sharpness(metric_fn)) newposition = positions[np.argmax(sharpnesses)] stage.focus_rel(newposition - stage.position[2]) return positions, sharpnesses def measure_sharpness(self, metric_fn=sharpness_sum_lap2): """Measure the sharpness of the camera's current view.""" return metric_fn(self.microscope.camera.array(use_video_port=True, resize=(640,480)))