def findStars(image): # find individual features image = threshHold(image) if doDumpFlat: import ImageIo ImageIo.dumpImage(image, "flat") labels, num_features = scipy.ndimage.label(image) if doDumpStars: dumpImage = image.copy() dumpImageMax = numpy.max(dumpImage) # remove small features sizes = scipy.ndimage.sum(image > 0, labels, range(num_features + 1)) # HARDCODED PARAMETER: removeSizeThreshhold # What is: Minimum size (in pixels) a signal clump needs to be to be considered a star # Adjust if: Small stars are getting rejected in --dump_stars OR large noise clumps are getting accepted # See also: keepThreshhold removeSizeThreshhold = 25 width, height = image.shape for maxx, maxy in scipy.ndimage.maximum_position(image, labels, [x for x in range(num_features + 1) if sizes[x] > removeSizeThreshhold]): maxx = int(maxx) # docs say maximum_position returns float maxy = int(maxy) sliceSize = 3 if maxx < sliceSize or maxy < sliceSize or maxx >= width - sliceSize or maxy >= height - sliceSize: continue slice = image[maxx - sliceSize:maxx + sliceSize, maxy - sliceSize:maxy + sliceSize] height, x, y, width_x, width_y = fitgaussian(slice) x += maxx - sliceSize y += maxy - sliceSize skewMax = max(width_x / width_y, width_y / width_x) if skewMax > 2: print("Invalid star found at", x, y, ": too skewed, factor", skewMax) continue if doDumpStars: width_r = (width_x + width_y) / 2 * 4 xx, yy = numpy.mgrid[:image.shape[0], :image.shape[1]] circle = (xx - x) ** 2 + (yy - y) ** 2 circle = numpy.logical_and(circle < width_r * width_r + 9, circle > width_r * width_r - 9) dumpImage += circle * dumpImageMax # print("Star at ", x, y, "of height", height, "of width", width_x, width_y) yield (height, x, y) if doDumpStars: import ImageIo ImageIo.dumpImage(dumpImage, "stars")
if __name__ == "__main__": argParser = argparse.ArgumentParser(description="Calibrate, register, and stack astrophotography images") argParser.add_argument("images", nargs='+', metavar="image", help="Input images to stack") argParser.add_argument("--reference", nargs='?', metavar="image", help="Reference image (not included in stack)") argParser.add_argument("--out", nargs='?', metavar="filename", help="Output file (mean)") argParser.add_argument("--outstdev", nargs='?', metavar="filename", help="Output file (stdev)") argParser.add_argument("--dump_dir", nargs='?', metavar="directory", help="Output directory for image dumps") argParser.add_argument("--dump_format", nargs='?', metavar="extension", help="Output format for image dumps") argParser.add_argument("--dump_stars", action="store_true", help="Dump found stars to an image") argParser.add_argument("--dump_flat", action="store_true", help="Dump flattened image (which is what the star finder uses)") argSuccess = True try: args = argParser.parse_args() except (Exception, SystemExit): argSuccess = False if argSuccess: ImageIo.initConfig(args.dump_dir, args.dump_format) Register.initConfig(args.dump_stars, args.dump_flat) list = ImageIo.loadImageGlob(args.images) reference = None if args.reference is not None: reference = ImageIo.loadImage(args.reference) reg = Register.register(reference, list) stack, stackDev = Stack.stack(reg) if args.out is not None: ImageIo.saveImage(stack, args.out) if args.outstdev is not None: ImageIo.saveImage(stackDev, args.outstdev)