This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
"simpleEditor" : false,
|
||||
"hideEditorLineNumbers" : false,
|
||||
"hideEditorContextMenu" : false,
|
||||
"consoleLocation" : "Left",
|
||||
"consoleLocation" : "Status",
|
||||
"dataPanelLocation" : null,
|
||||
"openDataFilesInDocTab" : false,
|
||||
"noVariableEvaluationPropagation" : false,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#Tue Sep 17 18:09:54 CEST 2024
|
||||
#Fri Sep 20 10:59:23 CEST 2024
|
||||
barcode_reader_scan_pucks=false
|
||||
beamline_status_enabled=false
|
||||
cold_position_timeout=3600
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
#Tue Sep 17 18:09:58 CEST 2024
|
||||
center_x=820.0
|
||||
center_y=570.0
|
||||
#Fri Sep 20 10:59:27 CEST 2024
|
||||
center_x=917.0
|
||||
center_y=1015.0
|
||||
continuous=false
|
||||
correlation_threshold=0.0
|
||||
diam_dewar=null
|
||||
diam_disk=null
|
||||
diam_target=null
|
||||
diameter_target=95
|
||||
diamter_dewar=1800
|
||||
diamter_disk=670
|
||||
mask_dewar=null
|
||||
mask_disk=null
|
||||
max_detect_offset=10
|
||||
modulo=3
|
||||
number_images=2
|
||||
offset_threshold=null
|
||||
open_strategy=both
|
||||
scale_x=0.3
|
||||
scale_y=0.3
|
||||
threshold=0.6
|
||||
size_mask_dewar=0.98
|
||||
size_mask_disk=0.8
|
||||
threshold=0.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#Wed Sep 04 15:28:07 CEST 2024
|
||||
#Fri Sep 20 09:24:26 CEST 2024
|
||||
colormap=Grayscale
|
||||
colormapAutomatic=true
|
||||
colormapLogarithmic=false
|
||||
|
||||
@@ -11,12 +11,20 @@ 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
|
||||
self.correlation_threshold = 0.60
|
||||
self.diameter_target=95
|
||||
self.diamter_disk=670
|
||||
self.diamter_dewar=1800
|
||||
self.size_mask_disk=0.8
|
||||
self.size_mask_dewar=0.98
|
||||
self.max_detect_offset=10
|
||||
self.open_strategy = "both"
|
||||
|
||||
class CoverCorrelation(ReadonlyAsyncRegisterBase):
|
||||
def __init__(self, name):
|
||||
ReadonlyAsyncRegisterBase.__init__(self, name)
|
||||
self.precision = 3
|
||||
|
||||
def set(self, value):
|
||||
self.onReadout(value)
|
||||
|
||||
@@ -96,7 +104,12 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
|
||||
ip = integrate(self.images)
|
||||
try:
|
||||
self.error = None
|
||||
x,y = detect(ip)
|
||||
center = (self.config.center_x, self.config.center_y)
|
||||
x,y = detect(ip, center, \
|
||||
diam_target=self.config.diameter_target, diam_disk= self.config.diamter_disk, diam_dewar=self.config.diamter_dewar, \
|
||||
mask_disk=self.config.size_mask_disk, mask_dewar=self.config.size_mask_dewar, \
|
||||
offset_threshold=self.config.max_detect_offset ,open_strategy= self.config.open_strategy)
|
||||
|
||||
except Exception as e:
|
||||
self.error = e
|
||||
x,y = -1, -1
|
||||
@@ -170,7 +183,7 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray):
|
||||
|
||||
def set_correlation(self, corr):
|
||||
self.corr = corr
|
||||
error = corr is not None and corr < self.config.threshold
|
||||
error = corr is not None and corr < self.config.correlation_threshold
|
||||
if error != self.correlation_error:
|
||||
self.correlation_error = error
|
||||
if error:
|
||||
|
||||
@@ -80,13 +80,19 @@ class VmbCamera (CameraBase):
|
||||
self.write_parameter("BinningHorizontal", value)
|
||||
|
||||
def getBinningX(self):
|
||||
return self.read_parameter("BinningHorizontal")
|
||||
try:
|
||||
return self.read_parameter("BinningHorizontal")
|
||||
except:
|
||||
return 1
|
||||
|
||||
def setBinningY(self, value):
|
||||
self.write_parameter("BinningVertical", value)
|
||||
|
||||
def getBinningY(self):
|
||||
return self.read_parameter("BinningVertical")
|
||||
try:
|
||||
return self.read_parameter("BinningVertical")
|
||||
except:
|
||||
return 1
|
||||
|
||||
def setROI(self, x, y, w, h):
|
||||
self.write_parameter("OffsetX", 0)
|
||||
|
||||
@@ -32,7 +32,7 @@ def rms_error(ip1, ip2):
|
||||
|
||||
|
||||
|
||||
def get_roi_img(img, img_size=1024, radius=512, offset_x=0, offset_y=0):
|
||||
def get_roi_img(img, img_size=1024, radius=800, 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
|
||||
|
||||
@@ -3,15 +3,24 @@ 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
|
||||
OFFSET_THRESHOLD= 10 #PIXELS
|
||||
MASK_SIZE = 0.8 # of DIAM_2
|
||||
def set_circle_mask(ip, center_x, center_y, radius, bitwise=False):
|
||||
w, h = ip.getWidth(), ip.getHeight()
|
||||
if bitwise:
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
distance = math.hypot(x - center_x, y - center_y)
|
||||
if distance >radius:
|
||||
ip.putPixel(x, y, 0)
|
||||
else:
|
||||
mask = ip.createProcessor(w, h) # Creates a new blank ImageProcessor
|
||||
mask.setColor(255) # Set the drawing color to white (255)
|
||||
mask.fillOval(int(center_x - radius), int(center_y - radius), int(2 * radius), int(2 * radius)) # 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
|
||||
|
||||
|
||||
def detect(ip, print_table=False, output_image=False):
|
||||
def detect( ip, center=None, diam_target=95, diam_disk=670, diam_dewar=1800, mask_disk=0.8, mask_dewar=0.98, offset_threshold=10,\
|
||||
open_strategy = "both", print_table=False, output_image=False):
|
||||
if output_image==True:
|
||||
output_image= "outlines"
|
||||
if ip.getProcessor().isGrayscale():
|
||||
@@ -20,58 +29,55 @@ def detect(ip, print_table=False, output_image=False):
|
||||
ig = grayscale(ip, in_place=False)
|
||||
#Threshoolding
|
||||
it = auto_threshold(ig, dark_background=True, in_place=False)
|
||||
w, h = it.getWidth(), it.getHeight()
|
||||
ip = it.getProcessor()
|
||||
w, h = ip.getWidth(), ip.getHeight()
|
||||
if center is None:
|
||||
center = (int(w/2), int(h/2))
|
||||
|
||||
if mask_dewar>0:
|
||||
set_circle_mask(ip, center_x=center[0], center_y=center[1], radius=diam_dewar*(mask_dewar/2.0), bitwise=False)
|
||||
|
||||
#it.show()
|
||||
if OPEN_STRATEGY in ("black", "both"): #Refine inner
|
||||
if open_strategy in ("black", "both"): #Refine inner (target)
|
||||
binary_open(it, dark_background=True, iterations=1, count=1);
|
||||
if OPEN_STRATEGY in ("white", "both"): #Refine outter
|
||||
if open_strategy in ("white", "both"): #Refine outer (disk)
|
||||
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)
|
||||
#Detect outer white circle: disk
|
||||
px = int(pow(diam_disk/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 "")
|
||||
msg = "Disk 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)
|
||||
|
||||
if mask_disk>0:
|
||||
set_circle_mask(ip, center_x=x2, center_y=x2, radius=diam_disk*(mask_disk/2.0), bitwise=False)
|
||||
|
||||
#Detect inner black circle: target
|
||||
px = int(pow(diam_target/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, \
|
||||
fill_holes = True, 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 "")
|
||||
msg = "Target 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) > OFFSET_THRESHOLD or abs(y1-y2) > OFFSET_THRESHOLD:
|
||||
msg = "Detection offset error: " + + "(" + str(x1-x2) + ", " + str(y1-y2) + ")"
|
||||
if abs(x1-x2) > offset_threshold or abs(y1-y2) > offset_threshold:
|
||||
msg = "Disk/Target offset error: " + "(" + str(int(x1-x2)) + ", " + str(int(y1-y2)) + ")"
|
||||
raise Exception( msg )
|
||||
|
||||
return x1,y1
|
||||
|
||||
9
script/test/TestEdgeFFT.py
Normal file
9
script/test/TestEdgeFFT.py
Normal file
@@ -0,0 +1,9 @@
|
||||
roi =get_roi_img(image.output, img_size=1800, radius=800)
|
||||
img = load_image(roi, title="ip_ref")
|
||||
imge =get_edge_img(roi)
|
||||
imgf = image_fft(img)
|
||||
imgfe = image_fft(imge)
|
||||
|
||||
|
||||
st=create_stack([img, imge,imgf, imgfe])
|
||||
st.show()
|
||||
Reference in New Issue
Block a user