diff --git a/config/preferences.json b/config/preferences.json index 169fd60..8e49321 100644 --- a/config/preferences.json +++ b/config/preferences.json @@ -46,7 +46,7 @@ "simpleEditor" : false, "hideEditorLineNumbers" : false, "hideEditorContextMenu" : false, - "consoleLocation" : "Left", + "consoleLocation" : "Status", "dataPanelLocation" : null, "openDataFilesInDocTab" : false, "noVariableEvaluationPropagation" : false, diff --git a/config/settings.properties b/config/settings.properties index 13da492..0905ce0 100644 --- a/config/settings.properties +++ b/config/settings.properties @@ -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 diff --git a/devices/cover_detection.properties b/devices/cover_detection.properties index 532b194..37b3411 100644 --- a/devices/cover_detection.properties +++ b/devices/cover_detection.properties @@ -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 diff --git a/devices/image.properties b/devices/image.properties index 7da52bd..72317ce 100644 --- a/devices/image.properties +++ b/devices/image.properties @@ -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 diff --git a/script/devices/CoverDetection.py b/script/devices/CoverDetection.py index 1a26b20..caaa685 100644 --- a/script/devices/CoverDetection.py +++ b/script/devices/CoverDetection.py @@ -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: diff --git a/script/devices/VmbCamera.py b/script/devices/VmbCamera.py index 3851b91..9e286d9 100644 --- a/script/devices/VmbCamera.py +++ b/script/devices/VmbCamera.py @@ -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) diff --git a/script/imgproc/NewCoverCorrelation.py b/script/imgproc/NewCoverCorrelation.py index 565352b..ae686a0 100644 --- a/script/imgproc/NewCoverCorrelation.py +++ b/script/imgproc/NewCoverCorrelation.py @@ -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 diff --git a/script/imgproc/NewCoverDetection.py b/script/imgproc/NewCoverDetection.py index c5d8da2..326768a 100644 --- a/script/imgproc/NewCoverDetection.py +++ b/script/imgproc/NewCoverDetection.py @@ -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 diff --git a/script/test/TestEdgeFFT.py b/script/test/TestEdgeFFT.py new file mode 100644 index 0000000..c3a32cc --- /dev/null +++ b/script/test/TestEdgeFFT.py @@ -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()