Пример #1
0
def calcUVXYZ(pxpts, hmatrix, camEnv):
    # xyzline (list):         Line length (xyz)
    # xyzpts (list):          XYZ coordinates of lines
    # pxline (list):          Line length (px)
    # pxpts (list):           UV coordinates of lines

    invprojvars = CamEnv.setProjection(camEnv.getDEM(), camEnv._camloc,
                                       camEnv._camDirection, camEnv._radCorr,
                                       camEnv._tanCorr, camEnv._focLen,
                                       camEnv._camCen, camEnv._refImage)

    # Calculate homography-corrected pts if desired
    # if hmatrix is not None:
    #     print 'Correcting for camera motion'
    #     pxpts = Velocity.apply_persp_homographyPts(pxpts, hmatrix, inverse=True)

    # Re-format pixel point coordinates
    pxpts = np.squeeze(pxpts)

    # Create OGR pixl line object and extract length
    pxline = getOGRLine(pxpts)
    print 'Line contains %i points' % (pxline.GetPointCount())
    pxline = pxline.Length()
    print 'Line length: %d px' % (pxline)

    if invprojvars is not None:
        # Get xyz coordinates with inverse projection
        xyzpts = projectUV(pxpts, invprojvars)

        # Create ogr line object
        xyzline = getOGRLine(xyzpts)
        xyzline = xyzline.Length()

        print 'Line length: %d m' % (xyzline)

        return [[xyzline, xyzpts], [pxline, pxpts]]

    else:
        # Return pixel coordinates only
        return [[None, None], [pxline, pxpts]]
Пример #2
0
def calcManualArea(img, imn, hmatrix=None, pxplot=None, invprojvars=None):
    '''Manually define an area in a given image. User input is facilitated
    through an interactive plot to click around the area of interest. XYZ areas
    are calculated if a set of inverse projection variables are given.
    
    Args
    img (arr):          Image array (for plotting the image).
    imn (str):          Image name
    pxplot (list):      Plotting extent for manual area definition
    invprojvars (list): Inverse projection variables
    
    Returns
    xyzarea (list):       Sum of total detected areas (xyz)
    xyzpts (list):        XYZ coordinates of detected areas
    pxextent (list):      Sum of total detected areas (px)
    pxpts (list):         UV coordinates of detected areas
    '''    
    #Initialise figure window and plot image
    fig=plt.gcf()
    fig.canvas.set_window_title(imn + ': Click around region. Press enter '
                                'to record points.')
    plt.imshow(img, origin='upper', cmap='gray')
    
    #Set plotting extent if required
    if pxplot is not None:
        plt.axis([pxplot[0],pxplot[1],
                  pxplot[2],pxplot[3]]) 
    
    #Manual input of points from clicking on plot using pyplot.ginput
    rawpx = plt.ginput(n=0, timeout=0, show_clicks=True, mouse_add=1, 
                       mouse_pop=3, mouse_stop=2)
    print('\n' + imn + ': you clicked ' + str(len(rawpx)) + ' points')
    
    #Show plot
    plt.show()
    plt.close()

    #Convert coordinates to array
    pxpts=[]
    for i in rawpx:
        pxpts.append([[i[0],i[1]]])
    pxpts.append([[rawpx[0][0],rawpx[0][1]]])
    pxpts=np.asarray(pxpts)
    
    #Calculate homography-corrected pts if desired
    if hmatrix is not None:
        print('Correcting for camera motion')
        pxpts = Velocity.apply_persp_homographyPts(pxpts, hmatrix, 
                                                   inverse=True)
        
    #Create polygon if area has been recorded   
    try:    
        #Create geometry
        pxpoly=getOGRArea(pxpts.squeeze())
        
        #Calculate area of polygon area
        pxextent = pxpoly.Area()
    
    #Create zero object if no polygon has been recorded 
    except:
        pxextent = 0
    
    print('Total extent: ' + str(pxextent) + ' px (out of ' + 
          str(img.shape[0]*img.shape[1]) + ' px)')    
    
    #Convert pts list to array
    pxpts = np.array(pxpts)           
    pxpts = np.squeeze(pxpts)
    

    if invprojvars is not None:
        #Get xyz coordinates with inverse projection
        xyzpts=projectUV(pxpts, invprojvars) 
        
        #Calculate area of xyz polygon
        xyzarea = getOGRArea(xyzpts)                   
        xyzarea=xyzarea.GetArea()
        
        #Return XYZ and pixel areas
        print('Total area: ' + str(xyzarea) + ' m')
        return [[[xyzarea], [xyzpts]], [[pxextent], [pxpts]]]

    #Return pixel areas only    
    else:
        return [[None, None], [pxextent, pxpts]]          
Пример #3
0
def calcAutoArea(img, imn, colourrange, hmatrix=None, threshold=None, 
                 invprojvars=None):
    '''Detects areas of interest from a given image, and returns pixel and xyz 
    areas along with polygon coordinates. Detection is performed from the image 
    using a predefined RBG colour range. The colour range is then used to 
    extract pixels within that range using the OpenCV function inRange. If a 
    threshold has been set (using the setThreshold function) then only nth 
    polygons will be retained. XYZ areas and polygon coordinates are only 
    calculated when a set of inverse projection variables are provided.
    
    Args
    img (arr):            Image array
    imn (str):            Image name
    colourrange (list):   RBG colour range for areas to be detected from
    threshold (int):      Threshold number of detected areas to retain
    invprojvars (list):   Inverse projection variables
    
    Returns
    xyzarea (list):       Sum of total detected areas (xyz)
    xyzpts (list):        XYZ coordinates of detected areas
    pxextent (list):      Sum of total detected areas (px)
    pxpts (list):         UV coordinates of detected areas
    '''                       
    #Get upper and lower RBG boundaries from colour range
    upper_boundary = colourrange[0]
    lower_boundary = colourrange[1]

    #Transform RBG range to array    
    upper_boundary = np.array(upper_boundary, dtype='uint8')
    lower_boundary = np.array(lower_boundary, dtype='uint8')

    #Extract extent based on RBG range
    mask = cv2.inRange(img, lower_boundary, upper_boundary)

#    #Speckle filter to remove noise - needs fixing
#    mask = cv2.filterSpeckles(mask, 1, 30, 2)

    #Polygonize extents using OpenCV findContours function        
    polyimg, line, hier = cv2.findContours(mask, cv2.RETR_EXTERNAL, 
                                           cv2.CHAIN_APPROX_NONE)
    
    print('\nDetected ' + str(len(line)) + ' regions in ' + str(imn))
    
    #Append all polygons from the polys list that have more than 
    #a given number of points     
    rawpx = []
    for c in line:
        if len(c) >= 40:
            rawpx.append(c)
    
    #If threshold has been set, only keep the nth longest polygons
    if threshold is not None:
        if len(rawpx) >= threshold:
            rawpx.sort(key=len)
            rawpx = rawpx[-(threshold):]        

    print('Kept ' + str(len(rawpx)) + ' regions')
    
    #Calculate homography-corrected pts if desired
    if hmatrix is not None:
        print('Correcting for camera motion')
        pxpts=[]
        for i in rawpx:
            corr = Velocity.apply_persp_homographyPts(i, hmatrix, inverse=True)
            pxpts.append(corr)
    else:
        pxpts=rawpx
                
        
    #Calculate areas
    pxextent=[]
    for p in range(len(pxpts)): 

        try:        
            #Create geometry
            pxpoly=getOGRArea(pxpts[p].squeeze())
            
            #Calculate area of polygon area
            pxextent.append(pxpoly.Area())
        
        #Create zero object if no polygon has been recorded 
        except:
            pxextent = 0
        
    print ('Total extent: ' + str(sum(pxextent)) + ' px (out of ' 
            + str(img.shape[0]*img.shape[1]) + ' px)')  
    
    #Get xyz coordinates with inverse projection
    if invprojvars is not None:
        xyzpts=[]
        xyzarea=[]
        
        for i in pxpts:           
            #Inverse project points 
            proj=projectUV(i, invprojvars)           
            xyzpts.append(proj)
            
            #Get areas for xyz polygons
            ogrpol = getOGRArea(proj)                   
            xyzarea.append(ogrpol.GetArea())
            
        print('Total area: ' + str(sum(xyzarea)) + ' m')
                
        #Return XYZ and pixel areas
        return [[xyzarea, xyzpts], [pxextent, pxpts]]
    
    else:
        #Return pixel areas only
        return [[None, None], [pxextent, pxpts]]
Пример #4
0
    def verifyAreas(self, areas, invprojvars):
        '''Method to manually verify all polygons in images. Plots sequential
        images with detected polygons and the user manually verifies them by 
        clicking them.
        
        Args
        area (list):                XYZ and UV area information
        invprojvars (list):         Inverse projection variables
        
        Returns
        verified (list):            Verified XYZ and UV area information
        '''
        #Create output
        verified = []
        
        #Get UV point coordinates
        uvpts=[item[1][1] for item in areas]
                
        #Verify pixel polygons in each image        
        for i in range(len(uvpts)):
            
            #Call corrected/uncorrected image
            if self._calibFlag is True:
                img1=self._imageSet[i].getImageCorr(self._camEnv.getCamMatrixCV2(), 
                                                    self._camEnv.getDistortCoeffsCV2())      
            else:
                img1=self._imageSet[i].getImageArray()            
            
            #Get image name
            imn=self._imageSet[i].getImageName()
            
            #Verify polygons
            img2 = np.copy(img1)
            
            if 1:                            
                print('\nVerifying detected areas from ' + str(imn))
                
                #Set up empty output list                
                verf = []
                
                #Function for click verification within a plot
                def onpick(event):
                    
                    #Get XY coordinates for clicked point in a plot
                    v = []
                    thisline = event.artist
                    xdata = thisline.get_xdata()
                    ydata = thisline.get_ydata()
                    
                    #Append XY coordinates
                    for x,y in zip(xdata,ydata):
                        v.append([x,y])
                    v2=np.array(v, dtype=np.int32).reshape((len(xdata)),2)
                    verf.append(v2)
                    
                    #Verify extent if XY coordinates coincide with a
                    #detected area
                    ind=event.ind
                    print ('Verified extent at ' + 
                           str(np.take(xdata, ind)[0]) + ', ' + 
                           str(np.take(ydata, ind)[0]))
                
                #Plot image
                fig, ax1 = plt.subplots()
                fig.canvas.set_window_title(imn + ': Click on valid areas.')
                ax1.imshow(img2, cmap='gray')
                
                #Chane plot extent if pxplot variable is present
                if self._pxplot is not None:
                    ax1.axis([self._pxplot[0],self._pxplot[1],
                              self._pxplot[2],self._pxplot[3]])
                
                #Plot all detected areas
                for a in uvpts[i]:
                    x=[]
                    y=[]
                    for b in a:
                        for c in b:
                            x.append(c[0])
                            y.append(c[1])
                    line = Line2D(x, y, linestyle='-', color='y', picker=True)
                    ax1.add_line(line)
                
                #Verify extents using onpick function
                fig.canvas.mpl_connect('pick_event', onpick)
            
            #Show plot
            plt.show() 
            plt.close()
            
            #Append all verified extents
            vpx=[]
            vpx=verf               
            
            #Get areas of verified extents
            h = img2.shape[0]
            w = img2.shape[1]
            px_im = Image.new('L', (w,h), 'black')
            px_im = np.array(px_im) 
            cv2.drawContours(px_im, vpx, -1, (255,255,255), 4)
            for p in vpx:
                cv2.fillConvexPoly(px_im, p, color=(255,255,255))           
            output = Image.fromarray(px_im)

            pixels = output.getdata()
            values = []    
            for px in pixels:
                if px > 0:
                    values.append(px)
            pxext = len(values)        
            print('Total verified extent: ' + str(pxext))  

            #Get xyz coordinates with inverse projection
            if invprojvars is not None:
                vxyzpts=[]
                vxyzarea=[]
                for i in vpx:
                    #Inverse project points 
                    proj=projectUV(i, invprojvars)           
                    vxyzpts.append(proj)
                    ogrpol = getOGRArea(proj)                   
                    vxyzarea.append(ogrpol.GetArea())
                    
                print('Total verified area: ' + str(sum(vxyzarea)) + ' m')            

            verified.append([[pxext, vpx],[vxyzarea, vxyzpts]])                    
            
            #Clear memory            
            self._imageSet[i].clearImage()
            self._imageSet[i].clearImageArray()
        
        #Rewrite verified area data
        return verified
Пример #5
0
#Define camera environment
tu1cam = CamEnv(tu1camenv)

#Get DEM from camera environment
dem = tu1cam.getDEM() 

#Get inverse projection variables through camera info               
invprojvars = setProjection(dem, tu1cam._camloc, tu1cam._camDirection, 
                            tu1cam._radCorr, tu1cam._tanCorr, tu1cam._focLen, 
                            tu1cam._camCen, tu1cam._refImage)
        
#Show GCPs                           
tu1cam.showGCPs()                        

#Inverse project image coordinates using function from CamEnv object                       
tu1_xyz = projectUV(tu1_xy, invprojvars)
print '\n\n' + str(len(tu1_xyz)) + ' locations for calving events georectified'


#-----------------------   Plot xyz location on DEM   -------------------------

print '\n\nPLOTTING XYZ CALVING LOCATIONS'


#Boolean flags (True/False)
save=True                          #Save plot?
show=True                          #Show plot?                          

        
#Retrieve DEM from CamEnv object
demobj=tu1cam.getDEM()
Пример #6
0
def calcManualLine(img, imn, hmatrix=None, invprojvars=None):
    """Manually define a line in a given image to produce XYZ and UV line 
    length and corresponding coordinates. Lines are defined through user input 
    by clicking in the interactive image plot. This primarily operates via the 
    pyplot.ginput function which allows users to define coordinates through 
    plot interaction. If inverse projection variables are given, XYZ lines
    and coordinates are also calculated.
    
    :param img: Image array for plotting.
    :type img: arr
    :param imn: Image name
    :type imn: str
    :param hmatrix: Homography matrix, default to None
    :type hmatrix: arr, optional
    :param invprojvars: Inverse projection variables [X,Y,Z,uv0], default to None
    :type invprojvars: list, optional    
    :returns: Four list elements containing: line length in xyz (list), xyz coordinates of lines (list), line length in pixels (list), and uvcoordinates of lines (list)
    :rtype: list
    """
    #Initialise figure window
    fig = plt.gcf()
    fig.canvas.set_window_title(imn + ': Define line. '
                                'Press enter to record points.')

    #Plot image
    plt.imshow(img, origin='upper', cmap='gray')
    rawpx = plt.ginput(n=0,
                       timeout=0,
                       show_clicks=True,
                       mouse_add=1,
                       mouse_pop=3,
                       mouse_stop=2)
    print('\nYou clicked ' + str(len(rawpx)) + ' points in image ' + str(imn))

    #Show plot
    plt.show()
    plt.close()

    #Convert coordinates to array
    pxpts = []
    for i in rawpx:
        pxpts.append([[i[0], i[1]]])
    pxpts = np.asarray(pxpts)

    #Calculate homography-corrected pts if desired
    if hmatrix is not None:
        print('Correcting for camera motion')
        pxpts = Velocity.apply_persp_homographyPts(pxpts,
                                                   hmatrix,
                                                   inverse=True)

    #Re-format pixel point coordinates
    pxpts = np.squeeze(pxpts)

    #Create OGR pixl line object and extract length
    pxline = getOGRLine(pxpts)
    print('Line contains ' + str(pxline.GetPointCount()) + ' points')
    pxline = pxline.Length()
    print('Line length: ' + str(pxline) + ' px')

    if invprojvars is not None:
        #Get xyz coordinates with inverse projection
        xyzpts = projectUV(pxpts, invprojvars)

        #Create ogr line object
        xyzline = getOGRLine(xyzpts)
        xyzline = xyzline.Length()

        print('Line length: ' + str(xyzline) + ' m')

        return [[xyzline, xyzpts], [pxline, pxpts]]

    else:
        #Return pixel coordinates only
        return [[None, None], [pxline, pxpts]]