87 lines
3.5 KiB
Python
87 lines
3.5 KiB
Python
import math
|
|
from ijutils import *
|
|
import ij.process.Blitter as Blitter
|
|
|
|
|
|
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, 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():
|
|
ig = ip
|
|
else:
|
|
ig = grayscale(ip, in_place=False)
|
|
#Threshoolding
|
|
it = auto_threshold(ig, dark_background=True, in_place=False)
|
|
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 (target)
|
|
binary_open(it, dark_background=True, iterations=1, count=1);
|
|
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: 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 = "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)
|
|
|
|
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 = True, exclude_edges = True, print_table=print_table, \
|
|
output_image = output_image, minCirc = 0.8, maxCirc = 1.0)
|
|
|
|
if res1.size() != 1:
|
|
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 = "Disk/Target offset error: " + "(" + str(int(x1-x2)) + ", " + str(int(y1-y2)) + ")"
|
|
raise Exception( msg )
|
|
|
|
return x1,y1
|
|
|
|
|
|
|