This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user