Example #1
0
def capture_thread():
    '''camera capture thread'''
    state = mpstate.camera_state
    t1 = time.time()
    last_frame_counter = 0
    h = None
    last_gamma = 0

    raw_dir = os.path.join(state.camera_dir, "raw")
    cuav_util.mkdir_p(raw_dir)

    if mpstate.continue_mode:
        mode = 'a'
    else:
        mode = 'w'
    gammalog = open(os.path.join(state.camera_dir, "gamma.log"), mode=mode)

    while not mpstate.camera_state.unload.wait(0.02):
        if not state.running:
            if h is not None:
                chameleon.close(h)
                h = None
            continue
        try:
            if h is None:
                h, base_time, last_frame_time = get_base_time()
                # put into continuous mode
                chameleon.trigger(h, True)

            capture_time = time.time()
            if state.settings.depth == 16:
                im = numpy.zeros((960, 1280), dtype='uint16')
            else:
                im = numpy.zeros((960, 1280), dtype='uint8')
            if last_gamma != state.settings.gamma:
                chameleon.set_gamma(h, state.settings.gamma)
                last_gamma = state.settings.gamma
            frame_time, frame_counter, shutter = chameleon.capture(h, 1000, im)
            if frame_time < last_frame_time:
                base_time += 128
            if last_frame_counter != 0:
                state.frame_loss += frame_counter - (last_frame_counter + 1)

            gammalog.write('%f %f %f %s %u %u\n' %
                           (frame_time, frame_time + base_time, capture_time,
                            cuav_util.frame_time(frame_time + base_time),
                            frame_counter, state.settings.gamma))
            gammalog.flush()

            state.save_queue.put((base_time + frame_time, im))
            state.scan_queue.put((base_time + frame_time, im))
            state.capture_count += 1
            state.fps = 1.0 / (frame_time - last_frame_time)

            last_frame_time = frame_time
            last_frame_counter = frame_counter
        except chameleon.error, msg:
            state.error_count += 1
            state.error_msg = msg
Example #2
0
def process(args):
    """process a set of files"""

    count = 0
    files = []
    for a in args:
        if os.path.isdir(a):
            files.extend(glob.glob(os.path.join(a, "*.png")))
        else:
            files.append(a)
    files.sort()
    num_files = len(files)
    print ("num_files=%u" % num_files)

    if opts.mavlog:
        mpos = mav_position.MavInterpolator(gps_lag=opts.gps_lag)
        mpos.set_logfile(opts.mavlog)
    else:
        print ("You must provide a mavlink log file")
        sys.exit(1)

    frame_time = 0

    if opts.destdir:
        cuav_util.mkdir_p(opts.destdir)

    for f in files:
        frame_time = os.path.getmtime(f)
        try:
            if opts.roll_stabilised:
                roll = 0
            else:
                roll = None
            pos = mpos.position(frame_time, opts.max_deltat, roll=roll)
        except mav_position.MavInterpolatorException as e:
            print e
            pos = None

        im_orig = cv.LoadImage(f)

        lat_deg = pos.lat
        lng_deg = pos.lon

        if opts.inplace:
            newfile = f
        else:
            basefile = f.split(".")[0]
            newfile = basefile + ".jpg"
            if opts.destdir:
                newfile = os.path.join(opts.destdir, os.path.basename(newfile))
        cv.SaveImage(newfile, im_orig)
        count += 1

        print (
            "%s %.7f %.7f [%u/%u %.1f%%]"
            % (os.path.basename(newfile), lat_deg, lng_deg, count, num_files, (100.0 * count) / num_files)
        )
        set_gps_location(newfile, lat_deg, lng_deg, pos.altitude, pos.time)
Example #3
0
def process(args):
    '''process a set of files'''

    count = 0
    files = []
    for a in args:
        if os.path.isdir(a):
            files.extend(glob.glob(os.path.join(a, '*.png')))
        else:
            files.append(a)
    files.sort()
    num_files = len(files)
    print("num_files=%u" % num_files)

    if opts.mavlog:
        mpos = mav_position.MavInterpolator(gps_lag=opts.gps_lag)
        mpos.set_logfile(opts.mavlog)
    else:
        print("You must provide a mavlink log file")
        sys.exit(1)

    frame_time = 0

    if opts.destdir:
        cuav_util.mkdir_p(opts.destdir)

    for f in files:
        frame_time = os.path.getmtime(f)
        try:
            if opts.roll_stabilised:
                roll = 0
            else:
                roll = None
            pos = mpos.position(frame_time, opts.max_deltat, roll=roll)
        except mav_position.MavInterpolatorException as e:
            print e
            pos = None

        im_orig = cv.LoadImage(f)

        lat_deg = pos.lat
        lng_deg = pos.lon

        if opts.inplace:
            newfile = f
        else:
            basefile = f.split('.')[0]
            newfile = basefile + '.jpg'
            if opts.destdir:
                newfile = os.path.join(opts.destdir, os.path.basename(newfile))
        cv.SaveImage(newfile, im_orig)
        count += 1

        print("%s %.7f %.7f [%u/%u %.1f%%]" %
              (os.path.basename(newfile), lat_deg, lng_deg, count, num_files,
               (100.0 * count) / num_files))
        set_gps_location(newfile, lat_deg, lng_deg, pos.altitude, pos.time)
Example #4
0
def process(args):
  '''process a set of files'''

  count = 0
  files = []
  if os.path.isdir(args.files):
    files.extend(glob.glob(os.path.join(args.files, '*.png')))
  else:
    files.append(args.files)
  files.sort()
  num_files = len(files)
  print("num_files=%u" % num_files)

  mpos = mav_position.MavInterpolator(gps_lag=args.gps_lag)
  mpos.set_logfile(args.mavlog)

  frame_time = 0

  if args.destdir:
    cuav_util.mkdir_p(args.destdir)

  for f in files:
    frame_time = os.path.getmtime(f)
    try:
      if args.roll_stabilised:
        roll = 0
      else:
        roll = None
      pos = mpos.position(frame_time, args.max_deltat,roll=roll)
    except mav_position.MavInterpolatorException as e:
      print e
      pos = None

    im_orig = cv.LoadImage(f)

    lat_deg = pos.lat
    lng_deg = pos.lon

    if args.inplace:
      newfile = f
    else:
      basefile = f.split('.')[0]
      newfile = basefile + '.jpg'    
      if args.destdir:
        newfile = os.path.join(args.destdir, os.path.basename(newfile))
    cv.SaveImage(newfile, im_orig)
    count += 1
    
    print("%s %.7f %.7f [%u/%u %.1f%%]" % (os.path.basename(newfile),
                                           lat_deg, lng_deg, count, num_files, (100.0*count)/num_files))
    set_gps_location(newfile, lat_deg, lng_deg, pos.altitude, pos.time)
Example #5
0
    def view_threadfunc(self):
        '''image viewing thread - this runs on the ground station'''
        self.start_gcs_bsend()
        self.image_count = 0
        self.thumb_count = 0
        self.image_total_bytes = 0
        #jpeg_total_bytes = 0
        self.thumb_total_bytes = 0
        self.region_count = 0
        self.mosaic = None
        self.thumbs_received = set()
        # the downloaded thumbs and views are stored in a temp dir
        self.view_dir = os.path.join(self.camera_dir, "view")
        #self.thumb_dir = os.path.join(self.camera_dir, "thumb")
        cuav_util.mkdir_p(self.view_dir)
        #cuav_util.mkdir_p(self.thumb_dir)

        self.console.set_status('Images', 'Images %u' % self.image_count, row=6)
        self.console.set_status('Regions', 'Regions %u' % self.region_count, row=6)
        self.console.set_status('JPGSize', 'JPGSize %.0f' % 0.0, row=6)

        self.console.set_status('Thumbs', 'Thumbs %u' % self.thumb_count, row=7)
        self.console.set_status('ThumbSize', 'ThumbSize %.0f' % 0.0, row=7)
        self.console.set_status('ImageSize', 'ImageSize %.0f' % 0.0, row=7)

        self.mosaic = cuav_mosaic.Mosaic(slipmap=self.mpstate.map, C=self.c_params,
                                         camera_settings=None,
                                         image_settings=None,
                                         thumb_size=self.camera_settings.mosaic_thumbsize)

        while not self.unload_event.wait(0.05):
            if self.boundary_polygon is not None:
                self.mosaic.set_boundary(self.boundary_polygon)
            if self.continue_mode:
                self.reload_mosaic(self.mosaic)

            # check for keyboard events
            self.mosaic.check_events()

            self.check_requested_images(self.mosaic)
            #check for any new packets
            for bsnd in self.bsend:
                bsnd.tick(packet_count=1000, max_queue=self.camera_settings.maxqueue)
                self.check_commands(bsnd)
            self.send_heartbeats()

        #ensure the mosiac is closed at end of thread
        if self.mosaic.image_mosaic:
            self.mosaic.image_mosaic.terminate()
Example #6
0
def save_thread():
    '''image save thread'''
    state = mpstate.camera_state
    raw_dir = os.path.join(state.camera_dir, "raw")
    cuav_util.mkdir_p(raw_dir)
    frame_count = 0
    while not state.unload.wait(0.02):
        if state.save_queue.empty():
            continue
        (frame_time,im) = state.save_queue.get()
        rawname = "raw%s" % cuav_util.frame_time(frame_time)
        frame_count += 1
        if state.settings.save_pgm != 0:
            if frame_count % state.settings.save_pgm == 0:
                chameleon.save_pgm('%s/%s.pgm' % (raw_dir, rawname), im)
Example #7
0
def save_thread():
    """image save thread"""
    state = mpstate.camera_state
    raw_dir = os.path.join(state.camera_dir, "raw")
    cuav_util.mkdir_p(raw_dir)
    frame_count = 0
    while not state.unload.wait(0.02):
        if state.save_queue.empty():
            continue
        (frame_time, im) = state.save_queue.get()
        rawname = "raw%s" % cuav_util.frame_time(frame_time)
        frame_count += 1
        if state.settings.save_pgm != 0:
            if frame_count % state.settings.save_pgm == 0:
                chameleon.save_pgm("%s/%s.pgm" % (raw_dir, rawname), im)
Example #8
0
def capture_thread():
    """camera capture thread"""
    state = mpstate.camera_state
    t1 = time.time()
    last_frame_counter = 0
    h = None
    last_gamma = 0

    raw_dir = os.path.join(state.camera_dir, "raw")
    cuav_util.mkdir_p(raw_dir)

    if mpstate.continue_mode:
        mode = "a"
    else:
        mode = "w"
    gammalog = open(os.path.join(state.camera_dir, "gamma.log"), mode=mode)

    while not mpstate.camera_state.unload.wait(0.02):
        if not state.running:
            if h is not None:
                chameleon.close(h)
                h = None
            continue
        try:
            if h is None:
                h, base_time, last_frame_time = get_base_time()
                # put into continuous mode
                chameleon.trigger(h, True)

            capture_time = time.time()
            if state.settings.depth == 16:
                im = numpy.zeros((960, 1280), dtype="uint16")
            else:
                im = numpy.zeros((960, 1280), dtype="uint8")
            if last_gamma != state.settings.gamma:
                chameleon.set_gamma(h, state.settings.gamma)
                last_gamma = state.settings.gamma
            frame_time, frame_counter, shutter = chameleon.capture(h, 1000, im)
            if frame_time < last_frame_time:
                base_time += 128
            if last_frame_counter != 0:
                state.frame_loss += frame_counter - (last_frame_counter + 1)

            gammalog.write(
                "%f %f %f %s %u %u\n"
                % (
                    frame_time,
                    frame_time + base_time,
                    capture_time,
                    cuav_util.frame_time(frame_time + base_time),
                    frame_counter,
                    state.settings.gamma,
                )
            )
            gammalog.flush()

            state.save_queue.put((base_time + frame_time, im))
            state.scan_queue.put((base_time + frame_time, im))
            state.capture_count += 1
            state.fps = 1.0 / (frame_time - last_frame_time)

            last_frame_time = frame_time
            last_frame_counter = frame_counter
        except chameleon.error, msg:
            state.error_count += 1
            state.error_msg = msg
Example #9
0
    def __init__(self):
        self.running = False
        self.unload = threading.Event()
        self.unload.clear()

        self.capture_thread = None
        self.save_thread = None
        self.scan_thread1 = None
        self.scan_thread2 = None
        self.transmit_thread = None
        self.view_thread = None

        self.settings = mp_settings.MPSettings(
            [
                ("depth", int, 8),
                ("gcs_address", str, None),
                ("gcs_view_port", int, 7543),
                ("bandwidth", int, 40000),
                ("bandwidth2", int, 2000),
                ("capture_brightness", int, 150),
                ("gamma", int, 950),
                ("brightness", float, 1.0),
                ("quality", int, 75),
                ("save_pgm", int, 1),
                ("transmit", int, 1),
                ("roll_stabilised", int, 1),
                ("minscore", int, 75),
                ("minscore2", int, 500),
                ("altitude", int, None),
                ("send1", int, 1),
                ("send2", int, 1),
                ("maxqueue1", int, None),
                ("maxqueue2", int, 30),
                ("thumbsize", int, 60),
                ("packet_loss", int, 0),
                ("gcs_slave", str, None),
                ("filter_type", str, "simple"),
                ("fullres", int, 0),
            ]
        )

        self.capture_count = 0
        self.scan_count = 0
        self.error_count = 0
        self.error_msg = None
        self.region_count = 0
        self.fps = 0
        self.scan_fps = 0
        self.cam = None
        self.save_queue = Queue.Queue()
        self.scan_queue = Queue.Queue()
        self.transmit_queue = Queue.Queue()
        self.viewing = False

        self.c_params = CameraParams(lens=4.0)
        self.jpeg_size = 0
        self.xmit_queue = 0
        self.xmit_queue2 = 0
        self.efficiency = 1.0

        self.last_watch = 0
        self.frame_loss = 0
        self.boundary = None
        self.boundary_polygon = None

        self.bandwidth_used = 0
        self.rtt_estimate = 0
        self.bsocket = None
        self.bsend2 = None
        self.bsend_slave = None

        # setup directory for images
        self.camera_dir = os.path.join(os.path.dirname(mpstate.logfile_name), "camera")
        cuav_util.mkdir_p(self.camera_dir)

        self.mpos = mav_position.MavInterpolator(backlog=5000, gps_lag=0.3)
        self.joelog = cuav_joe.JoeLog(os.path.join(self.camera_dir, "joe.log"), append=mpstate.continue_mode)
        # load camera params
        path = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), "..", "..", "..", "cuav", "data", "chameleon1_arecont0.json"
        )
        self.c_params.load(path)
Example #10
0
def process(args):
  '''process a set of files'''

  global slipmap, mosaic
  scan_count = 0
  files = []
  for a in args:
    if os.path.isdir(a):
      files.extend(glob.glob(os.path.join(a, '*.pgm')))
    else:
      files.append(a)
  files.sort()
  num_files = len(files)
  print("num_files=%u" % num_files)
  region_count = 0
  joes = []

  if opts.mavlog:
    mpos = mav_position.MavInterpolator(gps_lag=opts.gps_lag)
    mpos.set_logfile(opts.mavlog)
  else:
    mpos = None

  if opts.boundary:
    boundary = cuav_util.polygon_load(opts.boundary)
  else:
    boundary = None

  if opts.mosaic:
    slipmap = mp_slipmap.MPSlipMap(service='GoogleSat', elevation=True, title='Map')
    icon = slipmap.icon('planetracker.png')
    slipmap.add_object(mp_slipmap.SlipIcon('plane', (0,0), icon, layer=3, rotation=0,
                                           follow=True,
                                           trail=mp_slipmap.SlipTrail()))
    C_params = cam_params.CameraParams(lens=opts.lens)
    path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..',
                        'cuav', 'data', 'chameleon1_arecont0.json')
    C_params.load(path)
    mosaic = cuav_mosaic.Mosaic(slipmap, C=C_params)
    if boundary is not None:
      mosaic.set_boundary(boundary)

  if opts.joe:
    joes = cuav_util.polygon_load(opts.joe)
    if boundary:
      for i in range(len(joes)):
        joe = joes[i]
        if cuav_util.polygon_outside(joe, boundary):
          print("Error: joe outside boundary", joe)
          return
        icon = slipmap.icon('flag.png')
        slipmap.add_object(mp_slipmap.SlipIcon('joe%u' % i, (joe[0],joe[1]), icon, layer=4))

  joelog = cuav_joe.JoeLog('joe.log')      

  if opts.view:
    viewer = mp_image.MPImage(title='Image')

  frame_time = 0

  for f in files:
    if mpos:
      frame_time = cuav_util.parse_frame_time(f)
      try:
        if opts.roll_stabilised:
          roll = 0
        else:
          roll = None
        pos = mpos.position(frame_time, opts.max_deltat,roll=roll)
        slipmap.set_position('plane', (pos.lat, pos.lon), rotation=pos.yaw)
      except mav_position.MavInterpolatorException as e:
        print e
        pos = None
    else:
      pos = None

    # check for any events from the map
    if opts.mosaic:
      slipmap.check_events()
      mosaic.check_events()

    if f.endswith('.pgm'):
      pgm = cuav_util.PGM(f)
      im = pgm.array
      if pgm.eightbit:
        im_8bit = im
      else:
        im_8bit = numpy.zeros((960,1280,1),dtype='uint8')
        if opts.gamma != 0:
          scanner.gamma_correct(im, im_8bit, opts.gamma)
        else:
          scanner.reduce_depth(im, im_8bit)
      im_full = numpy.zeros((960,1280,3),dtype='uint8')
      scanner.debayer(im_8bit, im_full)
      im_640 = numpy.zeros((480,640,3),dtype='uint8')
      scanner.downsample(im_full, im_640)
    else:
      im_orig = cv.LoadImage(f)
      (w,h) = cuav_util.image_shape(im_orig)
      im_full = im_orig
      im_640 = cv.CreateImage((640, 480), 8, 3)
      cv.Resize(im_full, im_640, cv.CV_INTER_NN)
      im_640 = numpy.ascontiguousarray(cv.GetMat(im_640))
      im_full = numpy.ascontiguousarray(cv.GetMat(im_full))

    count = 0
    total_time = 0
    img_scan = im_640

    t0=time.time()
    for i in range(opts.repeat):
      if opts.fullres:
        regions = scanner.scan(im_full)
        regions = cuav_region.RegionsConvert(regions, 1280, 960)
      else:
        regions = scanner.scan(img_scan)
        regions = cuav_region.RegionsConvert(regions)
      count += 1
    t1=time.time()

    if opts.filter:
      regions = cuav_region.filter_regions(im_full, regions, frame_time=frame_time, min_score=opts.minscore,
                                           filter_type=opts.filter_type)

    scan_count += 1

    # optionally link all the images with joe into a separate directory
    # for faster re-running of the test with just joe images
    if pos and opts.linkjoe and len(regions) > 0:
      cuav_util.mkdir_p(opts.linkjoe)
      if not cuav_util.polygon_outside((pos.lat, pos.lon), boundary):
        joepath = os.path.join(opts.linkjoe, os.path.basename(f))
        if os.path.exists(joepath):
          os.unlink(joepath)
        os.symlink(f, joepath)

    if pos and len(regions) > 0:
      joelog.add_regions(frame_time, regions, pos, f, width=1280, height=960, altitude=opts.altitude)

      if boundary:
        regions = cuav_region.filter_boundary(regions, boundary, pos)

    region_count += len(regions)

    if opts.mosaic and len(regions) > 0:
      composite = cuav_mosaic.CompositeThumbnail(cv.GetImage(cv.fromarray(im_full)), regions)
      thumbs = cuav_mosaic.ExtractThumbs(composite, len(regions))
      mosaic.add_regions(regions, thumbs, f, pos)

    if opts.compress:
      jpeg = scanner.jpeg_compress(im_full, opts.quality)
      jpeg_filename = f[:-4] + '.jpg'
      if os.path.exists(jpeg_filename):
        print('jpeg %s already exists' % jpeg_filename)
        continue
      chameleon.save_file(jpeg_filename, jpeg)

    if opts.view:
      if opts.fullres:
        img_view = im_full
      else:
        img_view = img_scan
      mat = cv.fromarray(img_view)
      for r in regions:
        (x1,y1,x2,y2) = r.tuple()
        (w,h) = cuav_util.image_shape(img_view)
        x1 = x1*w//1280
        x2 = x2*w//1280
        y1 = y1*h//960
        y2 = y2*h//960
        cv.Rectangle(mat, (max(x1-2,0),max(y1-2,0)), (x2+2,y2+2), (255,0,0), 2)
      cv.CvtColor(mat, mat, cv.CV_BGR2RGB)
      viewer.set_image(mat)

    total_time += (t1-t0)
    if t1 != t0:
      print('%s scan %.1f fps  %u regions [%u/%u]' % (
        f, count/total_time, region_count, scan_count, num_files))
Example #11
0
def view_thread():
    '''image viewing thread - this runs on the ground station'''
    from cuav.lib import cuav_mosaic
    state = mpstate.camera_state

    bsend = block_xmit.BlockSender(state.settings.gcs_view_port, bandwidth=state.settings.bandwidth)
    state.bsocket = MavSocket(mpstate.mav_master[0])
    state.bsend2 = block_xmit.BlockSender(mss=96, sock=state.bsocket, dest_ip='mavlink', dest_port=0, backlog=5, debug=False)
    state.bsend2.set_bandwidth(state.settings.bandwidth2)

    view_window = False
    image_count = 0
    thumb_count = 0
    image_total_bytes = 0
    jpeg_total_bytes = 0
    thumb_total_bytes = 0
    region_count = 0
    mosaic = None
    thumbs_received = set()
    view_dir = os.path.join(state.camera_dir, "view")
    thumb_dir = os.path.join(state.camera_dir, "thumb")
    cuav_util.mkdir_p(view_dir)
    cuav_util.mkdir_p(thumb_dir)

    img_window = mp_image.MPImage(title='Camera')

    mpstate.console.set_status('Images', 'Images %u' % image_count, row=6)
    mpstate.console.set_status('Lost', 'Lost %u' % 0, row=6)
    mpstate.console.set_status('Regions', 'Regions %u' % region_count, row=6)
    mpstate.console.set_status('JPGSize', 'JPGSize %.0f' % 0.0, row=6)
    mpstate.console.set_status('XMITQ', 'XMITQ %.0f' % 0.0, row=6)

    mpstate.console.set_status('Thumbs', 'Thumbs %u' % thumb_count, row=7)
    mpstate.console.set_status('ThumbSize', 'ThumbSize %.0f' % 0.0, row=7)
    mpstate.console.set_status('ImageSize', 'ImageSize %.0f' % 0.0, row=7)

    ack_time = time.time()

    while not state.unload.wait(0.02):
        if state.viewing:
            tnow = time.time()
            if tnow - ack_time > 0.1:
                bsend.tick(packet_count=1000, max_queue=state.settings.maxqueue1)
                state.bsend2.tick(packet_count=1000, max_queue=state.settings.maxqueue2)
                if state.bsend_slave is not None:
                    state.bsend_slave.tick(packet_count=1000)
                ack_time = tnow
            if not view_window:
                view_window = True
                mosaic = cuav_mosaic.Mosaic(slipmap=mpstate.map, C=state.c_params)
                if state.boundary_polygon is not None:
                    mosaic.set_boundary(state.boundary_polygon)
                if mpstate.continue_mode:
                    reload_mosaic(mosaic)

            # check for keyboard events
            mosaic.check_events()

            buf = bsend.recv(0)
            if buf is None:
                buf = state.bsend2.recv(0)
            if buf is None:
                continue
            try:
                obj = cPickle.loads(str(buf))
                if obj == None:
                    continue
            except Exception as e:
                continue

            if state.settings.gcs_slave is not None:
                if state.bsend_slave is None:
                    state.bsend_slave = block_xmit.BlockSender(0, bandwidth=state.settings.bandwidth*10, debug=False)
                state.bsend_slave.send(buf,
                                       dest=(state.settings.gcs_slave, state.settings.gcs_view_port),
                                       priority=1)

            if isinstance(obj, ThumbPacket):
                # we've received a set of thumbnails from the plane for a positive hit
                if obj.frame_time in thumbs_received:
                    continue
                thumbs_received.add(obj.frame_time)

                thumb_total_bytes += len(buf)

                # save the thumbnails
                thumb_filename = '%s/v%s.jpg' % (thumb_dir, cuav_util.frame_time(obj.frame_time))
                chameleon.save_file(thumb_filename, obj.thumb)
                composite = cv.LoadImage(thumb_filename)
                thumbs = cuav_mosaic.ExtractThumbs(composite, len(obj.regions))

                # log the joe positions
                filename = '%s/v%s.jpg' % (view_dir, cuav_util.frame_time(obj.frame_time))
                pos = obj.pos
                log_joe_position(pos, obj.frame_time, obj.regions, filename, thumb_filename)

                # update the mosaic and map
                mosaic.set_brightness(state.settings.brightness)
                mosaic.add_regions(obj.regions, thumbs, filename, pos=pos)

                # update console display
                region_count += len(obj.regions)
                state.frame_loss = obj.frame_loss
                state.xmit_queue = obj.xmit_queue
                thumb_count += 1

                mpstate.console.set_status('Lost', 'Lost %u' % state.frame_loss)
                mpstate.console.set_status('Regions', 'Regions %u' % region_count)
                mpstate.console.set_status('XMITQ', 'XMITQ %.0f' % state.xmit_queue)
                mpstate.console.set_status('Thumbs', 'Thumbs %u' % thumb_count)
                mpstate.console.set_status('ThumbSize', 'ThumbSize %.0f' % (thumb_total_bytes/thumb_count))

            if isinstance(obj, ImagePacket):
                # we have an image from the plane
                image_total_bytes += len(buf)

                state.xmit_queue = obj.xmit_queue
                mpstate.console.set_status('XMITQ', 'XMITQ %.0f' % state.xmit_queue)

                # save it to disk
                filename = '%s/v%s.jpg' % (view_dir, cuav_util.frame_time(obj.frame_time))
                chameleon.save_file(filename, obj.jpeg)
                img = cv.LoadImage(filename)
                if img.width == 1280:
                    display_img = cv.CreateImage((640, 480), 8, 3)
                    cv.Resize(img, display_img)
                else:
                    display_img = img

                mosaic.add_image(obj.frame_time, filename, obj.pos)

                cv.ConvertScale(display_img, display_img, scale=state.settings.brightness)
                img_window.set_image(display_img, bgr=True)

                # update console
                image_count += 1
                jpeg_total_bytes += len(obj.jpeg)
                state.jpeg_size = 0.95 * state.jpeg_size + 0.05 * len(obj.jpeg)
                mpstate.console.set_status('Images', 'Images %u' % image_count)
                mpstate.console.set_status('JPGSize', 'JPG Size %.0f' % (jpeg_total_bytes/image_count))
                mpstate.console.set_status('ImageSize', 'ImageSize %.0f' % (image_total_bytes/image_count))

            if isinstance(obj, CommandResponse):
                print('REMOTE: %s' % obj.response)
                
        else:
            if view_window:
                view_window = False
Example #12
0
h, base_time, last_frame_time = get_base_time(opts.depth, colour=colour, capture_brightness=opts.capbrightness)
print("Found camera: colour=%u GUID=%x" % (colour, chameleon.guid(h)))
if opts.depth == 8:
  dtype = 'uint8'
else:
  dtype = 'uint16'
im = numpy.zeros((960,1280),dtype=dtype)

cv.NamedWindow('Viewer')

tstart = time.time()

chameleon.trigger(h, True)
chameleon.set_gamma(h, opts.gamma)

cuav_util.mkdir_p(opts.output)

start_thread(save_thread)

i=0
lost = 0
while True:
  try:
    frame_time, frame_counter, shutter = chameleon.capture(h, 300, im)
  except chameleon.error, msg:
    lost += 1
    continue
  if frame_time < last_frame_time:
    base_time += 128
  save_queue.put((frame_time+base_time, im))
  last_frame_time = frame_time
Example #13
0
def process(args):
    '''process a set of files'''

    count = 0
    files = []
    types = ('*.png', '*.jpeg', '*.jpg')
    if os.path.isdir(args.files):
        for tp in types:
            files.extend(glob.glob(os.path.join(args.files, tp)))
    else:
        files.append(args.files)
    files.sort()
    num_files = len(files)
    print("num_files=%u" % num_files)

    mpos = mav_position.MavInterpolator(gps_lag=args.gps_lag)
    mpos.set_logfile(os.path.join(os.getcwd(), args.mavlog))

    frame_time = 0

    if args.destdir:
        cuav_util.mkdir_p(args.destdir)

    for f in files:
        #timestamp is in filename
        timestamp = (os.path.splitext(os.path.basename(f))[0])
        m = re.search("\d", timestamp)
        if m:
            timestamp = timestamp[m.start():]

        frame_time = datetime.datetime.strptime(timestamp, "%Y%m%d%H%M%S%fZ")
        frame_time = mav_position.datetime_to_float(frame_time)

        try:
            if args.roll_stabilised:
                roll = 0
            else:
                roll = None
            pos = mpos.position(frame_time, args.max_deltat, roll=roll)
        except mav_position.MavInterpolatorException as e:
            print(e)
            pos = None

        if pos:

            lat_deg = pos.lat
            lng_deg = pos.lon

            if args.inplace:
                outfile = f
            else:
                basefile = os.path.basename(f)
                outfile = ""
                if args.destdir:
                    outfile = os.path.join(args.destdir, basefile)
                else:
                    outfile = os.path.join(os.getcwd(), basefile)
                shutil.copy2(f, outfile)
            count += 1

            print(
                "%s %.7f %.7f [%u/%u %.1f%%]" %
                (os.path.basename(outfile), lat_deg, lng_deg, count, num_files,
                 (100.0 * count) / num_files))
            set_gps_location(outfile, lat_deg, lng_deg, pos.altitude, pos.time)
Example #14
0
def process(args):
    '''process a set of files'''

    global slipmap, mosaic
    scan_count = 0
    files = scan_image_directory(args.imagedir)
    files.sort()
    num_files = len(files)
    print("num_files=%u" % num_files)
    region_count = 0
    joes = []

    if args.mavlog:
        mpos = mav_position.MavInterpolator(gps_lag=args.gps_lag)
        mpos.set_logfile(args.mavlog)
    else:
        mpos = None

    if args.boundary:
        boundary = cuav_util.polygon_load(args.boundary)
    else:
        boundary = None

    if args.mosaic:
        slipmap = mp_slipmap.MPSlipMap(service='GoogleSat', elevation=True, title='Map')
        icon = slipmap.icon('redplane.png')
        slipmap.add_object(mp_slipmap.SlipIcon('plane', (0,0), icon, layer=3, rotation=0,
                                         follow=True,
                                         trail=mp_slipmap.SlipTrail()))
        if args.camera_params:
            C_params = cam_params.CameraParams.fromfile(args.camera_params.name)
        else:
            im_orig = cv2.imread(files[0])
            (w,h) = cuav_util.image_shape(im_orig)
            C_params = cam_params.CameraParams(lens=args.lens, sensorwidth=args.sensorwidth, xresolution=w, yresolution=h)
        mosaic = cuav_mosaic.Mosaic(slipmap, C=C_params)
        if boundary is not None:
            mosaic.set_boundary(boundary)

    if args.joe:
        joes = cuav_util.polygon_load(args.joe)
        if boundary:
            for i in range(len(joes)):
                joe = joes[i]
                if cuav_util.polygon_outside(joe, boundary):
                    print("Error: joe outside boundary", joe)
                    return
                icon = slipmap.icon('flag.png')
                slipmap.add_object(mp_slipmap.SlipIcon('joe%u' % i, (joe[0],joe[1]), icon, layer=4))

    joelog = cuav_joe.JoeLog('joe.log')      

    if args.view:
        viewer = mp_image.MPImage(title='Image')

    frame_time = 0

    scan_parms = {
        'MinRegionArea' : args.min_region_area,
        'MaxRegionArea' : args.max_region_area,
        'MinRegionSize' : args.min_region_size,
        'MaxRegionSize' : args.max_region_size,
        'MaxRarityPct'  : args.max_rarity_pct,
        'RegionMergeSize' : args.region_merge,
        'SaveIntermediate' : float(0),
        #'SaveIntermediate' : float(args.debug),
        'MetersPerPixel' : args.meters_per_pixel100 * args.altitude / 100.0
    }

    filenum = 0
        
    for f in files:
        filenum += 1
        if mpos:
            frame_time = cuav_util.parse_frame_time(f)
            try:
                if args.roll_stabilised:
                    roll = 0
                else:
                    roll = None
                pos = mpos.position(frame_time, args.max_deltat,roll=roll)
                slipmap.set_position('plane', (pos.lat, pos.lon), rotation=pos.yaw)
            except mav_position.MavInterpolatorException as e:
                print(e)
                pos = None
        else:
              pos = None

        # check for any events from the map
        if args.mosaic:
            slipmap.check_events()
            mosaic.check_events()

        im_orig = cv2.imread(f)
        (w,h) = cuav_util.image_shape(im_orig)
        im_full = im_orig
        im_half = cv2.resize(im_orig, (0,0), fx=0.5, fy=0.5)
        im_half = numpy.ascontiguousarray(im_half)
        im_full = numpy.ascontiguousarray(im_full)

        count = 0
        total_time = 0
        if args.fullres:
            img_scan = im_full
        else:
            img_scan = im_half

        t0=time.time()
        for i in range(args.repeat):
            regions = scanner.scan(img_scan, scan_parms)
            regions = cuav_region.RegionsConvert(regions, cuav_util.image_shape(img_scan), cuav_util.image_shape(im_full))
            count += 1
        t1=time.time()

        if args.filter:
            regions = cuav_region.filter_regions(im_full, regions, min_score=args.minscore,
                                           filter_type=args.filter_type)

        if len(regions) > 0 and args.debug:
            composite = cuav_region.CompositeThumbnail(im_full, regions, thumb_size=args.thumb_size)
            thumbs = cuav_mosaic.ExtractThumbs(composite, len(regions))
            thumb_num = 0
            for thumb in thumbs:
                print("thumb %u score %f" % (thumb_num, regions[thumb_num].score))
                cv2.imwrite('%u_thumb%u.jpg' % (filenum,thumb_num), thumb)
                thumb_num += 1
            
        scan_count += 1

        # optionally link all the images with joe into a separate directory
        # for faster re-running of the test with just joe images
        if pos and args.linkjoe and len(regions) > 0:
            cuav_util.mkdir_p(args.linkjoe)
            if not cuav_util.polygon_outside((pos.lat, pos.lon), boundary):
                joepath = os.path.join(args.linkjoe, os.path.basename(f))
                if os.path.exists(joepath):
                    os.unlink(joepath)
                os.symlink(f, joepath)

        if pos and len(regions) > 0:
            joelog.add_regions(frame_time, regions, pos, f, width=w, height=h, altitude=args.altitude, C=C_params)

        if boundary:
            regions = cuav_region.filter_boundary(regions, boundary, pos)

        region_count += len(regions)

        if args.mosaic and len(regions) > 0 and pos:
            composite = cuav_region.CompositeThumbnail(im_full, regions)
            thumbs = cuav_mosaic.ExtractThumbs(composite, len(regions))
            mosaic.add_regions(regions, thumbs, f, pos)

        if args.view:
            if args.fullres:
                img_view = im_full
            else:
                img_view = img_scan
            #mat = cv.fromarray(img_view)
            for r in regions:
                r.draw_rectangle(img_view, colour=(255,0,0), linewidth=min(max(w/600,1),3), offset=max(w/200,1))
            img_view = cv2.cvtColor(img_view, cv2.COLOR_BGR2RGB)
            viewer.set_image(img_view)

        total_time += (t1-t0)
        if t1 != t0:
            print('%s scan %.1f fps  %u regions [%u/%u]' % (
                f, count/total_time, region_count, scan_count, num_files))
Example #15
0
def process(args):
  '''process a set of files'''

  count = 0
  files = []
  types = ('*.png', '*.jpeg', '*.jpg')
  if os.path.isdir(args.files):
    for tp in types:
        files.extend(glob.glob(os.path.join(args.files, tp)))
  else:
    files.append(args.files)
  files.sort()
  num_files = len(files)
  print("num_files=%u" % num_files)

  mpos = mav_position.MavInterpolator(gps_lag=args.gps_lag)
  mpos.set_logfile(os.path.join(os.getcwd(), args.mavlog))

  frame_time = 0

  if args.destdir:
    cuav_util.mkdir_p(args.destdir)

  for f in files:
    #timestamp is in filename
    timestamp = (os.path.splitext(os.path.basename(f))[0])
    m = re.search("\d", timestamp)
    if m :
        timestamp = timestamp[m.start():]
    
    frame_time = datetime.datetime.strptime(timestamp, "%Y%m%d%H%M%S%fZ")
    frame_time = mav_position.datetime_to_float(frame_time)

    try:
      if args.roll_stabilised:
        roll = 0
      else:
        roll = None
      pos = mpos.position(frame_time, args.max_deltat,roll=roll)
    except mav_position.MavInterpolatorException as e:
      print(e)
      pos = None

    if pos:

        lat_deg = pos.lat
        lng_deg = pos.lon

        if args.inplace:
            outfile = f
        else:
            basefile = os.path.basename(f)
            outfile = ""
            if args.destdir:
                outfile = os.path.join(args.destdir, basefile)
            else:
                outfile = os.path.join(os.getcwd(), basefile)
            shutil.copy2(f, outfile)
        count += 1
        
        print("%s %.7f %.7f [%u/%u %.1f%%]" % (os.path.basename(outfile),
                                               lat_deg, lng_deg, count, num_files, (100.0*count)/num_files))
        set_gps_location(outfile, lat_deg, lng_deg, pos.altitude, pos.time)
Example #16
0
def view_thread():
    """image viewing thread - this runs on the ground station"""
    from cuav.lib import cuav_mosaic

    state = mpstate.camera_state

    bsend = block_xmit.BlockSender(state.settings.gcs_view_port, bandwidth=state.settings.bandwidth)
    state.bsocket = MavSocket(mpstate.mav_master[0])
    state.bsend2 = block_xmit.BlockSender(
        mss=96, sock=state.bsocket, dest_ip="mavlink", dest_port=0, backlog=5, debug=False
    )
    state.bsend2.set_bandwidth(state.settings.bandwidth2)

    view_window = False
    image_count = 0
    thumb_count = 0
    image_total_bytes = 0
    jpeg_total_bytes = 0
    thumb_total_bytes = 0
    region_count = 0
    mosaic = None
    thumbs_received = set()
    view_dir = os.path.join(state.camera_dir, "view")
    thumb_dir = os.path.join(state.camera_dir, "thumb")
    cuav_util.mkdir_p(view_dir)
    cuav_util.mkdir_p(thumb_dir)

    img_window = mp_image.MPImage(title="Camera")

    mpstate.console.set_status("Images", "Images %u" % image_count, row=6)
    mpstate.console.set_status("Lost", "Lost %u" % 0, row=6)
    mpstate.console.set_status("Regions", "Regions %u" % region_count, row=6)
    mpstate.console.set_status("JPGSize", "JPGSize %.0f" % 0.0, row=6)
    mpstate.console.set_status("XMITQ", "XMITQ %.0f" % 0.0, row=6)

    mpstate.console.set_status("Thumbs", "Thumbs %u" % thumb_count, row=7)
    mpstate.console.set_status("ThumbSize", "ThumbSize %.0f" % 0.0, row=7)
    mpstate.console.set_status("ImageSize", "ImageSize %.0f" % 0.0, row=7)

    ack_time = time.time()

    while not state.unload.wait(0.02):
        if state.viewing:
            tnow = time.time()
            if tnow - ack_time > 0.1:
                bsend.tick(packet_count=1000, max_queue=state.settings.maxqueue1)
                state.bsend2.tick(packet_count=1000, max_queue=state.settings.maxqueue2)
                if state.bsend_slave is not None:
                    state.bsend_slave.tick(packet_count=1000)
                ack_time = tnow
            if not view_window:
                view_window = True
                mosaic = cuav_mosaic.Mosaic(slipmap=mpstate.map, C=state.c_params)
                if state.boundary_polygon is not None:
                    mosaic.set_boundary(state.boundary_polygon)
                if mpstate.continue_mode:
                    reload_mosaic(mosaic)

            # check for keyboard events
            mosaic.check_events()

            buf = bsend.recv(0)
            if buf is None:
                buf = state.bsend2.recv(0)
            if buf is None:
                continue
            try:
                obj = cPickle.loads(str(buf))
                if obj == None:
                    continue
            except Exception as e:
                continue

            if state.settings.gcs_slave is not None:
                if state.bsend_slave is None:
                    state.bsend_slave = block_xmit.BlockSender(0, bandwidth=state.settings.bandwidth * 10, debug=False)
                state.bsend_slave.send(buf, dest=(state.settings.gcs_slave, state.settings.gcs_view_port), priority=1)

            if isinstance(obj, ThumbPacket):
                # we've received a set of thumbnails from the plane for a positive hit
                if obj.frame_time in thumbs_received:
                    continue
                thumbs_received.add(obj.frame_time)

                thumb_total_bytes += len(buf)

                # save the thumbnails
                thumb_filename = "%s/v%s.jpg" % (thumb_dir, cuav_util.frame_time(obj.frame_time))
                chameleon.save_file(thumb_filename, obj.thumb)
                composite = cv.LoadImage(thumb_filename)
                thumbs = cuav_mosaic.ExtractThumbs(composite, len(obj.regions))

                # log the joe positions
                filename = "%s/v%s.jpg" % (view_dir, cuav_util.frame_time(obj.frame_time))
                pos = obj.pos
                log_joe_position(pos, obj.frame_time, obj.regions, filename, thumb_filename)

                # update the mosaic and map
                mosaic.set_brightness(state.settings.brightness)
                mosaic.add_regions(obj.regions, thumbs, filename, pos=pos)

                # update console display
                region_count += len(obj.regions)
                state.frame_loss = obj.frame_loss
                state.xmit_queue = obj.xmit_queue
                thumb_count += 1

                mpstate.console.set_status("Lost", "Lost %u" % state.frame_loss)
                mpstate.console.set_status("Regions", "Regions %u" % region_count)
                mpstate.console.set_status("XMITQ", "XMITQ %.0f" % state.xmit_queue)
                mpstate.console.set_status("Thumbs", "Thumbs %u" % thumb_count)
                mpstate.console.set_status("ThumbSize", "ThumbSize %.0f" % (thumb_total_bytes / thumb_count))

            if isinstance(obj, ImagePacket):
                # we have an image from the plane
                image_total_bytes += len(buf)

                state.xmit_queue = obj.xmit_queue
                mpstate.console.set_status("XMITQ", "XMITQ %.0f" % state.xmit_queue)

                # save it to disk
                filename = "%s/v%s.jpg" % (view_dir, cuav_util.frame_time(obj.frame_time))
                chameleon.save_file(filename, obj.jpeg)
                img = cv.LoadImage(filename)
                if img.width == 1280:
                    display_img = cv.CreateImage((640, 480), 8, 3)
                    cv.Resize(img, display_img)
                else:
                    display_img = img

                mosaic.add_image(obj.frame_time, filename, obj.pos)

                cv.ConvertScale(display_img, display_img, scale=state.settings.brightness)
                img_window.set_image(display_img, bgr=True)

                # update console
                image_count += 1
                jpeg_total_bytes += len(obj.jpeg)
                state.jpeg_size = 0.95 * state.jpeg_size + 0.05 * len(obj.jpeg)
                mpstate.console.set_status("Images", "Images %u" % image_count)
                mpstate.console.set_status("JPGSize", "JPG Size %.0f" % (jpeg_total_bytes / image_count))
                mpstate.console.set_status("ImageSize", "ImageSize %.0f" % (image_total_bytes / image_count))

            if isinstance(obj, CommandResponse):
                print ("REMOTE: %s" % obj.response)

        else:
            if view_window:
                view_window = False
Example #17
0
    def view_threadfunc(self):
        '''image viewing thread - this runs on the ground station'''
        self.start_gcs_bsend()
        self.image_count = 0
        self.thumb_count = 0
        self.image_total_bytes = 0
        #jpeg_total_bytes = 0
        self.thumb_total_bytes = 0
        self.region_count = 0
        self.mosaic = None
        self.thumbs_received = set()
        # the downloaded thumbs and views are stored in a temp dir
        self.view_dir = os.path.join(self.camera_dir, "view")
        #self.thumb_dir = os.path.join(self.camera_dir, "thumb")
        cuav_util.mkdir_p(self.view_dir)
        #cuav_util.mkdir_p(self.thumb_dir)

        self.console.set_status('Images',
                                'Images %u' % self.image_count,
                                row=6)
        self.console.set_status('Regions',
                                'Regions %u' % self.region_count,
                                row=6)

        self.console.set_status('Thumbs',
                                'Thumbs %u' % self.thumb_count,
                                row=7)
        self.console.set_status('ThumbSize', 'ThumbSize %.0f' % 0.0, row=7)
        self.console.set_status('BX1', 'BX1 --', row=7)
        self.console.set_status('BX2', 'BX2 --', row=7)
        self.console.set_status('BX3', 'BX3 --', row=7)

        # give time for maps to init
        time.sleep(3)

        map2 = self.module("map2")
        map3 = self.module("map3")
        if map2:
            search_map = map2.map
        if map3:
            lz_map = map3.map

        self.mosaic = cuav_mosaic.Mosaic(
            slipmap=self.mpstate.map,
            C=self.c_params,
            camera_settings=None,
            image_settings=None,
            thumb_size=self.camera_settings.mosaic_thumbsize,
            search_map=search_map,
            lz_map=lz_map)

        while not self.unload_event.wait(0.05):
            if self.boundary_polygon is not None:
                self.mosaic.set_boundary(self.boundary_polygon)
            if self.continue_mode:
                self.reload_mosaic(self.mosaic)

            # check for keyboard events
            self.mosaic.check_events()

            self.check_requested_images(self.mosaic)
            #check for any new packets
            for bsnd in self.bsend:
                bsnd.tick(packet_count=1000,
                          max_queue=self.camera_settings.maxqueue)
                self.check_commands(bsnd)
            if self.msend is not None:
                self.msend.tick(packet_count=1000,
                                max_queue=self.camera_settings.maxqueue)
                self.check_commands(self.msend)
            self.send_heartbeats()

        #ensure the mosiac is closed at end of thread
        if self.mosaic.image_mosaic:
            self.mosaic.image_mosaic.terminate()
Example #18
0
    def __init__(self):
        self.running = False
        self.unload = threading.Event()
        self.unload.clear()

        self.capture_thread = None
        self.save_thread = None
        self.scan_thread1 = None
        self.scan_thread2 = None
        self.transmit_thread = None
        self.view_thread = None

        self.settings = mp_settings.MPSettings(
            [ ('depth', int, 8),
              ('gcs_address', str, None),
              ('gcs_view_port', int, 7543),
              ('bandwidth',  int, 40000),
              ('bandwidth2', int, 2000),
              ('capture_brightness', int, 150),
              ('gamma', int, 950),
              ('brightness', float, 1.0),
              ('quality', int, 75),
              ('save_pgm', int, 1),
              ('transmit', int, 1),
              ('roll_stabilised', int, 1),
              ('minscore', int, 75),
              ('minscore2', int, 500),
              ('altitude', int, None),
              ('send1', int, 1),
              ('send2', int, 1),
              ('maxqueue1', int, None),
              ('maxqueue2', int, 30),
              ('thumbsize', int, 60),
              ('packet_loss', int, 0),             
              ('gcs_slave', str, None)  
              ]
            )

        self.capture_count = 0
        self.scan_count = 0
        self.error_count = 0
        self.error_msg = None
        self.region_count = 0
        self.fps = 0
        self.scan_fps = 0
        self.cam = None
        self.save_queue = Queue.Queue()
        self.scan_queue = Queue.Queue()
        self.transmit_queue = Queue.Queue()
        self.viewing = False
        
        self.c_params = CameraParams(lens=4.0)
        self.jpeg_size = 0
        self.xmit_queue = 0
        self.xmit_queue2 = 0
        self.efficiency = 1.0

        self.last_watch = 0
        self.frame_loss = 0
        self.boundary = None
        self.boundary_polygon = None

        self.bandwidth_used = 0
        self.rtt_estimate = 0
        self.bsocket = None
        self.bsend2 = None
        self.bsend_slave = None
        
        # setup directory for images
        self.camera_dir = os.path.join(os.path.dirname(mpstate.logfile_name),
                                      "camera")
        cuav_util.mkdir_p(self.camera_dir)

        self.mpos = mav_position.MavInterpolator(backlog=5000, gps_lag=0.3)
        self.joelog = cuav_joe.JoeLog(os.path.join(self.camera_dir, 'joe.log'), append=mpstate.continue_mode)
        # load camera params
        path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..',
                            'cuav', 'data', 'chameleon1_arecont0.json')
        self.c_params.load(path)
Example #19
0
    opts.depth, colour=colour, capture_brightness=opts.capbrightness)
print("Found camera: colour=%u GUID=%x" % (colour, chameleon.guid(h)))
if opts.depth == 8:
    dtype = 'uint8'
else:
    dtype = 'uint16'
im = numpy.zeros((960, 1280), dtype=dtype)

cv.NamedWindow('Viewer')

tstart = time.time()

chameleon.trigger(h, True)
chameleon.set_gamma(h, opts.gamma)

cuav_util.mkdir_p(opts.output)

start_thread(save_thread)

i = 0
lost = 0
while True:
    try:
        frame_time, frame_counter, shutter = chameleon.capture(h, 300, im)
    except chameleon.error, msg:
        lost += 1
        continue
    if frame_time < last_frame_time:
        base_time += 128
    save_queue.put((frame_time + base_time, im))
    last_frame_time = frame_time