This commit is contained in:
alexgobbo
2024-09-17 18:10:45 +02:00
parent 93f0c812e7
commit 0692cd7cdc
11 changed files with 575 additions and 25 deletions
+67 -8
View File
@@ -1,4 +1,5 @@
run("imgproc/NewCoverDetection")
run("imgproc/NewCoverCorrelation")
class CoverDetectionConfig(RegisterConfig):
@@ -10,7 +11,16 @@ class CoverDetectionConfig(RegisterConfig):
self.center_y = 570.0
self.scale_x = 1.0
self.scale_y = 1.0
self.scale_y = 1.0
self.threshold = 0.60
class CoverCorrelation(ReadonlyAsyncRegisterBase):
def __init__(self, name):
ReadonlyAsyncRegisterBase.__init__(self, name)
def set(self, value):
self.onReadout(value)
class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
def __init__(self, name, image):
@@ -32,13 +42,21 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
self.error_overlay=None
self.img_counter, self.proc_counter = 0, 0
self.offset_px = self.offset_um = None
self.correlation = CoverCorrelation("cover_correlation")
self.correlation_error = False
def doInitialize(self):
self.enable()
self.clear()
try:
self.enable()
self.clear()
#self.grab_ref_image()
except:
traceback.print_exc()
raise
def doClose(self):
self.disable()
def doClose(self):
self.disable()
self.correlation.close()
def set_renderer(self, renderer):
self.clear()
@@ -60,7 +78,8 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
def clear(self):
self.set_marker(None)
self.set_error_overlay(None)
self.set_error_overlay(None)
self.set_correlation(None)
def append(self, image):
self.img_counter += 1
@@ -83,7 +102,20 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
x,y = -1, -1
self.processing_time = time.time()-start
self.proc_counter += 1
try:
corr = get_correlation(ip.getBufferedImage())
self.correlation.set(corr)
self.set_correlation(corr)
except Exception as e:
#traceback.print_exc()
if self.error is None:
self.error = e
self.set(x, y, self.processing_time * 1000, self.error)
#traceback.print_exc()
if not self.config.continuous:
self.images=[]
@@ -96,7 +128,7 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
offx, offy = x-cover_detection.config.center_x, -(y-cover_detection.config.center_y)
self.offset_px = opx, opy = round(offx), round(offy)
self.offset_um = omx, omy = self.config.scale_x * offx * 1000.0, self.config.scale_y * offy *1000.0
value = to_array([x, y, opx, opy, omx, omy, tm], 'i')
value = to_array([x, y, opx, opy, omx, omy, tm], 'i')
self.onReadout(value)
if self.renderer is not None:
if error is None:
@@ -122,8 +154,35 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
self.error_overlay = error_overlay
else:
self.error_overlay = None
def grab_ref_image(self):
if self.config.number_images>1:
images = []
for i in range(self.config.number_images):
ip = load_image(ImagingUtils.grayscale(self.image.output, None))
images.append(ip)
self.image.waitNext(-1)
ip = integrate(images)
img = ip.getBufferedImage()
else:
img = self.image.output
save_ref_img(img)
def set_correlation(self, corr):
self.corr = corr
error = corr is not None and corr < self.config.threshold
if error != self.correlation_error:
self.correlation_error = error
if error:
print ("Image anomally detected")
else:
print ("Image ok")
if error:
raise Exception ("Image anomally detected")
add_device(CoverDetection("cover_detection", image), force = True)
add_device(cover_detection.correlation, force = True)
renderer=show_panel(image)
cover_detection.set_renderer(renderer)
+10 -7
View File
@@ -55,16 +55,15 @@ class VmbCamera (CameraBase):
fork(init_img)
self.setState(State.Disabled)
def add_img_device(self):
def add_dev_task():
def add_initialized_callback(self, callback):
def wait_init():
try:
self.waitStateNot(State.Disabled, -1)
if (self.stream.state == State.Busy) and (get_context().state.isActive()):
add_device(self.image, True)
log("Added VmbCamera image device")
callback()
except Exception as e:
log(str(e))
fork(add_dev_task)
fork(wait_init)
def getInfo(self):
try:
@@ -282,6 +281,10 @@ fork(start_camera_server)
c = VmbCamera("cam", image_name="image")
add_device(c, True)
add_device(c.stream, True)
c.add_img_device()
def initialized_callback():
add_device(c.image, True)
add_device(c.image.contrast, force = True)
log("Added VmbCamera image device")
run( "devices/CoverDetection")
c.add_initialized_callback(initialized_callback)
+99
View File
@@ -0,0 +1,99 @@
import ch.psi.pshell.imaging.ImageBuffer as ImageBuffer
offset = 0
add_mark = False
#offset = 50
#add_mark = True
Image_Correlator = get_context().getClassByName("Image_Correlator")
correlator = Image_Correlator()
def get_min(ip1):
return ip1.getProcessor().getStatistics().min
def mean_abs_error(ip1, ip2):
sum = 0.0
for y in range(ip1.getHeight()):
for x in range(ip1.getWidth()):
p1 = ip1.getPixel(x, y)
p2 = ip2.getPixel(x, y)
sum += abs(p1 - p2)
return sum / (ip1.height * ip1.width )
def rms_error(ip1, ip2):
sum = 0.0
for y in range(ip1.getHeight()):
for x in range(ip1.getWidth()):
p1 = ip1.getPixel(x, y)
p2 = ip2.getPixel(x, y)
sum += math.pow((p1 - p2),2)
return sum / (ip1.height * ip1.width )
def get_roi_img(img, img_size=1024, radius=512, offset_x=0, offset_y=0):
x,y,w,h = int(cover_detection.config.center_x-img_size/2 + offset_x), \
int(cover_detection.config.center_y-img_size/2 + offset_y), \
img_size, img_size
roi = ImagingUtils.copy(img, None, Rectangle(x,y,w,h))
ip = load_image(roi, title="Img")
p = ip.getProcessor()
mask = p.createProcessor(roi.getWidth(), roi.getHeight())
mask.setColor(255)
cx, cy = img_size/2 - offset_x, img_size/2 - offset_y
mask.fillOval(int(cx - radius), int(cy - radius), int(2 * radius), int(2 * radius)) # Draw the circular ROI
mask.autoThreshold() # Ensures the mask is binary (if needed)
p.copyBits(mask, 0, 0, Blitter.AND) # Apply the mask using a bitwise AND
#gaussian_blur(ip)
p.blurGaussian(1.0)
return ip.getBufferedImage()
def get_edge_img(ib):
ed = ImagingUtils.edgeDetect(ib)
ret = load_image(ed, title="Refe")
#auto_threshold(ret, dark_background=True)
#binary_dilate(ret, iterations=1, count=1)
return ret
def save_ref_img(img):
path = os.path.abspath(expand_path("{images}/ip_ref_fe.png"))
roi=get_roi_img(img, offset_x=0, offset_y=0)
ImageBuffer.saveImage(roi, path, "png")
#ip_ref = load_image(roi, title="ip_ref")
#save_image(ip_ref, path ,"png")
#$ImagingUtils.
#ip_ref_e =get_edge_img(roi)
#save_image(ip_ref_e, path+"ip_ref_e.png" ,"png")
##ip_ref_f = image_fft(ip_ref)
#ip_ref_fe = image_fft(ip_ref_e)
#save_image(ip_ref_fe, path+"ip_ref_fe.png" ,"png")
def put_mark(ib):
for x in range(450, 470):
for y in range(450, 470):
ib.setRGB(x,y, 0)
def get_correlation(img):
global ip_ref_fe
if "ip_ref_fe" not in globals() or ip_ref_fe is None:
path = os.path.abspath(expand_path("{images}/ip_ref_fe.png"))
roi = ImagingUtils.newImage(path)
#ip_ref_fe=open_imagroie(path+"ip_ref_fe.png" ,"png")
#ip_ref = load_image(roi, title="ip_ref")
ip_ref_e =get_edge_img(roi)
ip_ref_fe = image_fft(ip_ref_e)
print "Opend reference image"
roi =get_roi_img(img, offset_x=-offset, offset_y=-offset)
if add_mark:
put_mark(roi)
#ip_cur = load_image(roi, title="Ref")
ip_cur_e =get_edge_img(roi)
#ip_cur_f = image_fft(ip_cur)
ip_cur_fe = image_fft(ip_cur_e)
return correlator.getCorrelation(ip_ref_fe, ip_cur_fe)[0]
+5 -8
View File
@@ -110,9 +110,12 @@ set_setting(BEAMLINE_STATUS_ENABLED_PREFERENCE, is_beamline_status_enabled())
###################################################################################################
# Scripted devices and pseudo-devices
###################################################################################################
scripted_devices = ["devices/RobotSC", "devices/Wago", "devices/BarcodeReader", "devices/LaserDistance",
"devices/LedCtrl", "devices/SmartMagnet", "devices/Gonio", "devices/VmbCamera" #"devices/HexiPosi"]"
"devices/LedCtrl", "devices/SmartMagnet", "devices/Gonio", #"devices/HexiPosi"]"
"devices/VmbCamera",
]
for script in scripted_devices:
@@ -122,12 +125,6 @@ for script in scripted_devices:
run(script)
except:
print >> sys.stderr, traceback.format_exc()
#if is_imaging_enabled():
if get_device("img") is not None:
add_device(img.getContrast(), force = True)
+129
View File
@@ -0,0 +1,129 @@
show = False
img_size = 1024
RADIUS = 512
FRAMES = 1
offset = 0
add_mark = False
#offset = 50
#add_mark = True
Image_Correlator = get_context().getClassByName("Image_Correlator")
correlator = Image_Correlator()
def get_roi_img(radius, offset_x=0, offset_y=0, frames=1):
x,y,w,h = int(cover_detection.config.center_x-img_size/2 + offset_x), \
int(cover_detection.config.center_y-img_size/2 + offset_y), \
img_size, img_size
if frames>1:
ip = integrate_frames(samples = frames)
roi = ImagingUtils.copy(ip.getBufferedImage(), None, Rectangle(x,y,w,h))
else:
roi = ImagingUtils.copy(image.output, None, Rectangle(x,y,w,h))
ip = load_image(roi, title="Img")
p = ip.getProcessor()
mask = p.createProcessor(roi.getWidth(), roi.getHeight())
mask.setColor(255)
cx, cy = img_size/2 - offset_x, img_size/2 - offset_y
mask.fillOval(int(cx - radius), int(cy - radius), int(2 * radius), int(2 * radius)) # Draw the circular ROI
mask.autoThreshold() # Ensures the mask is binary (if needed)
p.copyBits(mask, 0, 0, Blitter.AND) # Apply the mask using a bitwise AND
#gaussian_blur(ip)
p.blurGaussian(1.0)
return ip.getBufferedImage()
def get_edge_img(ib):
ed = ImagingUtils.edgeDetect(ib)
ret = load_image(ed, title="Refe")
#auto_threshold(ret, dark_background=True)
#binary_dilate(ret, iterations=1, count=1)
return ret
def put_mark(ib):
for x in range(450, 470):
for y in range(450, 470):
ib.setRGB(x,y, 0)
def load_ref_img(reload = False, frames=FRAMES):
global ip_ref, ip_ref_e, ip_ref_f, ip_ref_fe
if reload or "ip_ref_fe" not in globals():
print "Loading cover reference image"
roi =get_roi_img(RADIUS, 0, 0, frames)
ip_ref = load_image(roi, title="Ref")
ip_ref_e =get_edge_img(roi)
ip_ref_f = image_fft(ip_ref)
ip_ref_fe = image_fft(ip_ref_e)
load_ref_img()
def load_cur_img(frames=FRAMES):
global ip_cur, ip_cur_e, ip_cur_f, ip_cur_fe
roi =get_roi_img(RADIUS, -offset, -offset, frames)
if add_mark:
put_mark(roi)
ip_cur = load_image(roi, title="Ref")
ip_cur_e =get_edge_img(roi)
ip_cur_f = image_fft(ip_cur)
ip_cur_fe = image_fft(ip_cur_e)
load_cur_img()
#show_panel(ip1e.getBufferedImage())
#show_panel(ip2e.getBufferedImage())
coef_img, _ = correlator.getCorrelation(ip_ref, ip_cur)
coef_ed, _ = correlator.getCorrelation(ip_ref_e, ip_cur_e)
coef_fft, _ = correlator.getCorrelation(ip_ref_f, ip_cur_f)
coef_ffte, _ = correlator.getCorrelation(ip_ref_fe, ip_cur_fe)
#show_panel(sub1)
#sub = ImagingUtils.sub(BufferedImage, BufferedImage, boolean)
#sub = load_image(sub, title="sub")
#sube = load_image(sube, title="sube")
if show:
st=create_stack([ip_ref, ip_cur, ip_ref_e, ip_cur_e, ip_ref_f, ip_cur_f, ip_ref_fe, ip_cur_fe])
st.show()
def get_min(ip1):
return ip1.getProcessor().getStatistics().min
def mean_abs_error(ip1, ip2):
sum = 0.0
for y in range(ip1.getHeight()):
for x in range(ip1.getWidth()):
p1 = ip1.getPixel(x, y)
p2 = ip2.getPixel(x, y)
sum += abs(p1 - p2)
return sum / (ip1.height * ip1.width )
def rms_error(ip1, ip2):
sum = 0.0
for y in range(ip1.getHeight()):
for x in range(ip1.getWidth()):
p1 = ip1.getPixel(x, y)
p2 = ip2.getPixel(x, y)
sum += math.pow((p1 - p2),2)
return sum / (ip1.height * ip1.width )
mean_err, mean_erre = mean_abs_error(ip_ref_f.getProcessor(), ip_cur_f.getProcessor()), mean_abs_error(ip_ref_fe.getProcessor(), ip_cur_fe.getProcessor())
rms_err, rms_erre = rms_error(ip_ref_f.getProcessor(), ip_cur_f.getProcessor()), rms_error(ip_ref_fe.getProcessor(), ip_cur_fe.getProcessor())
if show:
#print offset, coef_img, coef_ed, coef_fft, coef_ffte
print coef_fft, coef_ffte
print mean_err, mean_erre
print rms_err, rms_erre
+40
View File
@@ -0,0 +1,40 @@
class CoefFFT(ReadonlyRegisterBase):
def doRead(self):
return coef_fft
add_device(CoefFFT(), True)
CoefFFT.polling=1000
class CoefFFTE(ReadonlyRegisterBase):
def doRead(self):
return coef_ffte
add_device(CoefFFTE(), True)
CoefFFTE.polling=1000
class MeanErr(ReadonlyRegisterBase):
def doRead(self):
return mean_err
add_device(MeanErr(), True)
MeanErr.polling=1000
class MeanErrE(ReadonlyRegisterBase):
def doRead(self):
return mean_erre
add_device(MeanErrE(), True)
MeanErrE.polling=1000
class RmsErr(ReadonlyRegisterBase):
def doRead(self):
return rms_err
add_device(RmsErr(), True)
RmsErr.polling=1000
class RmsErrE(ReadonlyRegisterBase):
def doRead(self):
return rms_erre
add_device(RmsErrE(), True)
RmsErrE.polling=1000
#print coef_fft, coef_ffte
#print mean_err, mean_erre
#print rms_err, rms_erre