Example #1
0
    def isOutsideSearchAreaBoundingBox(self, lat, longy):
        '''Checks if the long/lat pair is inside the search area
        bounding box. Returns true if it is inside'''

        if cuav_util.polygon_outside((lat, longy), self.boundingBox):
            return 1
        else:
            return 0
Example #2
0
def filter_boundary(regions, boundary, pos=None):
	'''filter a list of regions using a search boundary'''
        ret = []
        for r in regions:
	    if pos is not None and pos.altitude < 10:
	        continue
	    print pos
            if r.latlon is None or cuav_util.polygon_outside(r.latlon, boundary):
                continue
            ret.append(r)
        return ret
Example #3
0
def filter_boundary(regions, boundary, pos=None):
	'''filter a list of regions using a search boundary'''
        ret = []
        for r in regions:
            if pos is None:
	        continue
	    if pos.altitude < 10:
              r.score = 0
	    #print pos
            if r.latlon is None or cuav_util.polygon_outside(r.latlon, boundary):
              r.score = 0
            ret.append(r)
        return ret
Example #4
0
def filter_boundary(regions, boundary, pos=None):
    """filter a list of regions using a search boundary"""
    ret = []
    for r in regions:
        if pos is None:
            continue
        if pos.altitude < 10:
            r.score = 0
        # print pos
        if r.latlon is None or cuav_util.polygon_outside(r.latlon, boundary):
            r.score = 0
        ret.append(r)
    return ret
Example #5
0
    def add_regions(self, regions, thumbs, filename, pos=None):
        '''add some regions'''
        for i in range(len(regions)):
            r = regions[i]
            (x1,y1,x2,y2) = r.tuple()

            (lat, lon) = r.latlon

            if self.boundary and (lat,lon) == (None,None):
                # its pointing into the sky
                continue
            if self.boundary:
                if cuav_util.polygon_outside((lat, lon), self.boundary):
                    # this region is outside the search boundary
                    continue

            # the thumbnail we have been given will be bigger than the size we want to
            # display on the mosaic. Extract the middle of it for display
            full_thumb = thumbs[i]
            tsize = cuav_util.image_width(full_thumb)
            thumb = cuav_util.SubImage(full_thumb, ((tsize-self.thumb_size)//2,
                                                    (tsize-self.thumb_size)//2,
                                                    self.thumb_size,
                                                    self.thumb_size))

            ridx = len(self.regions)
            self.regions.append(MosaicRegion(ridx, r, filename, pos, thumbs[i], thumb, latlon=(lat, lon)))
            self.regions_sorted.append(self.regions[-1])

            self.display_mosaic_region(ridx)

            if (lat,lon) != (None,None):
                import mp_slipmap
                self.slipmap.add_object(mp_slipmap.SlipThumbnail("region %u" % ridx, (lat,lon),
                                                                 img=thumb,
                                                                 layer=2, border_width=1, border_colour=(255,0,0)))

        self.image_mosaic.set_image(self.mosaic, bgr=True)
Example #6
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")

    for f in files:
        frame_time = cuav_util.parse_frame_time(f)
        if mpos:
            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_full(im_8bit, im_full)
            im_640 = numpy.zeros((480, 640, 3), dtype="uint8")
            scanner.downsample(im_full, im_640)
        else:
            im_full = cv.LoadImage(f)
            im_640 = cv.CreateImage((640, 480), 8, 3)
            cv.Resize(im_full, im_640)
            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_full(im_full)
            else:
                regions = scanner.scan(img_scan)
            count += 1
        regions = cuav_region.RegionsConvert(regions)
        t1 = time.time()

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

        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, quality=opts.quality
            )
            chameleon.save_file("composite.jpg", composite)
            thumbs = cuav_mosaic.ExtractThumbs(cv.LoadImage("composite.jpg"), 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()
                if opts.fullres:
                    x1 *= 2
                    y1 *= 2
                    x2 *= 2
                    y2 *= 2
                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
        print ("%s scan %.1f fps  %u regions [%u/%u]" % (f, count / total_time, region_count, scan_count, num_files))
Example #7
0
    def CreateSearchPattern(self, width=50.0, overlap=10.0, offset=10, wobble=10, alt=100):
        '''Generate the waypoints for the search pattern, using alternating strips
        width is the width (m) of each strip, overlap is the % overlap between strips, 
        alt is the altitude (relative to ground) of the points'''
        self.SearchPattern = []

        #find the nearest point to Airfield Home - use this as a starting point (if entry lanes are not used)
        if len(self.entryPoints) == 0:
            nearestdist = cuav_util.gps_distance(self.airfieldHome[0], self.airfieldHome[1], self.searchArea[0][0], self.searchArea[0][1])
            nearest = self.searchArea[0]
            for point in self.searchArea:
                newdist = cuav_util.gps_distance(self.airfieldHome[0], self.airfieldHome[1], point[0], point[1])
                if newdist < nearestdist:
                    nearest = point
                    nearestdist = newdist
        else:
            nearestdist = cuav_util.gps_distance(self.entryPoints[0][0], self.entryPoints[0][1], self.searchArea[0][0], self.searchArea[0][1])
            nearest = self.searchArea[0]
            for point in self.searchArea:
                newdist = cuav_util.gps_distance(self.entryPoints[0][0], self.entryPoints[0][1], point[0], point[1])
                #print "dist = " + str(newdist)
                if newdist < nearestdist:
                    nearest = point
                    nearestdist = newdist

        #print "Start = " + str(nearest) + ", dist = " + str(nearestdist)

        #the search pattern will run between the longest side from nearest
        bearing1 = cuav_util.gps_bearing(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)-1][0], self.searchArea[self.searchArea.index(nearest)-1][1])
        bearing2 = cuav_util.gps_bearing(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)+1][0], self.searchArea[self.searchArea.index(nearest)+1][1])
        dist1 = cuav_util.gps_distance(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)-1][0], self.searchArea[self.searchArea.index(nearest)-1][1])
        dist2 = cuav_util.gps_distance(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)+1][0], self.searchArea[self.searchArea.index(nearest)+1][1])
        if dist1 > dist2:
            self.searchBearing = bearing1
        else:
            self.searchBearing = bearing2

        #the search pattern will then run parallel between the two furthest points in the list
        #searchLine = (0, 0)
        #for point in self.searchArea: 
        #    newdist = cuav_util.gps_distance(point[0], point[1], self.searchArea[self.searchArea.index(point)-1][0], self.searchArea[self.searchArea.index(point)-1][1])
        #    if newdist > searchLine[0]:
        #        searchLine = (newdist, cuav_util.gps_bearing(point[0], point[1], self.searchArea[self.searchArea.index(point)-1][0], self.searchArea[self.searchArea.index(point)-1][1]))

        #self.searchBearing = searchLine[1]
        

        #need to find the 90 degree bearing to searchBearing that is inside the search area. This
        #will be the bearing we increment the search rows by
        #need to get the right signs for the bearings, depending which quadrant the search area is in wrt nearest
        if not cuav_util.polygon_outside(cuav_util.gps_newpos(nearest[0], nearest[1], (self.searchBearing + 45) % 360, 10), self.searchArea):
            self.crossBearing = (self.searchBearing + 90) % 360
        elif not cuav_util.polygon_outside(cuav_util.gps_newpos(nearest[0], nearest[1], (self.searchBearing + 135) % 360, 10), self.searchArea):
            self.crossBearing = (self.searchBearing + 90) % 360
            self.searchBearing = (self.searchBearing + 180) % 360
        elif not cuav_util.polygon_outside(cuav_util.gps_newpos(nearest[0], nearest[1], (self.searchBearing - 45) % 360, 10), self.searchArea):
            self.crossBearing = (self.searchBearing - 90) % 360
        else:
            self.crossBearing = (self.searchBearing - 90) % 360
            self.searchBearing = (self.searchBearing - 180) % 360

        print "Search bearing is " + str(self.searchBearing) + "/" + str((self.searchBearing + 180) % 360)
        print "Cross bearing is: " + str(self.crossBearing)

        #the distance between runs is this:
        self.deltaRowDist = width - width*(float(overlap)/100)
        if self.deltaRowDist <= 0:
            print "Error, overlap % is too high"
            return
        print "Delta row = " + str(self.deltaRowDist)

        #expand the search area to 1/2 deltaRowDist to ensure full coverage

        #we are starting at the "nearest" and mowing the lawn parallel to "self.searchBearing"
        #first waypoint is right near the Search Area boundary (without being on it) (10% of deltaRowDist
        #on an opposite bearing (so behind the search area)
        nextWaypoint =  cuav_util.gps_newpos(nearest[0], nearest[1], self.crossBearing, self.deltaRowDist/10)
        print "First = " + str(nextWaypoint)
        #self.SearchPattern.append(firstWaypoint)

        #mow the lawn, every 2nd row:
        while True:
            pts = self.projectBearing(self.searchBearing, nextWaypoint, self.searchArea)
            #print "Projecting " + str(nextWaypoint) + " along " + str(self.searchBearing)
            #check if we're outside the search area
            if pts == 0:
                break
            (nextW, nextnextW) = (pts[0], pts[1])
            if cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextW[0], nextW[1]) < cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextnextW[0], nextnextW[1]):
                self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], (self.searchBearing + 180) % 360, (offset+wobble)))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.searchBearing, (offset+wobble)))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                #now turn 90degrees from bearing and width distance
                nextWaypoint = cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.crossBearing, self.deltaRowDist*2)
                self.searchBearing = (self.searchBearing + 180) % 360
            else:
                self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], (self.searchBearing + 180) % 360, offset+wobble))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], self.searchBearing, (offset+wobble)))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                #now turn 90degrees from bearing and width distance
                nextWaypoint = cuav_util.gps_newpos(nextW[0], nextW[1], self.crossBearing, self.deltaRowDist*2)
                self.searchBearing = (self.searchBearing + 180) % 360

            print "Next = " + str(nextWaypoint)
        
        #go back and do the rows we missed. There still might be one more row to do in 
        # the crossbearing direction, so check for that first
        nextWaypoint = cuav_util.gps_newpos(nextWaypoint[0], nextWaypoint[1], self.crossBearing, -self.deltaRowDist)
        pts = self.projectBearing(self.searchBearing, nextWaypoint, self.searchArea)
        if pts == 0:
            nextWaypoint = cuav_util.gps_newpos(nextWaypoint[0], nextWaypoint[1], self.crossBearing, -2*self.deltaRowDist)
            self.crossBearing = (self.crossBearing + 180) % 360
        else:
            self.crossBearing = (self.crossBearing + 180) % 360

        while True:
            pts = self.projectBearing(self.searchBearing, nextWaypoint, self.searchArea)
            #print "Projecting " + str(nextWaypoint) + " along " + str(self.searchBearing)
            #check if we're outside the search area
            if pts == 0:
                break
            (nextW, nextnextW) = (pts[0], pts[1])
            if cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextW[0], nextW[1]) < cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextnextW[0], nextnextW[1]):
                self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], (self.searchBearing + 180) % 360, offset))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.searchBearing, offset))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                #now turn 90degrees from bearing and width distance
                nextWaypoint = cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.crossBearing, self.deltaRowDist*2)
                self.searchBearing = (self.searchBearing + 180) % 360
            else:
                self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], (self.searchBearing + 180) % 360, offset))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], self.searchBearing, offset))
                self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt)
                #now turn 90degrees from bearing and width distance
                nextWaypoint = cuav_util.gps_newpos(nextW[0], nextW[1], self.crossBearing, self.deltaRowDist*2)
                self.searchBearing = (self.searchBearing + 180) % 360

            print "Next(alt) = " + str(nextWaypoint)

        #add in the altitude points (relative to airfield home)
        for point in self.SearchPattern:
            self.SearchPattern[self.SearchPattern.index(point)] = (point[0], point[1], alt)