コード例 #1
0
ファイル: util.py プロジェクト: xorrhks0216/pr0ntools
def center_anchor_by_fn(pto):
	'''Rely on filename to make an anchor estimate'''
	pto.parse()
	m = ImageCoordinateMap.from_tagged_file_names(pto.get_file_names())
	# Chose a decent center image
	fn = m.get_image(int(m.width() / 2), int(m.height() / 2))
	print 'Selected %s as anchor' % fn
	anchor(pto, pto.get_image_by_fn(fn))
コード例 #2
0
def center_anchor_by_fn(pto):
    '''Rely on filename to make an anchor estimate'''
    pto.parse()
    m = ImageCoordinateMap.from_tagged_file_names(pto.get_file_names())
    # Chose a decent center image
    fn = m.get_image(int(m.width() / 2), int(m.height() / 2))
    dbg('Selected %s as anchor' % fn)
    anchor(pto, pto.get_image_by_fn(fn))
コード例 #3
0
ファイル: tile.py プロジェクト: xorrhks0216/pr0ntools
	def __init__(self, file_names, max_level, min_level = 0, out_dir_base=None):
		self.map = ImageCoordinateMap.from_tagged_file_names(file_names)
		#self.map.debug_print()
		self.max_level = max_level
		self.min_level = min_level
		self.out_dir_base = out_dir_base
		#self.set_out_extension('.png')
		self.set_out_extension('.jpg')
		self.zoom_factor = 2
		self.t_width = 250
		self.t_height = 250
		# JPEG quality level, 1-100 or something
		self.quality = 70
コード例 #4
0
    def __init__(self, dir_in, threads=1):
        print "TileMapSource()"
        self.tw = 250
        self.th = 250
        self.threads = threads

        self.file_names = set()
        for f in os.listdir(dir_in):
            self.file_names.add(dir_in + "/" + f)
        self.src_dir = dir_in

        self.map = ImageCoordinateMap.from_tagged_file_names(self.file_names)

        self.x_tiles = self.map.width()
        self.y_tiles = self.map.height()

        print "Tile canvas width %d, height %d" % (self.width(), self.height())

        MapSource.__init__(self)
コード例 #5
0
ファイル: map.py プロジェクト: ferdna/pr0ntools
    def __init__(self, dir_in, threads=1):
        print 'TileMapSource()'
        self.tw = 250
        self.th = 250
        self.threads = threads

        self.file_names = set()
        for f in os.listdir(dir_in):
            self.file_names.add(dir_in + "/" + f)
        self.src_dir = dir_in

        self.map = ImageCoordinateMap.from_tagged_file_names(self.file_names)

        self.x_tiles = self.map.width()
        self.y_tiles = self.map.height()

        print 'Tile canvas width %d, height %d' % (self.width(), self.height())

        MapSource.__init__(self)
コード例 #6
0
ファイル: map.py プロジェクト: xorrhks0216/pr0ntools
	def __init__(self, dir_in):
		print 'TileMapSource()'
		tw = None
		th = None
		
		tw = 256
		th = 256
		self.file_names = set()
		for f in os.listdir(dir_in):
			self.file_names.add(dir_in + "/" + f)
		
		self.dir_in = dir_in
		self.map = ImageCoordinateMap.from_tagged_file_names(self.file_names)
		
		self.x_tiles = self.map.width()
		self.y_tiles = self.map.height()
		self.tw = tw
		self.th = th
		
		print 'Tile canvas width %d, height %d' % (self.width(), self.height())
		
		MapSource.__init__(self)
コード例 #7
0
def linear_reoptimize(pto, pto_ref = None, allow_missing = False, order = 2, border = False):
	'''Change XY positions to match the trend in a linear XY positioned project (ex from XY stage).  pto must have all images in pto_ref '''
	if scipy is None:
		raise Exception('Re-optimizing requires scipi')
	
	if order is 0:
		raise Exception('Can not have order 0')
	if type(order) != type(0):
		raise Exception('Order is bad type')
	
	'''
	Our model should be like this:
	-Each axis will have some degree of backlash.  This backlash will create a difference between adjacent rows / cols
	-Axes may not be perfectly adjacent
		The naive approach would give:
			x = c * dx + xc
			y = r * dy + yc
		But really we need this:
			x = c * dx + r * dx/dy + xc
			y = c * dy/dx + r * dy + yc
		Each equation can be solved separately
		Need 3 points to solve each and should be in the expected direction of that line
		
		
	Perform a linear regression on each row/col?
	Might lead to very large y = mx + b equations for the column math
	'''
	
	if pto_ref is None:
		pto_ref = pto

	'''
	Phase 1: calculate linear system
	'''
	# Start by building an image coordinate map so we know what x and y are
	pto_ref.parse()
	ref_fns = pto_ref.get_file_names()
	real_fns = pto.get_file_names()
	print 'Files (all: %d, ref: %d):' % (len(real_fns), len(ref_fns))
	for fn in real_fns:
		if fn in ref_fns:
			ref_str = '*'
		else:
			ref_str = ' '
		print '  %s%s' % (ref_str, fn)
	m_ref = ImageCoordinateMap.from_tagged_file_names(ref_fns)
	m_real = ImageCoordinateMap.from_tagged_file_names(real_fns)
	#m.debug_print()
	
	'''
	Ultimately trying to form this equation
	x = c0 * c + c1 * r + c2
	y = c3 * c + c4 * r + c5
	
	Except that constants will also have even and odd varities
	c2 and c5 will be taken from reasonable points of reference, likely (0, 0) or something like that
	'''
	
	c0s = []
	c1s = []
	c3s = []
	c4s = []
	for cur_order in range(order):
		# Given a column find x (primary x)
		c0s.append(regress_c0(m_ref, pto_ref, xrange(cur_order, m_ref.height(), order), allow_missing))
		c1s.append(regress_c1(m_ref, pto_ref, xrange(cur_order, m_ref.width(), order), allow_missing))
		# Given a row find y (primary y)
		c3s.append(regress_c3(m_ref, pto_ref, xrange(cur_order, m_ref.height(), order), allow_missing))
		c4s.append(regress_c4(m_ref, pto_ref, xrange(cur_order, m_ref.width(), order), allow_missing))

	# Now chose a point in the center
	# it doesn't have to be a good fitting point in the old system, it just has to be centered
	# Fix at the origin
	
	'''
	Actually the even and the odd should have the same slope
	The only difference should be their offset
	'''
	c2 = None
	c5 = None
	
	if 0:
		print 'Solution found'
		print '  x = %g c + %g r + TBD' % (c0, c1)
		print '  y = %g c + %g r + TBD' % (c3, c4)
	

	# Verify the solution matrix by checking it against the reference project
	print
	print 'Verifying reference solution matrix....'
	# Entire reference is assumed to be good always, no border
	(c2s_ref, c5s_ref) = calc_constants(order, m_ref, pto_ref, c0s, c1s, c3s, c4s, m_ref, allow_missing)
	#c1s = [c1 + 12 for c1 in c1s]
	# Print the solution matrx for debugging
	for cur_order in range(order):
		# XXX: if we really cared we could center these up
		# its easier to just run the centering algorithm after though if one cares
		print 'Reference order %d solution:' % cur_order
		print '  x = %g c + %g r + %g' % (c0s[cur_order], c1s[cur_order], c2s_ref[cur_order])
		print '  y = %g c + %g r + %g' % (c3s[cur_order], c4s[cur_order], c5s_ref[cur_order])
	calc_ref_xs = []
	calc_ref_ys = []
	ref_xs = []
	ref_ys = []
	print 'Errors:'
	x_last = None
	y_last = None
	for col in range(m_ref.width()):
		for row in range(m_ref.height()):
			fn = m_ref.get_image(col, row)
			if fn is None:
				continue
			il = pto_ref.get_image_by_fn(fn)
			col_eo = col % order
			row_eo = row % order
			x_calc = c0s[row_eo] * col + c1s[row_eo] * row + c2s_ref[row_eo]
			y_calc = c3s[col_eo] * col + c4s[col_eo] * row + c5s_ref[col_eo]
			calc_ref_xs.append(x_calc)
			calc_ref_ys.append(y_calc)
			x_orig = il.x()
			y_orig = il.y()
			ref_xs.append(x_orig)
			ref_ys.append(y_orig)
			print '  c%d r%d: x%g y%g (x%g, y%g)' % (col, row, x_calc - x_orig, y_calc - y_orig, x_orig, y_orig)
			if col > 0:
				fn_old = m_ref.get_image(col - 1, row)
				if fn_old:
					il_old = pto_ref.get_image_by_fn(fn_old)
					print '    dx: %g' % (il.x() - il_old.x())
					if col > 1:
						'''
						x1' = x1 - x0
						x2' = x2 - x1
						x2'' = x2' - x1' = (x2 - x1) - (x1 - x0) = x2 - 2 x1 + x0
						'''
						fn_old2 = m_ref.get_image(col - 2, row)
						if fn_old2:
							il_old2 = pto_ref.get_image_by_fn(fn_old2)
							print '    dx2: %g' % (il.x() - 2 * il_old.x() + il_old2.x())
			if row != 0:
				fn_old = m_ref.get_image(col, row - 1)
				if fn_old:
					il_old = pto_ref.get_image_by_fn(fn_old)
					print '    dy: %g' % (il.y() - il_old.y())
					if row > 1:
						fn_old2 = m_ref.get_image(col, row - 2)
						if fn_old2:
							il_old2 = pto_ref.get_image_by_fn(fn_old2)
							print '    dy2: %g' % (il.y() - 2 * il_old.y() + il_old2.y())
	x_ref_rms_error = rms_error_diff(calc_ref_xs, ref_xs)
	y_ref_rms_error = rms_error_diff(calc_ref_ys, ref_ys)
	print 'Reference RMS error x%g y%g' % (x_ref_rms_error, y_ref_rms_error)
	print
	#exit(1)
	
	'''
	The reference project might not start at 0,0
	Therefore scan through to find some good starting positions so that we can calc each point
	in the final project
	'''
	print 'Anchoring solution...'
	'''
	Calculate the constant at each reference image
	Compute reference positions from these values
	'''
	
	'''
	FIXME: we have to calculate these initially and then re-calc for border if required
	if top_bottom_backlash and border:
		row_border = 1
	else:
		row_border = 0
	if left_right_backlash and border:
		col_border = 1
	else:
		col_border = 0
	'''
	row_border = 0
	col_border = 0
	
	(c2s, c5s) = calc_constants(order, m_real, pto_ref, c0s, c1s, c3s, c4s, m_ref, allow_missing, col_border, row_border)
	#c2s = [c2 + 30 for c2 in c2s]
		
	# Print the solution matrx for debugging
	for cur_order in range(order):
		# XXX: if we really cared we could center these up
		# its easier to just run the centering algorithm after though if one cares
		print 'Order %d solution:' % cur_order
		print '  x = %g c + %g r + %g' % (c0s[cur_order], c1s[cur_order], c2s[cur_order])
		print '  y = %g c + %g r + %g' % (c3s[cur_order], c4s[cur_order], c5s[cur_order])
	
	c2_rms = rms_errorl(c2s)
	c5_rms = rms_errorl(c5s)
	print 'RMS offset error x%g y%g' % (c2_rms, c5_rms)
	left_right_backlash = False
	top_bottom_backlash = False
	if c2_rms > c5_rms:
		print 'x offset varies most, expect left-right scanning'
		left_right_backlash = True
	else:
		print 'y offset varies most, expect top-bottom scanning'
		top_bottom_backlash = True
	#exit(1)
	'''
	We have the solution matrix now so lets roll
	'''
	optimized = set()
	for col in range(col_border, m_real.width() - col_border):
		for row in range(row_border, m_real.height() - row_border):
			fn = m_real.get_image(col, row)
			il = pto.get_image_by_fn(fn)

			if fn is None:
				if not allow_missing:
					raise Exception('Missing item')
				continue
			
			col_eo = col % order
			row_eo = row % order
			
			# FIRE!
			# take the dot product
			x = c0s[row_eo] * col + c1s[row_eo] * row + c2s[row_eo]
			y = c3s[col_eo] * col + c4s[col_eo] * row + c5s[col_eo]
			# And push it out
			#print '%s: c%d r%d => x%g y%d' % (fn, col, row, x, y)
			il.set_x(x)
			il.set_y(y)
			#print il
			optimized.add(fn)
	'''
	Finally manually optimize those that were in the border area
	'''
	if border:
		# Gather all file names
		# There are essentially four cases to do this faster but be lazy since it will still be O(images)
		to_manually_optimize = set()
		for col in range(0, m_real.width()):
			for row in range(m_real.height()):
				fn = m_real.get_image(col, row)
				il = pto.get_image_by_fn(fn)

				if fn is None:
					if not allow_missing:
						raise Exception('Missing item')
					continue
				if fn in optimized:
					continue
				to_manually_optimize.add(fn)
		# Prepare the pto to operate on the ones we want
		optimize_xy_only_for_images(pto, to_manually_optimize)
		# and run
		optimizer = PTOptimizer(pto)
		# Don't clear out the xy data we just calculated
		optimizer.reoptimize = False
		optimizer.run()
コード例 #8
0
ファイル: pr0nshift.py プロジェクト: ferdna/pr0ntools
            # Delete the old key
            del icm.layout[(col + 1, row)]
        # Nothing to shift in
        except KeyError:
            pass

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Manipulate .pto files')
    parser.add_argument('--dry', action='store_true', help='Dont actually do anything')
    parser.add_argument('dir', help='Image directory to work on')
    parser.add_argument('actions', nargs='+', help='Actions to perform')
    args = parser.parse_args()

    print 'Constructing ICM'
    working_set = set(glob.glob(os.path.join(args.dir, '*.jpg')))
    icm = ImageCoordinateMap.from_tagged_file_names(working_set)
    print 'ICM ready'
    
    for action in args.actions:
        print 'Action: %s' % action
        
        m = re.match('r([0-9]+)-', action)
        if m:
            row = int(m.group(1))
            print 'Remove row %d' % row
            # if additional rows exist shift them
            for cur_row in xrange(row + 1, icm.rows):
                for cur_col in xrange(icm.cols):
                    fn = icm.get_image(cur_col, cur_row)
                    icm.set_image(cur_col, cur_row - 1, fn)
                    icm.set_image(cur_col, cur_row, None)
コード例 #9
0
from pr0ntools.stitch.image_coordinate_map import ImageCoordinateMap
import subprocess
import shutil

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='create tiles from unstitched images')
    parser.add_argument('--border', default='1', help='border size')
    parser.add_argument('pto', default='out.pto', nargs='?', help='pto project')
    args = parser.parse_args()
    args.border = int(args.border, 0)
    
    pto_orig = PTOProject.from_file_name(args.pto)
    img_fns = []
    for il in pto_orig.get_image_lines():
        img_fns.append(il.get_name())
    icm = ImageCoordinateMap.from_tagged_file_names(img_fns)
    
    # Reduced .pto
    pto_red = pto_orig.copy()
    # Delete all lines not in the peripheral
    pto_orig.build_image_fn_map()
    ils_del = []
    for y in xrange(args.border, icm.height() - args.border):
        for x in xrange(args.border, icm.width() - args.border):
            im = icm.get_image(x, y)
            if im is None:
                continue
            ils_del.append(pto_orig.img_fn2il[im])
    print 'Deleting %d / %d images' % (len(ils_del), icm.width() * icm.height())
    pto_red.del_images(ils_del)
    pto_red.save_as(pto_orig.file_name.replace('.pto', '_sm.pto'), is_new_filename=True)
コード例 #10
0
ファイル: tile_opt.py プロジェクト: ferdna/pr0ntools
def linearize(pto, pto_ref=None, allow_missing=False, order=2):
    if order is 0:
        raise Exception('Can not have order 0')
    if type(order) != type(0):
        raise Exception('Order is bad type')
    '''
    Our model should be like this:
    -Each axis will have some degree of backlash.  This backlash will create a difference between adjacent rows / cols
    -Axes may not be perfectly adjacent
        The naive approach would give:
            x = c * dx + xc
            y = r * dy + yc
        But really we need this:
            x = c * dx + r * dx/dy + xc
            y = c * dy/dx + r * dy + yc
        Each equation can be solved separately
        Need 3 points to solve each and should be in the expected direction of that line
        
        
    Perform a linear regression on each row/col?
    Might lead to very large y = mx + b equations for the column math
    '''

    if pto_ref is None:
        pto_ref = pto
    '''
    Phase 1: calculate linear system
    '''
    # Start by building an image coordinate map so we know what x and y are
    pto_ref.parse()
    ref_fns = pto_ref.get_file_names()
    real_fns = pto.get_file_names()
    print 'Files (all: %d, ref: %d):' % (len(real_fns), len(ref_fns))
    if 0:
        for fn in real_fns:
            if fn in ref_fns:
                ref_str = '*'
            else:
                ref_str = ' '
            print '  %s%s' % (ref_str, fn)
    m_ref = ImageCoordinateMap.from_tagged_file_names(ref_fns)
    # Ref likely does not cover the entire map
    ((ref_x0, ref_x1), (ref_y0, ref_y1)) = m_ref.active_box()
    print 'Reference map uses x(%d:%d), y(%d:%d)' % (ref_x0, ref_x1, ref_y0,
                                                     ref_y1)

    #m_real = ImageCoordinateMap.from_tagged_file_names(real_fns)
    #print 'Real map uses x(%d:%d), y(%d:%d)' % (ref_x0, ref_x1, ref_y0, ref_y1)
    #m.debug_print()
    '''
    Ultimately trying to form this equation
    x = c0 * c + c1 * r + c2
    y = c3 * c + c4 * r + c5
    
    Except that constants will also have even and odd varities
    c2 and c5 will be taken from reasonable points of reference, likely (0, 0) or something like that
    '''

    c0s = []
    c1s = []
    c3s = []
    c4s = []
    for cur_order in xrange(order):
        # Ex: ref_x0 = 3
        # cur_order 0: start 4
        # cur_order 1: start 3
        if ref_x0 % order == cur_order:
            reg_x0 = ref_x0
        else:
            reg_x0 = ref_x0 + 1
        if ref_y0 % order == cur_order:
            reg_y0 = ref_y0
        else:
            reg_y0 = ref_y0 + 1
        reg_x1 = ref_x1
        reg_y1 = ref_y1
        print 'Order %d: using x(%d:%d), y(%d:%d)' % (cur_order, reg_x0,
                                                      reg_x1, reg_y0, reg_y1)

        # Given a column find x (primary x)
        # dependence of x on col in specified rows
        c0s.append(
            regress_row(m_ref,
                        pto_ref,
                        cols=xrange(reg_x0, reg_x1 + 1, order),
                        rows=xrange(reg_y0, reg_y1 + 1, order),
                        selector=lambda x: x.x(),
                        allow_missing=allow_missing))
        # dependence of x on row in specified cols
        c1s.append(
            regress_col(m_ref,
                        pto_ref,
                        cols=xrange(reg_x0, reg_x1 + 1, order),
                        rows=xrange(reg_y0, reg_y1 + 1, order),
                        selector=lambda x: x.x(),
                        allow_missing=allow_missing))
        # Given a row find y (primary y)
        # dependence of y on col in specified rows
        c3s.append(
            regress_row(m_ref,
                        pto_ref,
                        cols=xrange(reg_x0, reg_x1 + 1, order),
                        rows=xrange(reg_y0, reg_y1 + 1, order),
                        selector=lambda x: x.y(),
                        allow_missing=allow_missing))
        # cdependence of y on row in specified cols
        c4s.append(
            regress_col(m_ref,
                        pto_ref,
                        cols=xrange(reg_x0, reg_x1 + 1, order),
                        rows=xrange(reg_y0, reg_y1 + 1, order),
                        selector=lambda x: x.y(),
                        allow_missing=allow_missing))

    # Now chose a point in the center
    # it doesn't have to be a good fitting point in the old system, it just has to be centered
    # Fix at the origin
    '''
    Actually the even and the odd should have the same slope
    The only difference should be their offset
    '''

    if 0:
        print 'Solution found'
        print '  x = %g c + %g r + TBD' % (c0s[0], c1s[0])
        print '  y = %g c + %g r + TBD' % (c3s[0], c4s[0])

    # Verify the solution matrix by checking it against the reference project
    print
    print 'Verifying reference solution matrix....'
    # Entire reference is assumed to be good always, no border
    (c2s_ref, c5s_ref) = calc_constants(order, m_ref, pto_ref, c0s, c1s, c3s,
                                        c4s, m_ref, allow_missing)
    #c1s = [c1 + 12 for c1 in c1s]
    # Print the solution matrx for debugging
    for cur_order in range(order):
        # XXX: if we really cared we could center these up
        # its easier to just run the centering algorithm after though if one cares
        print 'Reference order %d solution:' % cur_order
        print '  x = %g c + %g r + %g' % (c0s[cur_order], c1s[cur_order],
                                          c2s_ref[cur_order])
        print '  y = %g c + %g r + %g' % (c3s[cur_order], c4s[cur_order],
                                          c5s_ref[cur_order])

    return ((c0s, c1s, c2s_ref), (c3s, c4s, c5s_ref))
コード例 #11
0
ファイル: tile_opt.py プロジェクト: JohnDMcMaster/pr0ntools
def linearize(pto, pto_ref = None, allow_missing = False, order = 2):
    if order is 0:
        raise Exception('Can not have order 0')
    if type(order) != type(0):
        raise Exception('Order is bad type')
    
    '''
    Our model should be like this:
    -Each axis will have some degree of backlash.  This backlash will create a difference between adjacent rows / cols
    -Axes may not be perfectly adjacent
        The naive approach would give:
            x = c * dx + xc
            y = r * dy + yc
        But really we need this:
            x = c * dx + r * dx/dy + xc
            y = c * dy/dx + r * dy + yc
        Each equation can be solved separately
        Need 3 points to solve each and should be in the expected direction of that line
        
        
    Perform a linear regression on each row/col?
    Might lead to very large y = mx + b equations for the column math
    '''
    
    if pto_ref is None:
        pto_ref = pto

    '''
    Phase 1: calculate linear system
    '''
    # Start by building an image coordinate map so we know what x and y are
    pto_ref.parse()
    ref_fns = pto_ref.get_file_names()
    real_fns = pto.get_file_names()
    print 'Files (all: %d, ref: %d):' % (len(real_fns), len(ref_fns))
    if 0:
        for fn in real_fns:
            if fn in ref_fns:
                ref_str = '*'
            else:
                ref_str = ' '
            print '  %s%s' % (ref_str, fn)
    m_ref = ImageCoordinateMap.from_tagged_file_names(ref_fns)
    # Ref likely does not cover the entire map
    ((ref_x0, ref_x1), (ref_y0, ref_y1)) = m_ref.active_box()
    print 'Reference map uses x(%d:%d), y(%d:%d)' % (ref_x0, ref_x1, ref_y0, ref_y1)

    #m_real = ImageCoordinateMap.from_tagged_file_names(real_fns)
    #print 'Real map uses x(%d:%d), y(%d:%d)' % (ref_x0, ref_x1, ref_y0, ref_y1)
    #m.debug_print()
    
    '''
    Ultimately trying to form this equation
    x = c0 * c + c1 * r + c2
    y = c3 * c + c4 * r + c5
    
    Except that constants will also have even and odd varities
    c2 and c5 will be taken from reasonable points of reference, likely (0, 0) or something like that
    '''
    
    c0s = []
    c1s = []
    c3s = []
    c4s = []
    for cur_order in xrange(order):
        # Ex: ref_x0 = 3
        # cur_order 0: start 4
        # cur_order 1: start 3
        if ref_x0 % order == cur_order:
            reg_x0 = ref_x0
        else:
            reg_x0 = ref_x0 + 1
        if ref_y0 % order == cur_order:
            reg_y0 = ref_y0
        else:
            reg_y0 = ref_y0 + 1
        reg_x1 = ref_x1
        reg_y1 = ref_y1
        print 'Order %d: using x(%d:%d), y(%d:%d)' % (cur_order, reg_x0, reg_x1, reg_y0, reg_y1)

        # Given a column find x (primary x)
        # dependence of x on col in specified rows
        c0s.append(regress_row(m_ref, pto_ref,
                    cols=xrange(reg_x0, reg_x1 + 1, order), rows=xrange(reg_y0, reg_y1 + 1, order),
                    selector=lambda x: x.x(), allow_missing=allow_missing))
        # dependence of x on row in specified cols
        c1s.append(regress_col(m_ref, pto_ref,
                    cols=xrange(reg_x0, reg_x1 + 1, order), rows=xrange(reg_y0, reg_y1 + 1, order),
                    selector=lambda x: x.x(), allow_missing=allow_missing))
        # Given a row find y (primary y)
        # dependence of y on col in specified rows
        c3s.append(regress_row(m_ref, pto_ref,
                    cols=xrange(reg_x0, reg_x1 + 1, order), rows=xrange(reg_y0, reg_y1 + 1, order),
                    selector=lambda x: x.y(), allow_missing=allow_missing))
        # cdependence of y on row in specified cols
        c4s.append(regress_col(m_ref, pto_ref,
                    cols=xrange(reg_x0, reg_x1 + 1, order), rows=xrange(reg_y0, reg_y1 + 1, order),
                    selector=lambda x: x.y(), allow_missing=allow_missing))

    # Now chose a point in the center
    # it doesn't have to be a good fitting point in the old system, it just has to be centered
    # Fix at the origin
    
    '''
    Actually the even and the odd should have the same slope
    The only difference should be their offset
    '''
    
    if 0:
        print 'Solution found'
        print '  x = %g c + %g r + TBD' % (c0s[0], c1s[0])
        print '  y = %g c + %g r + TBD' % (c3s[0], c4s[0])

    # Verify the solution matrix by checking it against the reference project
    print
    print 'Verifying reference solution matrix....'
    # Entire reference is assumed to be good always, no border
    (c2s_ref, c5s_ref) = calc_constants(order, m_ref, pto_ref, c0s, c1s, c3s, c4s, m_ref, allow_missing)
    #c1s = [c1 + 12 for c1 in c1s]
    # Print the solution matrx for debugging
    for cur_order in range(order):
        # XXX: if we really cared we could center these up
        # its easier to just run the centering algorithm after though if one cares
        print 'Reference order %d solution:' % cur_order
        print '  x = %g c + %g r + %g' % (c0s[cur_order], c1s[cur_order], c2s_ref[cur_order])
        print '  y = %g c + %g r + %g' % (c3s[cur_order], c4s[cur_order], c5s_ref[cur_order])
    
    return ((c0s, c1s, c2s_ref), (c3s, c4s, c5s_ref))
コード例 #12
0
ファイル: linear_optimizer.py プロジェクト: ferdna/pr0ntools
def linear_reoptimize(pto,
                      pto_ref=None,
                      allow_missing=False,
                      order=2,
                      border=False):
    '''Change XY positions to match the trend in a linear XY positioned project (ex from XY stage).  pto must have all images in pto_ref '''
    if scipy is None:
        raise Exception('Re-optimizing requires scipi')

    if order is 0:
        raise Exception('Can not have order 0')
    if type(order) != type(0):
        raise Exception('Order is bad type')
    '''
	Our model should be like this:
	-Each axis will have some degree of backlash.  This backlash will create a difference between adjacent rows / cols
	-Axes may not be perfectly adjacent
		The naive approach would give:
			x = c * dx + xc
			y = r * dy + yc
		But really we need this:
			x = c * dx + r * dx/dy + xc
			y = c * dy/dx + r * dy + yc
		Each equation can be solved separately
		Need 3 points to solve each and should be in the expected direction of that line
		
		
	Perform a linear regression on each row/col?
	Might lead to very large y = mx + b equations for the column math
	'''

    if pto_ref is None:
        pto_ref = pto
    '''
	Phase 1: calculate linear system
	'''
    # Start by building an image coordinate map so we know what x and y are
    pto_ref.parse()
    ref_fns = pto_ref.get_file_names()
    real_fns = pto.get_file_names()
    print 'Files (all: %d, ref: %d):' % (len(real_fns), len(ref_fns))
    for fn in real_fns:
        if fn in ref_fns:
            ref_str = '*'
        else:
            ref_str = ' '
        print '  %s%s' % (ref_str, fn)
    m_ref = ImageCoordinateMap.from_tagged_file_names(ref_fns)
    m_real = ImageCoordinateMap.from_tagged_file_names(real_fns)
    #m.debug_print()
    '''
	Ultimately trying to form this equation
	x = c0 * c + c1 * r + c2
	y = c3 * c + c4 * r + c5
	
	Except that constants will also have even and odd varities
	c2 and c5 will be taken from reasonable points of reference, likely (0, 0) or something like that
	'''

    c0s = []
    c1s = []
    c3s = []
    c4s = []
    for cur_order in range(order):
        # Given a column find x (primary x)
        c0s.append(
            regress_c0(m_ref, pto_ref, xrange(cur_order, m_ref.height(),
                                              order), allow_missing))
        c1s.append(
            regress_c1(m_ref, pto_ref, xrange(cur_order, m_ref.width(), order),
                       allow_missing))
        # Given a row find y (primary y)
        c3s.append(
            regress_c3(m_ref, pto_ref, xrange(cur_order, m_ref.height(),
                                              order), allow_missing))
        c4s.append(
            regress_c4(m_ref, pto_ref, xrange(cur_order, m_ref.width(), order),
                       allow_missing))

    # Now chose a point in the center
    # it doesn't have to be a good fitting point in the old system, it just has to be centered
    # Fix at the origin
    '''
	Actually the even and the odd should have the same slope
	The only difference should be their offset
	'''
    c2 = None
    c5 = None

    if 0:
        print 'Solution found'
        print '  x = %g c + %g r + TBD' % (c0, c1)
        print '  y = %g c + %g r + TBD' % (c3, c4)

    # Verify the solution matrix by checking it against the reference project
    print
    print 'Verifying reference solution matrix....'
    # Entire reference is assumed to be good always, no border
    (c2s_ref, c5s_ref) = calc_constants(order, m_ref, pto_ref, c0s, c1s, c3s,
                                        c4s, m_ref, allow_missing)
    #c1s = [c1 + 12 for c1 in c1s]
    # Print the solution matrx for debugging
    for cur_order in range(order):
        # XXX: if we really cared we could center these up
        # its easier to just run the centering algorithm after though if one cares
        print 'Reference order %d solution:' % cur_order
        print '  x = %g c + %g r + %g' % (c0s[cur_order], c1s[cur_order],
                                          c2s_ref[cur_order])
        print '  y = %g c + %g r + %g' % (c3s[cur_order], c4s[cur_order],
                                          c5s_ref[cur_order])
    calc_ref_xs = []
    calc_ref_ys = []
    ref_xs = []
    ref_ys = []
    print 'Errors:'
    x_last = None
    y_last = None
    for col in range(m_ref.width()):
        for row in range(m_ref.height()):
            fn = m_ref.get_image(col, row)
            if fn is None:
                continue
            il = pto_ref.get_image_by_fn(fn)
            col_eo = col % order
            row_eo = row % order
            x_calc = c0s[row_eo] * col + c1s[row_eo] * row + c2s_ref[row_eo]
            y_calc = c3s[col_eo] * col + c4s[col_eo] * row + c5s_ref[col_eo]
            calc_ref_xs.append(x_calc)
            calc_ref_ys.append(y_calc)
            x_orig = il.x()
            y_orig = il.y()
            ref_xs.append(x_orig)
            ref_ys.append(y_orig)
            print '  c%d r%d: x%g y%g (x%g, y%g)' % (
                col, row, x_calc - x_orig, y_calc - y_orig, x_orig, y_orig)
            if col > 0:
                fn_old = m_ref.get_image(col - 1, row)
                if fn_old:
                    il_old = pto_ref.get_image_by_fn(fn_old)
                    print '    dx: %g' % (il.x() - il_old.x())
                    if col > 1:
                        '''
						x1' = x1 - x0
						x2' = x2 - x1
						x2'' = x2' - x1' = (x2 - x1) - (x1 - x0) = x2 - 2 x1 + x0
						'''
                        fn_old2 = m_ref.get_image(col - 2, row)
                        if fn_old2:
                            il_old2 = pto_ref.get_image_by_fn(fn_old2)
                            print '    dx2: %g' % (il.x() - 2 * il_old.x() +
                                                   il_old2.x())
            if row != 0:
                fn_old = m_ref.get_image(col, row - 1)
                if fn_old:
                    il_old = pto_ref.get_image_by_fn(fn_old)
                    print '    dy: %g' % (il.y() - il_old.y())
                    if row > 1:
                        fn_old2 = m_ref.get_image(col, row - 2)
                        if fn_old2:
                            il_old2 = pto_ref.get_image_by_fn(fn_old2)
                            print '    dy2: %g' % (il.y() - 2 * il_old.y() +
                                                   il_old2.y())
    x_ref_rms_error = rms_error_diff(calc_ref_xs, ref_xs)
    y_ref_rms_error = rms_error_diff(calc_ref_ys, ref_ys)
    print 'Reference RMS error x%g y%g' % (x_ref_rms_error, y_ref_rms_error)
    print
    #exit(1)
    '''
	The reference project might not start at 0,0
	Therefore scan through to find some good starting positions so that we can calc each point
	in the final project
	'''
    print 'Anchoring solution...'
    '''
	Calculate the constant at each reference image
	Compute reference positions from these values
	'''
    '''
	FIXME: we have to calculate these initially and then re-calc for border if required
	if top_bottom_backlash and border:
		row_border = 1
	else:
		row_border = 0
	if left_right_backlash and border:
		col_border = 1
	else:
		col_border = 0
	'''
    row_border = 0
    col_border = 0

    (c2s, c5s) = calc_constants(order, m_real, pto_ref, c0s, c1s, c3s, c4s,
                                m_ref, allow_missing, col_border, row_border)
    #c2s = [c2 + 30 for c2 in c2s]

    # Print the solution matrx for debugging
    for cur_order in range(order):
        # XXX: if we really cared we could center these up
        # its easier to just run the centering algorithm after though if one cares
        print 'Order %d solution:' % cur_order
        print '  x = %g c + %g r + %g' % (c0s[cur_order], c1s[cur_order],
                                          c2s[cur_order])
        print '  y = %g c + %g r + %g' % (c3s[cur_order], c4s[cur_order],
                                          c5s[cur_order])

    c2_rms = rms_errorl(c2s)
    c5_rms = rms_errorl(c5s)
    print 'RMS offset error x%g y%g' % (c2_rms, c5_rms)
    left_right_backlash = False
    top_bottom_backlash = False
    if c2_rms > c5_rms:
        print 'x offset varies most, expect left-right scanning'
        left_right_backlash = True
    else:
        print 'y offset varies most, expect top-bottom scanning'
        top_bottom_backlash = True
    #exit(1)
    '''
	We have the solution matrix now so lets roll
	'''
    optimized = set()
    for col in range(col_border, m_real.width() - col_border):
        for row in range(row_border, m_real.height() - row_border):
            fn = m_real.get_image(col, row)
            il = pto.get_image_by_fn(fn)

            if fn is None:
                if not allow_missing:
                    raise Exception('Missing item')
                continue

            col_eo = col % order
            row_eo = row % order

            # FIRE!
            # take the dot product
            x = c0s[row_eo] * col + c1s[row_eo] * row + c2s[row_eo]
            y = c3s[col_eo] * col + c4s[col_eo] * row + c5s[col_eo]
            # And push it out
            #print '%s: c%d r%d => x%g y%d' % (fn, col, row, x, y)
            il.set_x(x)
            il.set_y(y)
            #print il
            optimized.add(fn)
    '''
	Finally manually optimize those that were in the border area
	'''
    if border:
        # Gather all file names
        # There are essentially four cases to do this faster but be lazy since it will still be O(images)
        to_manually_optimize = set()
        for col in range(0, m_real.width()):
            for row in range(m_real.height()):
                fn = m_real.get_image(col, row)
                il = pto.get_image_by_fn(fn)

                if fn is None:
                    if not allow_missing:
                        raise Exception('Missing item')
                    continue
                if fn in optimized:
                    continue
                to_manually_optimize.add(fn)
        # Prepare the pto to operate on the ones we want
        optimize_xy_only_for_images(pto, to_manually_optimize)
        # and run
        optimizer = PTOptimizer(pto)
        # Don't clear out the xy data we just calculated
        optimizer.reoptimize = False
        optimizer.run()