This commit is contained in:
alexgobbo
2024-09-12 16:19:14 +02:00
parent 75400ca453
commit d3b931cebd
4 changed files with 269 additions and 40 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
#Wed Sep 11 16:12:29 CEST 2024
#Thu Sep 12 16:17:12 CEST 2024
barcode_reader_scan_pucks=false
beamline_status_enabled=false
cold_position_timeout=3600
+205
View File
@@ -0,0 +1,205 @@
import math
from ijutils import *
import ij.process.Blitter as Blitter
FILL_STRATEGY = "mask" #"mask", "bits", "none"
OPEN_STRATEGY = "both" #"black", "white", "both", "none"
DIAM_1 = 84
DIAM_2 = 550
DETECT_THRESHOLD = 10 #PIXELS
FRAMES = 5
MASK_SIZE = 0.8 # of DIAM_2
ROLLING_WINDOW = False
def detect(ip, print_table=False, output_image=False):
if output_image==True:
output_image= "outlines"
if ip.getProcessor().isGrayscale():
ig = ip
else:
ig = grayscale(ip, in_place=False)
#Threshoolding
it = auto_threshold(ig, dark_background=True, in_place=False)
w, h = it.getWidth(), it.getHeight()
#it.show()
if OPEN_STRATEGY in ("black", "both"): #Refine inner
binary_open(it, dark_background=True, iterations=1, count=1);
if OPEN_STRATEGY in ("white", "both"): #Refine outter
binary_open(it, dark_background=False, iterations=1, count=1);
#it.repaintWindow()
#Detect outer white circle
px = int(pow(DIAM_2/2,2) * math.pi)
(res2,out2)=analyse_particles(it, px/2, px*2, \
fill_holes = True, exclude_edges = True, print_table=print_table, \
output_image = output_image, minCirc = 0.8, maxCirc = 1.0)
if res2.size() != 1:
msg = "Outter detection error: " + ("none" if res2.size()==0 else "")
for i in range( res2.size()):
msg = msg + "(" + str(res2.getValue("XM", 0)) + ", " + str( res2.getValue("YM", 0)) + ")"
raise Exception( msg )
x2,y2 = res2.getValue("XM", 0), res2.getValue("YM", 0)
invert(it, in_place=True)
ip = it.getProcessor()
dist = DIAM_2 * (MASK_SIZE/2.0)
if FILL_STRATEGY == "bits":
for y in range(h):
for x in range(w):
distance = math.hypot(x - x2, y - y2)
if distance >dist:
ip.putPixel(x, y, 0)
elif FILL_STRATEGY == "mask":
mask = ip.createProcessor(w, h) # Creates a new blank ImageProcessor
mask.setColor(255) # Set the drawing color to white (255)
mask.fillOval(int(x2 - dist), int(y2 - dist), int(2 * dist), int(2 * dist)) # Draw the circular ROI
mask.autoThreshold() # Ensures the mask is binary (if needed)
ip.copyBits(mask, 0, 0, Blitter.AND) # Apply the mask using a bitwise AND
px = int(pow(DIAM_1/2,2) * math.pi)
(res1,out1)=analyse_particles(it, px/2, px*2, \
fill_holes = FILL_STRATEGY!="none", exclude_edges = True, print_table=print_table, \
output_image = output_image, minCirc = 0.8, maxCirc = 1.0)
if res1.size() != 1:
msg = "Inner detection error: " + ("none" if res1.size()==0 else "")
for i in range( res1.size()):
msg = msg + "(" + str(res1.getValue("XM", 0)) + ", " + str( res2.res1("YM", 0)) + "), "
raise Exception( msg )
x1,y1 = res1.getValue("XM", 0), res1.getValue("YM", 0)
if abs(x1-x2) > DETECT_THRESHOLD or abs(y1-y2) > DETECT_THRESHOLD:
msg = "Detection offseterror: " + + "(" + str(x1-x2) + ", " + str(y1-y2) + ")"
raise Exception( msg )
return x1,y1
"""
if FRAMES>1:
ip = integrate_frames(samples = FRAMES)
else:
ip = load_image(image.output, title="Image")
try:
x,y = detect(ip)
print("Detected: ", (x, y))
p = Point(int(x),int(y))
ov = Overlays.Crosshairs(renderer.getPenProfile(), p, Dimension(-1, -1))
renderer.setMarker(ov);
except Exception as e:
traceback.print_exc(e)
print(e)
renderer.setMarker(None)
"""
error_overlay=None
def clear_error_overlay(renderer):
global error_overlay
try:
renderer.removeOverlay(error_overlay)
except:
pass
error_overlay = None
def add_error_overlay(renderer, error):
global error_overlay
former = error_overlay
error_overlay = Overlays.Text(renderer.getPenErrorText(), error, Font("Verdana", Font.PLAIN, 12), Point(20, 20))
error_overlay.setFixed(True)
error_overlay.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT)
renderer.updateOverlays(error_overlay, former)
class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
def __init__(self, name, image, renderer):
ReadonlyAsyncRegisterBase.__init__(self, name)
self.image = image
class ImgListener (ImageListener):
def onImage(s, origin, image, data):
self.append(image)
def onError(s, origin, ex):
print ex
self.listener = ImgListener()
self.enabled = False
self.images = []
self.processing_time = None
self.renderer = renderer
self.error = None
def doInitialize(self):
print "Init"
#super(ReadonlyAsyncRegisterBase, self).doInitialize()
#ReadonlyRegisterBase.doInitialize(self)
self.enable()
self.clear()
def doClose(self):
print 1
self.disable()
print 2
#DeviceBase.doClose(self)
#print 3
def enable(self):
if not self.enabled:
self.enabled = True
self.image.addListener(self.listener)
def disable(self):
if self.enabled:
self.image.removeListener(self.listener)
self.enabled = False
self.onReadout(None)
self.clear()
def clear(self):
if self.renderer is not None:
renderer.setMarker(None)
clear_error_overlay(renderer)
def append(self, image):
ip = load_image(ImagingUtils.grayscale(image, None))
self.images.append(ip)
while len(self.images) > FRAMES:
self.images.pop(0)
if len(self.images) == FRAMES:
ip = integrate(self.images)
#print type(ip)
start = time.time()
try:
self.error = None
x,y = detect(ip)
except Exception as e:
self.error = e
x,y = -1, -1
self.processing_time = time.time()-start
self.set(x, y, self.processing_time * 1000, self.error)
if not ROLLING_WINDOW:
self.images=[]
def set(self, x, y, tm, error):
if self.enabled:
value = to_array([x, y, tm], 'i')
self.onReadout(value)
if self.renderer is not None:
if error is None:
clear_error_overlay(renderer)
marker = Overlays.Crosshairs(renderer.getPenProfile(), Point(int(x),int(y)), Dimension(-1, -1))
else:
add_error_overlay(renderer, str(error))
marker = None
renderer.setMarker(marker);
renderer=show_panel(image)
add_device(CoverDetection("cover_detection", image, renderer), force = True)
+3 -1
View File
@@ -63,6 +63,7 @@ roi_radius = 600
roi_border = 30
def get_roi():
img = image
#roi_center = (img.output.width/2, img.output.height/2)
#roi_radius = min(roi_center[0], roi_center[1])
#return (roi_center[0] - roi_radius, roi_center[1] - roi_radius, 2* roi_radius, 2*roi_radius)
@@ -72,12 +73,13 @@ def get_roi():
return (0,0,img.output.width, img.output.height)
def get_image():
img = image
roi = get_roi()
#ip = load_image(img.output)
#ret = ip if (roi is None) else sub_image(ip, roi[0], roi[1], roi[2], roi[3])
#grayscale(ret, do_scaling=True)
ret = load_image(Utils.grayscale(img.output, Rectangle(roi[0], roi[1], roi[2], roi[3]) if (roi is not None) else None))
ret = load_image(ImagingUtils.grayscale(img.output, Rectangle(roi[0], roi[1], roi[2], roi[3]) if (roi is not None) else None))
return ret
#def detect_pucks(ip):
+60 -38
View File
@@ -1,58 +1,80 @@
import math
from ijutils import *
import ij.process.Blitter as Blitter
DIAM_1 = 80
FILL_STRATEGY = "mask" #"mask", "bits", "none"
OPEN_STRATEGY = "both" #"black", "white", "both", "none"
DIAM_1 = 84
DIAM_2 = 550
DETECT_THRESHOLD = 10 #PIXELS
FRAMES = 1
MASK_SIZE = 0.8 # of DIAM_2
renderer=show_panel(image)
renderer.setMarker(None);
start = time.time()
#Image Loading
ip = load_image(image.output, title="Image")
aux = grayscale(ip, in_place=False)
#invert(aux);
px1 = int(pow(DIAM_1/2,2) * math.pi)
px2 = int(pow(DIAM_2/2,2) * math.pi)
#aux.show()
#binary_open(aux); aux.repaintWindow()
if FRAMES>1:
ig = integrate_frames(samples = FRAMES)
else:
ip = load_image(image.output, title="Image")
ig = grayscale(ip, in_place=False)
ti = auto_threshold(aux, dark_background=False, in_place=False) #; aux.repaintWindow()
#ti.show()
#binary_fill_holes(ti)
#ti.repaintWindow()
#Threshoolding
it = auto_threshold(ig, dark_background=True, in_place=False)
w, h = it.getWidth(), it.getHeight()
#it.show()
if OPEN_STRATEGY in ("black", "both"): #Refine inner
binary_open(it, dark_background=True, iterations=1, count=1);
if OPEN_STRATEGY in ("white", "both"): #Refine outter
binary_open(it, dark_background=False, iterations=1, count=1);
#it.repaintWindow()
(res1,out1)=analyse_particles(ti, px1/2, px1*2, \
fill_holes = False, exclude_edges = True, print_table=True, \
output_image = "outlines", minCirc = 0.8, maxCirc = 1.0)
#out1.show()
ti = auto_threshold(aux, dark_background=True, in_place=False) #; aux.repaintWindow()
(res2,out2)=analyse_particles(ti, px2/2, px2*2, \
fill_holes = False, exclude_edges = True, print_table=True, \
#Detect outer white circle
px = int(pow(DIAM_2/2,2) * math.pi)
(res2,out2)=analyse_particles(it, px/2, px*2, \
fill_holes = True, exclude_edges = True, print_table=True, \
output_image = "outlines", minCirc = 0.8, maxCirc = 1.0)
#output_img.show()
if res1.size() == res2.size() == 1:
x1,y1 = res1.getValue("XM", 0), res1.getValue("YM", 0)
if res2.size() == 1:
x2,y2 = res2.getValue("XM", 0), res2.getValue("YM", 0)
if abs(x1-x2) <= DETECT_THRESHOLD and abs(y1-y2) <= DETECT_THRESHOLD:
print("Detected: ", (x1, y1))
renderer=show_panel(image)
p = Point(int(x1),int(y1))
ov = Overlays.Crosshairs(renderer.getPenProfile(), p, Dimension(-1, -1))
renderer.setMarker(ov);
invert(it, in_place=True)
ip = it.getProcessor()
dist = DIAM_2 * (MASK_SIZE/2.0)
if FILL_STRATEGY == "bits":
for y in range(h):
for x in range(w):
distance = math.hypot(x - x2, y - y2)
if distance >dist:
ip.putPixel(x, y, 0)
elif FILL_STRATEGY == "mask":
mask = ip.createProcessor(w, h) # Creates a new blank ImageProcessor
mask.setColor(255) # Set the drawing color to white (255)
mask.fillOval(int(x2 - dist), int(y2 - dist), int(2 * dist), int(2 * dist)) # Draw the circular ROI
mask.autoThreshold() # Ensures the mask is binary (if needed)
ip.copyBits(mask, 0, 0, Blitter.AND) # Apply the mask using a bitwise AND
#it.show()
px = int(pow(DIAM_1/2,2) * math.pi)
(res1,out1)=analyse_particles(it, px/2, px*2, \
fill_holes = FILL_STRATEGY!="none", exclude_edges = True, print_table=True, \
output_image = "outlines", minCirc = 0.8, maxCirc = 1.0)
if res1.size() == res2.size() == 1:
x1,y1 = res1.getValue("XM", 0), res1.getValue("YM", 0)
if abs(x1-x2) <= DETECT_THRESHOLD and abs(y1-y2) <= DETECT_THRESHOLD:
print("Detected: ", (x1, y1))
renderer=show_panel(image)
p = Point(int(x1),int(y1))
ov = Overlays.Crosshairs(renderer.getPenProfile(), p, Dimension(-1, -1))
renderer.setMarker(ov);
print "Processing time:", time.time()-start