Example #1
0
def clip_raster(rast, gt, points):
    # from http://geospatialpython.com/
    minX, minY, maxX, maxY = get_shape_extent(points)
    # Convert the layer extent to image pixel coordinate
    ulX, ulY = world_to_pixel(gt, minX, maxY)
    lrX, lrY = world_to_pixel(gt, maxX, minY)
    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    clip = rast[:, ulY:lrY, ulX:lrX]
    #print [x for x in clip.shape]
    # Create a new geomatrix for the image
    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY
    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    pixels = []
    for p in points:
        pixels.append(world_to_pixel(gt2, p[0], p[1]))
    print pixels
    raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0) # Fill with zeroes
    mask = np.array(list(raster_poly.getdata())).reshape(clip.shape[1:])
    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint8)
    return clip
Example #2
0
def clip_raster(rastarray, geotransform, poly):
    # from http://geospatialpython.com/
    rast = rastarray#rast.ReadAsArray()
    gt = geotransform#rast.GetGeoTransform()
    minX, minY, maxX, maxY = poly.bbox
    # Convert the layer extent to image pixel coordinates
    #minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world_to_pixel(gt, minX, maxY)
    lrX, lrY = world_to_pixel(gt, maxX, minY)
    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    clip = rast[:, ulY:lrY, ulX:lrX]
    # Create a new geomatrix for the image
    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY
    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    pixels = []
    points = poly.points
    for p in points: pixels.append(world_to_pixel(gt2, p[0], p[1]))
    raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0) # Fill with zeroes
    mask = image_to_array(raster_poly)
    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, (clip, np.nan)).astype(gdalnumeric.uint8)
    return clip
Example #3
0
def clip(poly, gt, data):

    minX, maxX = min(poly.envelope.exterior.coords.xy[0]), max(
        poly.envelope.exterior.coords.xy[0])
    minY, maxY = min(poly.envelope.exterior.coords.xy[1]), max(
        poly.envelope.exterior.coords.xy[1])

    uper_left_X, uper_left_Y = geo2pixel((minX, maxY), gt)
    lower_right_X, lower_right_Y = geo2pixel((maxX, minY), gt)

    pxWidth = int(lower_right_X - uper_left_X)
    pxHeight = int(lower_right_Y - uper_left_Y)
    #根据外接矩形裁剪
    clip = data.ReadAsArray(int(uper_left_X), int(uper_left_Y), int(pxWidth),
                            int(pxHeight))

    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY
    ext_pix = np.array(
        [geo2pixel(points, gt2) for points in poly.exterior.coords])
    ext_pix = np.expand_dims(ext_pix, axis=0)
    mask = np.ones([pxHeight, pxWidth], np.uint8)

    mask = cv2.fillPoly(mask, ext_pix, 0)  #介绍CV2.fillploy()
    clip = gdalnumeric.choose(mask, (clip, 0))
    return clip
Example #4
0
def clip_raster(rastarray, geotransform, poly):
    # from http://geospatialpython.com/
    rast = rastarray  #rast.ReadAsArray()
    gt = geotransform  #rast.GetGeoTransform()
    minX, minY, maxX, maxY = poly.bbox
    # Convert the layer extent to image pixel coordinates
    #minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world_to_pixel(gt, minX, maxY)
    lrX, lrY = world_to_pixel(gt, maxX, minY)
    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    clip = rast[:, ulY:lrY, ulX:lrX]
    # Create a new geomatrix for the image
    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY
    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    pixels = []
    points = poly.points
    for p in points:
        pixels.append(world_to_pixel(gt2, p[0], p[1]))
    raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0)  # Fill with zeroes
    mask = image_to_array(raster_poly)
    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, (clip, np.nan)).astype(gdalnumeric.uint8)
    return clip
Example #5
0
def main(shapefile_path, raster_path, fileName):
    # 读取栅格影像路径
    srcArray = gdalnumeric.LoadFile(raster_path)
    # 读取栅格据
    srcImage = gdal.Open(raster_path)
    geoTrans = srcImage.GetGeoTransform()
    # 读取矢量图形数据路径
    shapef = ogr.Open(shapefile_path)
    lyr = shapef.GetLayer(
        os.path.split(os.path.splitext(shapefile_path)[0])[1])
    poly = lyr.GetNextFeature()
    # 矢量图形坐标换算
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)
    # 计算新生成图像大小
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    clip = srcArray[:, ulY:lrY, ulX:lrX]
    xoffset = ulX
    yoffset = ulY
    print("Xoffset, Yoffset = ( %f, %f )" % (xoffset, yoffset))
    # 创建geomatrix
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY
    # 创建一张黑白遮罩图像,将矢量点集映射到像素上
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
        pixels.append(world2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly)
    # 裁剪遮罩
    clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.int16)
    clip = clip.astype(gdalnumeric.int16)
    #加载GTiff驱动,存储结果为tiff图像
    gtiffDriver = gdal.GetDriverByName('GTiff')
    if gtiffDriver is None:
        raise ValueError("Can't load GeoTiff Driver")
    print(type(clip))
    gdalnumeric.SaveArray(clip, fileName, format="GTiff")
    print("裁剪完毕")
    gdal.ErrorReset()
Example #6
0
    def clip_as_array(self, shape):
        ul, lr = self.clipbounds(shape) #upper left, lower right
        ulx, uly = ul
        lrx, lry = lr

        width = int(lrx - ulx)
        height = int(lry - uly)

        # Map points to pixels for drawing the
        # boundary on a blank 8-bit,
        # black and white, mask image.
        pixels = []
        shape_geom = shape.polygon.GetGeometryRef()
        shape_points = shape_geom.GetGeometryRef(0)

        for p in range(shape_points.GetPointCount()):
            p = (shape_points.GetX(p), shape_points.GetY(p))
            pxx, pxy = self.coord2pixel(p)

            if pxx < ulx and pxy < uly:
                pixels.append((ulx, uly))
            elif pxx < ulx and pxy >= uly:
                pixels.append((ulx, pxy))
            elif pxx >= ulx and pxy < uly:
                pixels.append((pxx, uly))
            elif pxx > lrx and pxy > lry:
                pixels.append((lrx, uly))
            elif pxx > lrx and pxy <= lry:
                pixels.append((lrx, pxy))
            elif pxx <= lrx and pxy > lry:
                pixels.append((pxx, lry))
            else:
                pixels.append((pxx, pxy))

        image = Image.new("L", (width, height), 1)
        rasterize = ImageDraw.Draw(image)
        rasterize.polygon(pixels, 0)
        mask = imageToArray(image)

        data = gdalnumeric.LoadFile(self.filepath)
        clipped_data = data[uly:lry, ulx:lrx]

        gdal.ErrorReset()

        return gdalnumeric.choose(mask,
                (clipped_data, 255)).astype(gdalnumeric.uint8)
def main(delete):
    source=r"D:\Program Files\Python学习文档\samples\NDVI\farm.tif"
    target=r"D:\Program Files\Python学习文档\samples\NDVI\Clip_farm.tif"
    shp=r"D:\Program Files\Python学习文档\samples\NDVI\field.shp"
    output=r"D:\Program Files\Python学习文档\samples\NDVI\clip_ndvi.tif"
    compute_band(source,target)
    srcArray = gdalnumeric.LoadFile(target)
    srcImage = gdal.Open(target)
    geoTrans = srcImage.GetGeoTransform()
    shapef = ogr.Open(shp)
    lyr = shapef.GetLayer(os.path.split(os.path.splitext(shp)[0] )[1] )
    poly = lyr.GetNextFeature()
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = World2Pixel(geoTrans, minX, maxY)
    lrX, lrY = World2Pixel(geoTrans, maxX, minY)
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    clip = srcArray[ulY:lrY, ulX:lrX]
    xoffset =  ulX
    yoffset =  ulY
    print("Xoffset, Yoffset = ( %f, %f )" % ( xoffset, yoffset ))
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
      points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
      pixels.append(World2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = ImageToArray(rasterPoly)
    clip = gdalnumeric.choose(mask,(clip, 0)).astype(gdalnumeric.uint8)
    gtiffDriver = gdal.GetDriverByName( 'GTiff' )
    if gtiffDriver is None:
        raise ValueError("Can't find GeoTiff Driver")
    gtiffDriver.CreateCopy(output,OpenArray( clip, prototype_ds=target, xoff=xoffset, yoff=yoffset ))
    if delete and os.path.exists(target):
        os.remove(target)
def clipImage(raster, sourceImagePath, outputImagePath):
    def imageToArray(i):
        """
        Converts a Python Imaging Library array to a 
        gdalnumeric image.
        """
        a=gdalnumeric.fromstring(i.tostring(),'b')
        a.shape=i.im.size[1], i.im.size[0]
        return a
    def arrayToImage(a):
        """
        Converts a gdalnumeric array to a 
        Python Imaging Library Image.
        """
        i=Image.fromstring('L',(a.shape[1],a.shape[0]),
                (a.astype('b')).tostring())
        return i   
    def world2Pixel(geoMatrix, x, y):
      """
      Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
      the pixel location of a geospatial coordinate 
      """

      ulX = geoMatrix[0]
      ulY = geoMatrix[3]
      xDist = geoMatrix[1]
      yDist = geoMatrix[5]
      rtnX = geoMatrix[2]
      rtnY = geoMatrix[4]
      pixel = int((x - ulX) / xDist)
      line = int((y - ulY) / yDist)
      return (pixel, line) 
    def getGeometryExtent(points):
        ## Convert the layer extent to image pixel coordinates V2?
        minX = min(points, key=lambda x: x[0])[0]
        maxX = max(points, key=lambda x: x[0])[0]
        minY = min(points, key=lambda x: x[1])[1]
        maxY = max(points, key=lambda x: x[1])[1]
        return minX, maxX, minY, maxY

    ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### 

    srcImage = gdal.Open(sourceImagePath + raster + '.jp2')                                               
    gdal.Warp(sourceImagePath + raster + '_WGS84.jp2', srcImage, dstSRS='EPSG:4326')                                
    
    ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
    
    srcImage = gdal.Open(sourceImagePath + raster + '_WGS84.jp2') 
    srcArray = gdalnumeric.LoadFile(sourceImagePath + raster + '_WGS84.jp2')
    geoTrans = srcImage.GetGeoTransform()

    sourceMinRasterX = geoTrans[0]
    xPixelSize = geoTrans[1]
    sourceMaxRasterY = geoTrans[3]
    yPixelSize = geoTrans[5]

    sourceRasterHeight = srcImage.RasterYSize
    sourceRasterWidth = srcImage.RasterXSize

    sourceMaxRasterX = sourceMinRasterX+(sourceRasterWidth*xPixelSize)
    sourceMinRasterY = sourceMaxRasterY+(sourceRasterHeight*yPixelSize)

    # Create an OGR layer from a boundary shapefile
    shapefile = ogr.Open("%s.shp" % shp)
    lyr = shapefile.GetLayer("PL")
    poly = lyr.GetNextFeature()
    cutterGeometry = poly.GetGeometryRef()

    rasterWKT = "POLYGON ((%s %s, %s %s, %s %s, %s %s, %s %s))" % (str(sourceMinRasterX), str(sourceMaxRasterY), str(sourceMaxRasterX), str(sourceMaxRasterY), str(sourceMaxRasterX), str(sourceMinRasterY), str(sourceMinRasterX), str(sourceMinRasterY), str(sourceMinRasterX), str(sourceMaxRasterY))
    rasterGeometry = ogr.CreateGeometryFromWkt(rasterWKT)

    shapei = cutterGeometry.Intersection(rasterGeometry)

    pts = shapei.GetGeometryRef(0)
    points = []
    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))
    minX, maxX, minY, maxY = getGeometryExtent(points)

    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)

    if (ulX <0):
        ulX = 0
    if (ulY <0):
        ulY = 0
    if (lrX > sourceRasterWidth):
        lrX = sourceRasterWidth
    if (lrY > sourceRasterHeight):
        lrY = sourceRasterHeight

    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)

    clip = srcArray[ulY:lrY, ulX:lrX]

    # Create a new geomatrix for the image
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    pixels = []

    for p in points:
        pixels.append(world2Pixel(geoTrans, p[0], p[1]))

    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly) 

    ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### 

    try: 
        clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint16 )
    except ValueError:
        clip = mask

    ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### 

    dst_filename = "%s.tif" % output
    #pxWidth = lrX - ulX
    #pxHeight = lrY - ulY
    driver = gdal.GetDriverByName('GTiff')
    dataset = driver.Create(outputImagePath + raster + '.tif' ,pxWidth, pxHeight, 1,gdal.GDT_UInt16)
    dataset.GetRasterBand(1).WriteArray(clip)

    proj=srcImage.GetProjection()
    dataset.SetGeoTransform(geoTrans)
    dataset.SetProjection(proj)
    dataset.FlushCache()
    dataset=None
Example #9
0
def downloadImage(request, result_id, band):
    if request.method == 'GET':
        resultImg = models.QueryResult.objects.filter(pk=result_id).first()
        if resultImg == None:
            raise Http404

        tiles = list(resultImg.tileMatrix)

        src_srs = osr.SpatialReference()
        src_srs.ImportFromWkt(tiles[0].image.wkt)
        tgt_srs = osr.SpatialReference()
        tgt_srs.ImportFromEPSG(4326)
        tgt_srs = src_srs.CloneGeogCS()

        preClipDS, preClipSize, preClipGeoTransform = GetPreClipImage(
            tiles, band, resultImg.imageName, src_srs, tgt_srs)
        # print preClipGeoTransform

        # Raster of input polygons
        rasterPoly = Image.new("L", (preClipSize[0], preClipSize[1]), 1)
        rasterize = ImageDraw.Draw(rasterPoly)

        inputPolygons = resultImg.inputPolygons.polygons

        mostULx = mostLRx = mostULy = mostLRy = None

        for polygon in inputPolygons:
            pixels = []
            inputPolygonReprojected = ReprojectCoords(
                polygon['coordinates'][0], tgt_srs, src_srs)
            for p in inputPolygonReprojected:
                pixels.append(world2Pixel(preClipGeoTransform, p[0], p[1]))

            pixels = intersectPolygonToBorder(pixels, preClipSize[0],
                                              preClipSize[1])
            if pixels is None:
                continue

            print pixels

            if mostULx == None or   \
                mostLRx == None or  \
                mostULy == None or  \
                mostLRy == None:

                mostULx = mostLRx = pixels[0][0]
                mostULy = mostLRy = pixels[0][1]

            for x, y in pixels:
                if x > mostLRx:
                    mostLRx = x
                if x < mostULx:
                    mostULx = x
                if y < mostULy:
                    mostULy = y
                if y > mostLRy:
                    mostLRy = y

            # mostULx, mostULy = world2Pixel(preClipGeoTransform, mostULx, mostULy)
            # mostLRx, mostLRy = world2Pixel(preClipGeoTransform, mostLRx, mostLRy)

            mostULx = 0 if mostULx < 0 else mostULx
            mostLRx = 0 if mostLRx < 0 else mostLRx
            mostULy = 0 if mostULy < 0 else mostULy
            mostLRy = 0 if mostLRy < 0 else mostLRy

            rasterize.polygon(pixels, 0)

        print '%i %i %i %i' % (mostULx, mostULy, mostLRx, mostLRy)

        # clipped the output dataset by minimum rect
        clip = preClipDS.GetRasterBand(1).ReadAsArray(
            0, 0, preClipSize[0], preClipSize[1])[mostULy:mostLRy,
                                                  mostULx:mostLRx]

        # create mask to clip image by polygon
        mask = imageToArray(rasterPoly)[mostULy:mostLRy, mostULx:mostLRx]

        # Clip the image using the mask
        clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint16)

        finalFile = NamedTemporaryFile(suffix='.tif',
                                       prefix=resultImg.imageName + '-' +
                                       str(band))
        gdalnumeric.SaveArray(clip, str(finalFile.name), format="GTiff")

        clippedGeoTransform = [
            preClipGeoTransform[0] + mostULx * preClipGeoTransform[1],
            preClipGeoTransform[1], preClipGeoTransform[2],
            preClipGeoTransform[3] + mostULy * preClipGeoTransform[5],
            preClipGeoTransform[4], preClipGeoTransform[5]
        ]

        ds = gdal.Open(str(finalFile.name), gdal.GA_Update)
        ds.SetGeoTransform(clippedGeoTransform)
        ds.SetProjection(src_srs.ExportToWkt())

        # Return HttpResponse Image
        wrapper = FileWrapper(finalFile)
        content_type = mimetypes.guess_type(finalFile.name)[0]
        response = StreamingHttpResponse(wrapper, content_type='content_type')
        response[
            'Content-Disposition'] = "attachment; filename=%s" % finalFile.name

        return response

        # return HttpResponse(json.dumps(dict(out=output_geo_transform,
        #     ext=ext,
        #     finalXSize=finalXSize,
        #     finalYSize=finalYSize)))

    raise Http404
Example #10
0
    else:
	Usage()

    i = i + 1

if infile is None:
    Usage()
if  outfile is None:
    Usage()
if inNoData is None:
    Usage()
if outNoData is None:
    Usage()

indataset = gdal.Open( infile, GA_ReadOnly )

out_driver = gdal.GetDriverByName(format)
outdataset = out_driver.Create(outfile, indataset.RasterXSize, indataset.RasterYSize, indataset.RasterCount, type)

for iBand in range(1, indataset.RasterCount + 1):
    inband = indataset.GetRasterBand(iBand)
    outband = outdataset.GetRasterBand(iBand)

    for i in range(inband.YSize - 1, -1, -1):
	scanline = inband.ReadAsArray(0, i, inband.XSize, 1, inband.XSize, 1)
        scanline = gdalnumeric.choose( gdalnumeric.equal( scanline, inNoData),
                                       (scanline, outNoData) )
	outband.WriteArray(scanline, 0, i)

Example #11
0
    def run(bands, map_mask, dst_dir):
        cropped_bands = []
        for band in bands:
            # http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html#clip-a-geotiff-with-shapefile
            # http://karthur.org/2015/clipping-rasters-in-python.html
            # https://gis.stackexchange.com/questions/228602/clip-raster-by-mask-without-change-values
            # http://karthur.org/2015/clipping-rasters-in-python.html

            # Copy the file corresponding to the band in the destination directory for the bands
            band_dir, band_filename = os.path.split(band)
            shutil.copy(band, dst_dir)

            # raster_path es our source band
            raster_path = os.path.join(dst_dir, band_filename)
            if band_filename.endswith('.jp2'):
                raster_gtiff = raster_path.replace('.jp2', '.tiff')
                jp2_to_gtiff(raster_path, raster_gtiff)
                raster_path = raster_gtiff

            # Load the source data as a gdalnumeric array
            rast = gdalnumeric.LoadFile(raster_path)

            # Also load as a gdal image to get geotransform
            # (world file) info
            srcImage = gdalnumeric.gdal.Open(raster_path)
            gt = srcImage.GetGeoTransform()
            srcImage = None

            # Create an OGR layer from a boundary shapefile
            shapef = ogr.Open(map_mask)
            lyr = shapef.GetLayer(
                os.path.split(os.path.splitext(map_mask)[0])[1])
            poly = lyr.GetNextFeature()

            # Convert the layer extent to image pixel coordinates
            minX, maxX, minY, maxY = lyr.GetExtent()
            ulX, ulY = world_to_pixel(gt, minX, maxY)
            lrX, lrY = world_to_pixel(gt, maxX, minY)

            # Calculate the pixel size of the new image
            pxWidth = int(lrX - ulX)
            pxHeight = int(lrY - ulY)

            # If the clipping features extend out-of-bounds and ABOVE the raster...
            if gt[3] < maxY:
                # In such a case... ulY ends up being negative--can't have that!
                iY = ulY
                ulY = 0

            try:
                # Multi-band image?
                clip = rast[:, ulY:lrY, ulX:lrX]
            except IndexError:
                # Nope: Must be single-band
                clip = rast[ulY:lrY, ulX:lrX]

            # create pixel offset to pass to new image Projection info
            xoffset = ulX
            yoffset = ulY

            # Create a new geomatrix for the image
            gt2 = list(gt)
            gt2[0] = minX
            gt2[3] = maxY

            # Map points to pixels for drawing the boundary on a blank 8-bit,
            # black and white, mask image.
            points = []
            pixels = []
            geom = poly.GetGeometryRef()
            pts = geom.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(world_to_pixel(gt2, p[0], p[1]))

            raster_poly = Image.new("L", (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(raster_poly)
            rasterize.polygon(pixels, 0)

            # If the clipping features extend out-of-bounds and ABOVE the raster...
            if gt[3] < maxY:
                # The clip features were "pushed down" to match the bounds of the
                #   raster; this step "pulls" them back up
                premask = image_to_array(raster_poly)
                # We slice out the piece of our clip features that are "off the map"
                mask = np.ndarray(
                    (premask.shape[-2] - abs(iY), premask.shape[-1]),
                    premask.dtype)
                mask[:] = premask[abs(iY):, :]
                mask.resize(premask.shape)  # Then fill in from the bottom

                # Most importantly, push the clipped piece down
                gt2[3] = maxY - (maxY - gt[3])
            else:
                mask = image_to_array(raster_poly)

            # Clip the image using the mask
            try:
                clip = gdalnumeric.choose(mask, (clip, 0))
                clip = clip.astype(gdalnumeric.numpy.float32)
            # If the clipping features extend out-of-bounds and BELOW the raster...
            except ValueError:
                # We have to cut the clipping features to the raster!
                rshp = list(mask.shape)
                if mask.shape[-2] != clip.shape[-2]:
                    rshp[0] = clip.shape[-2]

                if mask.shape[-1] != clip.shape[-1]:
                    rshp[1] = clip.shape[-1]

                mask.resize(*rshp, refcheck=False)

                clip = gdalnumeric.choose(mask, (clip, 0))
                clip = clip.astype(gdalnumeric.numpy.float32)

            # Save new tiff
            raster_name, raster_ext = os.path.splitext(band_filename)
            mask_dir, mask_file = os.path.split(map_mask)
            mask_name, mask_ext = os.path.splitext(mask_file)
            cropped_band = os.path.join(
                dst_dir, raster_name + '-' + mask_name + '.tiff')
            gtiff_driver = gdalnumeric.gdal.GetDriverByName('GTiff')
            if gtiff_driver is None:
                raise ValueError("Can't find GeoTiff Driver")
            a = open_array(clip,
                           prototype_ds=raster_path,
                           xoff=xoffset,
                           yoff=yoffset)
            gtiff_driver.CreateCopy(cropped_band, a)

            gdalnumeric.gdal.ErrorReset()

            cropped_bands.append(cropped_band)

            # Remove the files from the auxiliary bands copied to the destination directory
            os.remove(raster_path)
            raster_path = raster_path.replace('.tiff', '.jp2')
            if os.path.exists(raster_path):
                os.remove(raster_path)
        return cropped_bands
Example #12
0
def main(shapefile_path, raster_path):
    # Load the source data as a gdalnumeric array
    srcArray = gdalnumeric.LoadFile(raster_path)

    # Also load as a gdal image to get geotransform
    # (world file) info
    srcImage = gdal.Open(raster_path)
    geoTrans = srcImage.GetGeoTransform()

    # Create an OGR layer from a boundary shapefile
    shapef = ogr.Open(shapefile_path)
    lyr = shapef.GetLayer(
        os.path.split(os.path.splitext(shapefile_path)[0])[1])
    poly = lyr.GetNextFeature()

    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)

    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)

    clip = srcArray[ulY:lrY, ulX:lrX]

    #
    # EDIT: create pixel offset to pass to new image Projection info
    #
    xoffset = ulX
    yoffset = ulY
    print("Xoffset, Yoffset = ( %f, %f )" % (xoffset, yoffset))

    # Create a new geomatrix for the image
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    # Map points to pixels for drawing the
    # boundary on a blank 8-bit,
    # black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
        pixels.append(world2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly)

    # Clip the image using the mask
    # clip = gdalnumeric.choose(mask, \
    #                           (clip, 0)).astype(gdalnumeric.uint8)
    clip = gdalnumeric.choose(mask, (clip, 0))

    real = np.zeros(clip.shape)
    for i in range(len(clip)):
        for j in range(len(clip[i])):
            val = clip[i][j].real
            if (val < -4):
                val = -4
            real[i, j] = val

    dst_ds = gdal.GetDriverByName('GTiff').Create("hello86568.tif", 300, 300,
                                                  1, gdal.GDT_CFloat32)
    # dst_ds.SetGeoTransform([444720, 30, 0, 3751320, 0, -30])
    raster = np.zeros(real.shape, dtype=np.float32)
    dst_ds.GetRasterBand(1).WriteArray(real)
    # Once we're done, close properly the dataset
    dst_ds = None
    # This image has 3 bands so we stretch each one to make them
    # visually brighter
    # for i in range(3):
    clip2 = stretch(clip)

    # Save new tiff
    #
    #  EDIT: instead of SaveArray, let's break all the
    #  SaveArray steps out more explicity so
    #  we can overwrite the offset of the destination
    #  raster
    #
    ### the old way using SaveArray
    #
    # gdalnumeric.SaveArray(clip, "OUTPUT.tif", format="GTiff", prototype=raster_path)
    #
    ###
    #
    # gtiffDriver = gdal.GetDriverByName('GTiff')
    # if gtiffDriver is None:
    #     raise ValueError("Can't find GeoTiff Driver")
    # gtiffDriver.CreateCopy("beijing9.tif",
    #                        gdal_array.OpenArray(clip, prototype_ds=raster_path)
    #                        )
    # real = np.zeros(clip.shape)
    # for i in range(len(clip)):
    #     for j in range(len(clip[i])):
    #         val = clip[i][j].real
    #         real[i, j] = val
    # draw(real)

    # Save as an 8-bit jpeg for an easy, quick preview
    clip3 = clip2.astype(gdalnumeric.uint8)
    gdalnumeric.SaveArray(clip3, "beijing.jpg", format="JPEG")
    # misc.imsave("beijing7.png", clip2)

    gdal.ErrorReset()
Example #13
0
# 地图上的点到用在空白的8位黑白掩模图像上绘制边界的像素
points = []
pixels = []
geom = poly.GetGeometryRef()
pts = geom.GetGeometryRef(0)
for p in range(pts.GetPointCount()):
    points.append((pts.GetX(p), pts.GetY(p)))
for p in points:
    pixels.append(world2Pixel(geoTrans, p[0], p[1]))
rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
rasterize = ImageDraw.Draw(rasterPoly)
rasterize.polygon(pixels, 0)
mask = imageToArray(rasterPoly)

# 用掩模裁剪图像
clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint8)

# 这个图像有3个波段,因此我们得拉伸每一个波段使得他们有更好的可视化效果
for i in range(3):
    clip[i, :, :] = stretch(clip[i, :, :])

# 将ndvi另存为tiff
gdalnumeric.SaveArray(clip,
                      "%s.tiff" % output,
                      format="GTiff",
                      prototype=raster)

# 将ndvi保存为8位的jpeg,以便于快速预览
clip = clip.astype(gdalnumeric.uint8)
gdalnumeric.SaveArray(clip, "%s.jpg" % output, format="JPEG")
Example #14
0
def crop(input_file, extents, geo_trans=None, nodata=np.nan):
    """
    Adapted from http://karthur.org/2015/clipping-rasters-in-python.html

    Clips a raster (given as either a gdal.Dataset or as a numpy.array
    instance) to a polygon layer provided by a Shapefile (or other vector
    layer). If a numpy.array is given, a "GeoTransform" must be provided
    (via dataset.GetGeoTransform() in GDAL). Returns an array. Clip features
    must be a dissolved, single-part geometry (not multi-part). Modified from:

    http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html
    #clip-a-geotiff-with-shapefile

    Arguments:
        rast            A gdal.Dataset or a NumPy array
        features_path   The path to the clipping features
        geo_trans              An optional GDAL GeoTransform to use instead
        nodata          The NoData value; defaults to -9999.

    :param str input_file: input image file path
    :param list extents: extents for the cropped area
    :param list geo_trans: An optional GDAL GeoTransform to use instead
    :param int nodata: The NoData value; defaults to -9999

    :return: clip: cropped part of the image
    :rtype: ndarray
    :return: gt2: geotransform parameters for the cropped image
    :rtype: list
    """
    def image_to_array(i):
        """
        Converts a Python Imaging Library (PIL) array to a gdalnumeric image.
        """
        arr = gdalnumeric.frombuffer(i.tobytes(), 'b')
        arr.shape = i.im.size[1], i.im.size[0]
        return arr

    raster = gdal.Open(input_file)
    # Can accept either a gdal.Dataset or numpy.array instance
    if not isinstance(raster, np.ndarray):
        if not geo_trans:
            geo_trans = raster.GetGeoTransform()
        raster = raster.ReadAsArray()
    else:
        if not geo_trans:
            raise ValueError('geo transform must be supplied')

    # Convert the layer extent to image pixel coordinates
    min_x, min_y, max_x, max_y = extents
    ul_x, ul_y = world_to_pixel(geo_trans, min_x, max_y)
    lr_x, lr_y = world_to_pixel(geo_trans, max_x, min_y)

    # Calculate the pixel size of the new image
    px_width = int(lr_x - ul_x)
    px_height = int(lr_y - ul_y)

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    if geo_trans[3] < max_y:
        # In such a case... ul_y ends up being negative--can't have that!
        # iY = ul_y
        ul_y = 0

    # Multi-band image?
    try:
        clip = raster[:, ul_y:lr_y, ul_x:lr_x]

    except IndexError:
        clip = raster[ul_y:lr_y, ul_x:lr_x]

    # Create a new geomatrix for the image
    gt2 = list(geo_trans)
    gt2[0] = min_x
    gt2[3] = max_y

    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    points = [(min_x, min_y), (max_x, min_y), (max_x, max_y), (min_y, max_y)]
    pixels = []

    for point in points:
        pixels.append(world_to_pixel(gt2, point[0], point[1]))

    raster_poly = Image.new('L', size=(px_width, px_height), color=1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0)  # Fill with zeroes

    mask = image_to_array(raster_poly)

    # Clip the image using the mask
    try:
        clip = gdalnumeric.choose(mask, (clip, nodata))

    # If the clipping features extend out-of-bounds and BELOW the raster...
    except ValueError:
        # We have to cut the clipping features to the raster!
        rshp = list(mask.shape)
        if mask.shape[-2] != clip.shape[-2]:
            rshp[0] = clip.shape[-2]

        if mask.shape[-1] != clip.shape[-1]:
            rshp[1] = clip.shape[-1]

        mask.resize(*rshp, refcheck=False)

        clip = gdalnumeric.choose(mask, (clip, nodata))

    raster = None

    return clip, gt2
Example #15
0
def ShapeClipRaster(shapefile_filename,
                    FLAT,
                    FLON,
                    srcArray,
                    resolutionX=0.01,
                    resolutionY=0.01):

    if not os.path.isfile(shapefile_filename):
        print("%s is not exist, will be exit!!!" % shapefile_filename)
        exit(3)
    inShp = shapefile.Reader(shapefile_filename)

    # 获取shapefile文件经纬度范围
    minX, minY, maxX, maxY = inShp.bbox
    print('minX, maxX, minY, maxY:', minX, maxX, minY, maxY)

    # 获取裁剪区域范围的经纬度
    if minX < np.nanmin(FLON):
        minX = np.nanmin(FLON)
    if maxX > np.nanmax(FLON):
        maxX = np.nanmax(FLON)

    if minY < np.nanmin(FLAT):
        minY = np.nanmin(FLAT)
    if maxY > np.nanmax(FLAT):
        maxY = np.nanmax(FLAT)

    # 计算裁剪区域范围的行列号
    ulX = Calculate_IJ(FLON[0, 0], minX, resolutionX)
    ulY = Calculate_IJ(FLAT[0, 0], maxY, resolutionY)

    lrX = Calculate_IJ(FLON[0, 0], maxX, resolutionX)
    lrY = Calculate_IJ(FLAT[0, 0], minY, resolutionY)

    print('ulX, lrX, ulY, lrY:', ulX, lrX, ulY, lrY)

    # 根据shapefile文件的范围对原始数据进行切片
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    print(" pxHeight, pxWidth:", pxHeight, pxWidth)

    if len(srcArray.shape) == 3:
        Level, Row, Pix = srcArray.shape
        clip = srcArray[:, ulY:lrY, ulX:lrX]
    elif len(srcArray.shape) == 2:
        Row, Pix = srcArray.shape
        clip = srcArray[ulY:lrY, ulX:lrX]
    else:
        print("Input Data Dims is not 2 or 3!!!")
        return -1

    xoffset = ulX
    yoffset = ulY
    print("Xoffset, Yoffset = ( %d, %d )" % (xoffset, yoffset))

    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)

    for shape in inShp.shapes():
        partCount = len(shape.parts)
        print(partCount)

        # 处理除最后一个部分之外的其他部分
        for i in range(partCount - 1):
            pixels = []
            for j in range(shape.parts[i], shape.parts[i + 1] - 1):
                pX = Calculate_IJ(minX, shape.points[j][0], resolutionX)
                pY = Calculate_IJ(maxY, shape.points[j][1], resolutionY)
                pixels.append((pX, pY))
            rasterize.polygon(pixels, 0)

    mask = ImageToArray(rasterPoly)

    clip = gdalnumeric.choose(mask, (clip, 0))
    # clip = clip.astype(gdalnumeric.uint8)
    # clip[clip == 0] = np.nan
    # clip[clip >  1] = np.nan

    return clip
Example #16
0
def clip_raster1(shapefile_path, raster_path):
    '''
    This function will convert the rasterized clipper shapefile
    to a mask for use within GDAL.

    This comes (with slight modification) from:

    https://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html#clip-a-geotiff-with-shapefile

    which is an updated version of:
    
    http://geospatialpython.com/2011/02/clip-raster-using-shapefile.html
    '''
    def imageToArray(i):
        """
        Converts a Python Imaging Library array to a
        gdalnumeric image.
        """
        a = gdalnumeric.fromstring(i.tostring(), 'b')
        a.shape = i.im.size[1], i.im.size[0]
        return a

    def arrayToImage(a):
        """
        Converts a gdalnumeric array to a
        Python Imaging Library Image.
        """
        i = Image.fromstring('L', (a.shape[1], a.shape[0]),
                             (a.astype('b')).tostring())
        return i

    def world2Pixel(geoMatrix, x, y):
        """
        Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
        the pixel location of a geospatial coordinate
        """
        ulX = geoMatrix[0]
        ulY = geoMatrix[3]
        xDist = geoMatrix[1]
        yDist = geoMatrix[5]
        rtnX = geoMatrix[2]
        rtnY = geoMatrix[4]
        pixel = int((x - ulX) / xDist)
        line = int((ulY - y) / xDist)
        return (pixel, line)

    #  EDIT: this is basically an overloaded
    #  version of the gdal_array.OpenArray passing in xoff, yoff explicitly
    #  so we can pass these params off to CopyDatasetInfo
    #
    def OpenArray(array, prototype_ds=None, xoff=0, yoff=0):
        ds = gdal.Open(gdalnumeric.GetArrayFilename(array))

        if ds is not None and prototype_ds is not None:
            if type(prototype_ds).__name__ == 'str':
                prototype_ds = gdal.Open(prototype_ds)
            if prototype_ds is not None:
                gdalnumeric.CopyDatasetInfo(prototype_ds,
                                            ds,
                                            xoff=xoff,
                                            yoff=yoff)
        return ds

    def histogram(a, bins=range(0, 256)):
        """
        Histogram function for multi-dimensional array.
        a = array
        bins = range of numbers to match
        """
        fa = a.flat
        n = gdalnumeric.searchsorted(gdalnumeric.sort(fa), bins)
        n = gdalnumeric.concatenate([n, [len(fa)]])
        hist = n[1:] - n[:-1]
        return hist

    def stretch(a):
        """
        Performs a histogram stretch on a gdalnumeric array image.
        """
        hist = histogram(a)
        im = arrayToImage(a)
        lut = []
        for b in range(0, len(hist), 256):
            # step size
            step = reduce(operator.add, hist[b:b + 256]) / 255
            # create equalization lookup table
            n = 0
            for i in range(256):
                lut.append(n / step)
                n = n + hist[i + b]
        im = im.point(lut)
        return imageToArray(im)

    # Load the source data as a gdalnumeric array
    srcArray = gdalnumeric.LoadFile(raster_path)

    # Also load as a gdal image to get geotransform
    # (world file) info
    srcImage = gdal.Open(raster_path)
    geoTrans = srcImage.GetGeoTransform()

    # Create an OGR layer from a boundary shapefile
    shapef = ogr.Open(shapefile_path)
    lyr = shapef.GetLayer(
        os.path.split(os.path.splitext(shapefile_path)[0])[1])
    poly = lyr.GetNextFeature()

    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)

    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)

    clip = srcArray[:, ulY:lrY, ulX:lrX]

    #
    # EDIT: create pixel offset to pass to new image Projection info
    #
    xoffset = ulX
    yoffset = ulY
    print("Xoffset, Yoffset = ( %f, %f )" % (xoffset, yoffset))

    # Create a new geomatrix for the image
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    # Map points to pixels for drawing the
    # boundary on a blank 8-bit,
    # black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
        pixels.append(world2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly)

    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, \
        (clip, 0)).astype(gdalnumeric.uint8)

    # This image has 3 bands so we stretch each one to make them
    # visually brighter
    for i in range(3):
        clip[i, :, :] = stretch(clip[i, :, :])

    # Save new tiff
    #
    #  EDIT: instead of SaveArray, let's break all the
    #  SaveArray steps out more explicity so
    #  we can overwrite the offset of the destination
    #  raster
    #
    ### the old way using SaveArray
    #
    # gdalnumeric.SaveArray(clip, "OUTPUT.tif", format="GTiff",
    #                       prototype=raster_path)
    #
    ###
    #
    gtiffDriver = gdal.GetDriverByName('GTiff')
    if gtiffDriver is None:
        raise ValueError("Can't find GeoTiff Driver")
    gtiffDriver.CreateCopy(
        "OUTPUT.tif",
        OpenArray(clip, prototype_ds=raster_path, xoff=xoffset, yoff=yoffset))

    # Save as an 8-bit jpeg for an easy, quick preview
    clip = clip.astype(gdalnumeric.uint8)
    gdalnumeric.SaveArray(clip, "OUTPUT.jpg", format="JPEG")

    gdal.ErrorReset()

    return (clip, ulX, ulY, geoTrans)
    def initialClip(self, shapef=None, lyr=None, openfile=True):
        DriverName = "ESRI Shapefile"
        driver = ogr.GetDriverByName(DriverName)
        
        if openfile:
            # Create an OGR layer from a boundary shapefile            
            shapef = driver.Open('%s.shp' % self.countryshp)
            lyr = shapef.GetLayer()
        
        geoTrans = self.srcImage.GetGeoTransform() 
        poly = lyr.GetNextFeature()     
        
            
        minX, maxX, minY, maxY = poly.GetGeometryRef().GetEnvelope()

        ulX, ulY = self.world2Pixel(geoTrans, minX, maxY)
        lrX, lrY = self.world2Pixel(geoTrans, maxX, minY)
        
        # Include offset to position correctly within overall image
        xoffset =  ulX
        yoffset =  ulY
        
        # Correction for countries that exceed satellite dataset boundaries
        if ulY < 0:
            ulY = 0
            yoffset = 0
            maxY = 75.
    
        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)
        
        clip = self.srcArray[ulY:lrY, ulX:lrX]              
        
        # Create a new geomatrix for the image
        geoTrans = list(geoTrans)
        geoTrans[0] = minX
        geoTrans[3] = maxY  
        
        # Create new mask image for each province
        rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)  
        
        geom = poly.GetGeometryRef()
        
        for ring in range(geom.GetGeometryCount()):
            points = []
            pixels = []
            geom_poly = geom.GetGeometryRef(ring)
            
            # If picking the feature gets a polygon, there are islands, 
            # go down another level to get LINEARRING
            if geom_poly.GetGeometryName() == "POLYGON":
                pts = geom_poly.GetGeometryRef(0)
            else:
                pts = geom.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(self.world2Pixel(geoTrans, p[0], p[1]))
            
            rasterize = ImageDraw.Draw(rasterPoly)
            rasterize.polygon(pixels, 0)
            
            mask = self.imageToArray(rasterPoly) 
            
            
        # Clip the image using the mask
        try:
            clip = gdalnumeric.choose(mask, \
                (clip, 0)).astype(gdalnumeric.uint32)
        except:
            print('%s exceeds the boundaries of the satellite dataset' % poly.GetField('name'))
            sys.exit()
            
        # Save clipped province image   
        province_name = poly.GetField('name')           
        gtiffDriver = gdal.GetDriverByName( 'GTiff' )
        if gtiffDriver is None:
            raise ValueError("Can't find GeoTiff Driver")
        if not os.path.exists(self.output):
            os.makedirs(self.output)
        gtiffDriver.CreateCopy( "%s%s.tif" % (self.output, province_name),
            self.OpenArray( clip, prototype_ds=self.raster, xoff=xoffset, yoff=yoffset )
        )
        
        return '%s%s.tif' % (self.output, province_name)
Example #18
0
geo_trans = ds.GetGeoTransform()
w = ds.RasterXSize
h = ds.RasterYSize
img_shape = [h, w]
proj = ds.GetProjection()
cls_l8s2 = ds.GetRasterBand(1).ReadAsArray()
cls_s2 = ds.GetRasterBand(2).ReadAsArray()
cmask = ds.GetRasterBand(3).ReadAsArray().astype(np.int8)
cmask[cmask == 2] = 0
print(np.max(cmask), np.min(cmask))

cls_l8s2[cls_l8s2 == 3] = 33
cls_l8s2[cls_l8s2 == 2] = 3
cls_l8s2[cls_l8s2 == 33] = 2

cliped = gdalnumeric.choose(cmask, (cls_s2, cls_l8s2))

print("rice: ", len(cliped[cliped == 1]))
print("soybean: ", len(cliped[cliped == 2]))
print("corn: ", len(cliped[cliped == 3]))
# build output path
outpath = img_path.replace(".tif", "_masked.tif")
# write output into tiff file
out_ds = gdal.GetDriverByName("GTiff").Create(outpath, w, h, 1, gdal.GDT_Byte)
out_ds.SetProjection(ds.GetProjection())
out_ds.SetGeoTransform(geo_trans)
out_ds.GetRasterBand(1).WriteArray(cliped)
out_ds.FlushCache()

print("done")
Example #19
0
def clip_raster(rast_path, features_path, nodata=-9999):
    """Clip raster to polygon.

    Args:
      rast_path (str): path to raster file
      features_path (str): path to features file or geojson string
      nodata: the no data value

    Returns: (numpy array, GeoTransform)

    Notes: Oddly, the "features path" can be either a filename
      OR a geojson string. GDAL seems to figure it out and do
      the right thing.
    """

    rast = gdal.Open(rast_path)
    band = rast.GetRasterBand(1)
    rast_xsize = band.XSize
    rast_ysize = band.YSize
    gt = rast.GetGeoTransform()

    #Open Features and get all the necessary data for clipping
    #features = ogr.Open(open(features_path).read())
    features = ogr.Open(features_path)
    if features.GetDriver().GetName() == 'ESRI Shapefile':
        lyr = features.GetLayer(
            os.path.split(os.path.splitext(features_path)[0])[1])
    else:
        lyr = features.GetLayer()

    poly = lyr.GetNextFeature()
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world_to_pixel(gt, minX, maxY)
    lrX, lrY = world_to_pixel(gt, maxX, minY)
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    if pxWidth < 0:
        pxWidth = -pxWidth
    if pxHeight < 0:
        pxHeight = -pxHeight

    # If the clipping features extend out-of-bounds and
    # ABOVE the raster...
    # We don't want negative values
    if gt[3] < maxY:
        iY = ulY
        ulY = 0

    # Ensure bounding box doesn't exceed the boundary of the geoTIFF
    if ulX < 0: ulX = 0
    if ulY < 0: ulY = 0
    if ulX + pxWidth > rast_xsize:
        pxWidth = rast_xsize - ulX
    if ulY + pxHeight > rast_ysize:
        pxHeight = rast_ysize - ulY

    clip = rast.ReadAsArray(ulX, ulY, pxWidth, pxHeight)

    # Map points to pixels for drawing the boundary on a blank 8-bit,
    # black and white, mask image. The canvas has the size of
    # pixWidth and pixHeight, the things that are not on the ploy
    # lines will be filled with 1 and on the poly lines will be
    # filled 0.

    # We start from creating a new geomatrix for the image
    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    while pts.GetPointCount() == 0:
        pts = pts.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
        pixels.append(world_to_pixel(gt2, pts.GetX(p), pts.GetY(p)))

    raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0)  # Fill with zeroes

    if gt[3] < maxY:
        premask = image_to_array(raster_poly)
        mask = np.ndarray((premask.shape[-2] - abs(iY), premask.shape[-1]),
                          premask.dtype)
        mask[:] = premask[abs(iY):, :]
        mask.resize(premask.shape)  # Then fill in from the bottom
        gt2[3] = maxY - (maxY - gt[3])
    else:
        mask = image_to_array(raster_poly)

    # Clip the image using the mask, no data is used to fill
    # the unbounded areas.
    try:
        clip = gdalnumeric.choose(mask, (clip, nodata))

    # If the clipping features extend out-of-bounds and
    # BELOW the raster...
    except ValueError:
        # We have to cut the clipping features to the raster!
        rshp = list(mask.shape)
        if mask.shape[-2] != clip.shape[-2]:
            rshp[0] = clip.shape[-2]

        if mask.shape[-1] != clip.shape[-1]:
            rshp[1] = clip.shape[-1]

        mask.resize(*rshp, refcheck=False)
        clip = gdalnumeric.choose(mask, (clip, nodata))

    # TODO: I think this is provided above as gt2
    # newGT = pixel_to_world(gt, ulX, ulY)
    return clip, gt2
Example #20
0
def clip_image_to_shape(source_image_path, output_image_path):
    def image_to_array(pil_array):
        """
        Converts a Python Imaging Library (PIL) array to a
        gdalnumeric image.
        """
        gdal_numeric_array = gdalnumeric.fromstring(pil_array.tobytes(), 'b')
        gdal_numeric_array.shape = pil_array.im.size[1], pil_array.im.size[0]
        return gdal_numeric_array

    def split_path(source_path):
        file_dir = os.path.split(source_path)[0]
        file_name = os.path.split(source_path)[1]
        file_extension = os.path.splitext(file_name)[1]
        file_name = os.path.splitext(file_name)[0]

        print(file_name)

        return file_dir, file_name, file_extension

    def get_geometry_extent(polygons):
        xs = []
        ys = []
        for polygon in polygons:
            for point in polygon:
                xs.append(point[0])
                ys.append(point[1])

        min_x = min(xs)
        max_x = max(xs)
        min_y = min(ys)
        max_y = max(ys)

        # min_x = min(points, key=lambda x: x[0])[0]
        # max_x = max(points, key=lambda x: x[0])[0]
        # min_y = min(points, key=lambda x: x[1])[1]
        # max_y = max(points, key=lambda x: x[1])[1]
        return min_x, max_x, min_y, max_y

    def world_to_pixel(geotransform_matrix, x, y):
        """
        Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
        the pixel location of a geospatial coordinate
        """

        min_x = geotransform_matrix[0]
        max_y = geotransform_matrix[3]
        pixel_size_x = geotransform_matrix[1]
        pixel_size_y = geotransform_matrix[5]
        # rtnX = geotransform_matrix[2]
        # rtnY = geotransform_matrix[4]
        column = int((x - min_x) / pixel_size_x)
        row = int((y - max_y) / pixel_size_y)
        return column, row

    source_file_dir, source_file_name, source_file_extension = split_path(source_image_path)

    # Output file geographic projection
    wkt_projection = 'GEOGCS["WGS 84",' \
                     'DATUM["WGS_1984",' \
                     'SPHEROID["WGS 84",6378137,298.257223563,' \
                     'AUTHORITY["EPSG","7030"]],' \
                     'AUTHORITY["EPSG","6326"]],' \
                     'PRIMEM["Greenwich",0,' \
                     'AUTHORITY["EPSG","8901"]],' \
                     'UNIT["degree",0.01745329251994328,' \
                     'AUTHORITY["EPSG","9122"]],' \
                     'AUTHORITY["EPSG","4326"]]'

    if source_file_extension == '.tif' or source_file_extension == '.tiff':
        source_image = gdal.Open(source_image_path)

        # (x, y) coordinates refer are geographical coordinates (latitude and longtitude)
        # (i, j) and (cols, rows) are pixel coordinates

        # Read coordinates of ground control points (GCPs) and calculate their extent (min and max x, y values)
        gcps = source_image.GetGCPs()
        gcp_x = []
        gcp_y = []
        for a, val in enumerate(gcps):
            gcp_x.append(gcps[a].GCPX)
            gcp_y.append(gcps[a].GCPY)
        min_source_x = min(gcp_x)
        max_source_x = max(gcp_x)
        min_source_y = min(gcp_y)
        max_source_y = max(gcp_y)

        # A warped virtual raster (middle_raster) needs to be created
        # because the source_raster has no geographical projection.
        # That's why it's being reprojected from None to wkt_projection (None to WGS84).
        error_threshold = 0.125
        resampling = gdal.GRA_NearestNeighbour
        middle_image = gdal.AutoCreateWarpedVRT(source_image, None, wkt_projection, resampling, error_threshold)
        source_image = None

        # Calculate the GeoTransform matrix for the input image
        # geotransform[0]   top left x, minimal x value
        # geotransform[1]   pixel width, pixel size in x dimension
        # geotransform[2]   0
        # geotransform[3]   top left y, maximal y value
        # geotransform[4]   0
        # geotransform[5]   pixel height, pixel size in y dimension, should be negative
        source_cols = middle_image.RasterXSize
        source_rows = middle_image.RasterYSize
        geotransform = [min_source_x, (max_source_x - min_source_x) / source_cols, 0,
                        max_source_y, 0, (max_source_y - min_source_y) / source_rows * (-1)]

        # Calculate the x, y coordinates for a lower right corner of the source_image
        pixel_size_source_x = geotransform[1]
        pixel_size_source_y = geotransform[5]
        max_source_x = min_source_x + (source_cols * pixel_size_source_x)
        min_source_y = max_source_y + (source_rows * pixel_size_source_y)

        # Create a polygon equal to extent of the source_image
        # POLYGON((x1 y1, x2 y2, x3 y3, x4 y4, x1 y1))
        image_wkt = 'POLYGON ((' \
                    + str(min_source_x) + ' ' \
                    + str(max_source_y) + ',' \
                    + str(max_source_x) + ' ' \
                    + str(max_source_y) + ',' \
                    + str(max_source_x) + ' ' \
                    + str(min_source_y) + ',' \
                    + str(min_source_x) + ' ' \
                    + str(min_source_y) + ',' \
                    + str(min_source_x) + ' ' \
                    + str(max_source_y) + '))'
        source_geometry = ogr.CreateGeometryFromWkt(image_wkt)

        # Load a *.shp file and read the single feature containing border
        shapefile = ogr.Open(SHP_PATH)
        shapefile_layer = shapefile.GetLayer("PL")
        shapefile_polygon = shapefile_layer.GetNextFeature()
        border_geometry = shapefile_polygon.GetGeometryRef()

        # Calculate the spatial intersection of the source_image and the border shapefile
        # It's a shape of the output image
        output_geometry = border_geometry.Intersection(source_geometry)
        output_geometry_type = output_geometry.GetGeometryType()
        output_geometry_geom_count = output_geometry.GetGeometryCount()

        # GetGeometryType() == 2: LINEARRING
        # GetGeometryType() == 3: POLYGON
        # GetGeometryType() == 6: MULTIPOLYGON

        # Create a list of (x,y) pairs of output_geometry coordinates
        polygons = []
        if output_geometry_type == 3:
            pts = output_geometry.GetGeometryRef(0)
            polygon = []
            for point in range(pts.GetPointCount()):
                polygon.append((pts.GetX(point), pts.GetY(point)))
            polygons.append(polygon)
        elif output_geometry_type == 6:
            for geom in range(output_geometry_geom_count):
                pts = output_geometry.GetGeometryRef(geom)
                pts = pts.GetGeometryRef(0)
                polygon = []
                for p in range(pts.GetPointCount()):
                    polygon.append((pts.GetX(p), pts.GetY(p)))
                polygons.append(polygon)

        # Calculate the pixel extent of the output_geometry polygon
        min_output_x, max_output_x, min_output_y, max_output_y = get_geometry_extent(polygons)
        min_output_i, max_output_j = world_to_pixel(geotransform, min_output_x, max_output_y)
        max_output_i, min_output_j = world_to_pixel(geotransform, max_output_x, min_output_y)

        # If calculated extent is outside of the source_image array it has to be clipped
        if min_output_i < 0:
            min_output_i = 0
        if max_output_j < 0:
            max_output_j = 0
        if max_output_i > source_cols:
            max_output_i = source_cols
        if min_output_j > source_rows:
            min_output_j = source_rows

        # Width and height of the output_raster in pixels
        output_cols = int(max_output_i - min_output_i)
        output_rows = int(min_output_j - max_output_j)

        # Read the middle image as array and select pixels within calculated range
        middle_array = np.array(middle_image.GetRasterBand(1).ReadAsArray())
        clip = middle_array[max_output_j:min_output_j, min_output_i:max_output_i]

        # Calculate the GeoTransform matrix for the output image, it has a different x and y origin
        output_geotransform = geotransform
        output_geotransform[0] = min_output_x
        output_geotransform[3] = max_output_y

        # Convert (x,y) pairs of output_geometry coordinates to pixel coordinates
        polygons_pixel = []
        for polygon in polygons:
            polygon_pixel = []
            for point in polygon:
                polygon_pixel.append(world_to_pixel(output_geotransform, point[0], point[1]))
            polygons_pixel.append(polygon_pixel)

        # Create a new PIL image and rasterize the clipping shape
        polygon_raster = Image.new("L", (output_cols, output_rows), 1)
        rasterize = ImageDraw.Draw(polygon_raster)

        for polygon in polygons_pixel:
            rasterize.polygon(polygon, 0)

        mask = image_to_array(polygon_raster)
        clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint16)

        # Create the output file
        driver = gdal.GetDriverByName('GTiff')
        # !
        # proj = middle_image.GetProjection()
        output_image = driver.Create(output_image_path, output_cols, output_rows, 1, gdal.GDT_UInt16)
        output_image.GetRasterBand(1).WriteArray(clip)
        output_image.SetGeoTransform(output_geotransform)
        # !
        output_image.SetProjection(wkt_projection)
        output_image.FlushCache()
        output_image = None

    elif source_file_extension == '.jp2':
        source_image = gdal.Open(source_image_path)

        # TODO: output_image should be in UTM projection
        gdal.Warp(os.path.join(source_file_dir,
                               source_file_name
                               + '_WGS84'
                               + source_file_extension),
                  source_image,
                  dstSRS='EPSG:4326')

        source_image = gdal.Open(os.path.join(source_file_dir,
                                              source_file_name
                                              + '_WGS84'
                                              + source_file_extension))

        source_array = gdalnumeric.LoadFile(os.path.join(source_file_dir,
                                                         source_file_name
                                                         + '_WGS84'
                                                         + source_file_extension))
        geotransform = source_image.GetGeoTransform()

        min_source_x = geotransform[0]
        max_source_y = geotransform[3]

        source_cols = source_image.RasterXSize
        source_rows = source_image.RasterYSize

        pixel_size_source_x = geotransform[1]
        pixel_size_source_y = geotransform[5]
        max_source_x = min_source_x + (source_cols * pixel_size_source_x)
        min_source_y = max_source_y + (source_rows * pixel_size_source_y)

        image_wkt = 'POLYGON ((' \
                    + str(min_source_x) + ' ' \
                    + str(max_source_y) + ',' \
                    + str(max_source_x) + ' ' \
                    + str(max_source_y) + ',' \
                    + str(max_source_x) + ' ' \
                    + str(min_source_y) + ',' \
                    + str(min_source_x) + ' ' \
                    + str(min_source_y) + ',' \
                    + str(min_source_x) + ' ' \
                    + str(max_source_y) + '))'
        source_geometry = ogr.CreateGeometryFromWkt(image_wkt)

        shapefile = ogr.Open(SHP_PATH)
        shapefile_layer = shapefile.GetLayer("PL")
        shapefile_polygon = shapefile_layer.GetNextFeature()
        border_geometry = shapefile_polygon.GetGeometryRef()

        output_geometry = border_geometry.Intersection(source_geometry)
        output_geometry_type = output_geometry.GetGeometryType()
        output_geometry_geom_count = output_geometry.GetGeometryCount()

        # GetGeometryType() == 2: LINEARRING
        # GetGeometryType() == 3: POLYGON
        # GetGeometryType() == 6: MULTIPOLYGON
        polygons = []
        if output_geometry_type == 3:
            pts = output_geometry.GetGeometryRef(0)
            polygon = []
            for point in range(pts.GetPointCount()):
                polygon.append((pts.GetX(point), pts.GetY(point)))
            polygons.append(polygon)

        elif output_geometry_type == 6:
            for geom in range(output_geometry_geom_count):
                pts = output_geometry.GetGeometryRef(geom)
                pts = pts.GetGeometryRef(0)
                polygon = []
                for p in range(pts.GetPointCount()):
                    polygon.append((pts.GetX(p), pts.GetY(p)))
                polygons.append(polygon)

        min_output_x, max_output_x, min_output_y, max_output_y = get_geometry_extent(polygons)

        min_ouput_i, max_output_j = world_to_pixel(geotransform, min_output_x, max_output_y)
        max_output_i, min_output_j = world_to_pixel(geotransform, max_output_x, min_output_y)

        if min_ouput_i < 0:
            min_ouput_i = 0
        if max_output_j < 0:
            max_output_j = 0
        if max_output_i > source_cols:
            max_output_i = source_cols
        if min_output_j > source_rows:
            min_output_j = source_rows

        output_cols = int(max_output_i - min_ouput_i)
        output_rows = int(min_output_j - max_output_j)

        clip = source_array[max_output_j:min_output_j, min_ouput_i:max_output_i]

        output_geotransform = list(geotransform)
        output_geotransform[0] = min_output_x
        output_geotransform[3] = max_output_y

        polygons_pixel = []
        for polygon in polygons:
            polygon_pixel = []
            for point in polygon:
                polygon_pixel.append(world_to_pixel(output_geotransform, point[0], point[1]))
            polygons_pixel.append(polygon_pixel)

        polygon_raster = Image.new("L", (output_cols, output_rows), 1)
        rasterize = ImageDraw.Draw(polygon_raster)

        for polygon in polygons_pixel:
            rasterize.polygon(polygon, 0)

        mask = image_to_array(polygon_raster)

        clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint16)

        driver = gdal.GetDriverByName('GTiff')
        output_image = driver.Create(output_image_path, output_cols, output_rows, 1, gdal.GDT_UInt16)
        output_image.GetRasterBand(1).WriteArray(clip)

        proj = source_image.GetProjection()
        output_image.SetGeoTransform(output_geotransform)
        output_image.SetProjection(proj)
        output_image.FlushCache()
        output_image = None

    else:
        print('unknown file format')
Example #21
0
def downloadImage(request, result_id, band):
    if request.method == 'GET':
        resultImg = models.QueryResult.objects.filter(pk=result_id).first()
        if resultImg == None:
            raise Http404 

        tiles = list(resultImg.tileMatrix)

        src_srs=osr.SpatialReference()
        src_srs.ImportFromWkt(tiles[0].image.wkt)
        tgt_srs=osr.SpatialReference()
        tgt_srs.ImportFromEPSG(4326)
        tgt_srs = src_srs.CloneGeogCS()

        preClipDS, preClipSize, preClipGeoTransform = GetPreClipImage(tiles, band, resultImg.imageName, src_srs, tgt_srs)
        # print preClipGeoTransform

        # Raster of input polygons
        rasterPoly = Image.new("L", (preClipSize[0], preClipSize[1]), 1)
        rasterize = ImageDraw.Draw(rasterPoly)

        inputPolygons = resultImg.inputPolygons.polygons

        mostULx = mostLRx = mostULy = mostLRy = None

        for polygon in inputPolygons:
            pixels = []
            inputPolygonReprojected = ReprojectCoords(polygon['coordinates'][0], tgt_srs, src_srs)
            for p in inputPolygonReprojected:
                pixels.append(world2Pixel(preClipGeoTransform, p[0], p[1]))

            pixels = intersectPolygonToBorder(pixels, preClipSize[0], preClipSize[1])
            if pixels is None:
                continue
            
            print pixels

            if mostULx == None or   \
                mostLRx == None or  \
                mostULy == None or  \
                mostLRy == None:
                
                mostULx = mostLRx = pixels[0][0]
                mostULy = mostLRy = pixels[0][1]

            for x, y in pixels:
                if x > mostLRx:
                    mostLRx = x
                if x < mostULx:
                    mostULx = x
                if y < mostULy:
                    mostULy = y
                if y > mostLRy:
                    mostLRy = y

            # mostULx, mostULy = world2Pixel(preClipGeoTransform, mostULx, mostULy)
            # mostLRx, mostLRy = world2Pixel(preClipGeoTransform, mostLRx, mostLRy)

            mostULx = 0 if mostULx < 0 else mostULx
            mostLRx = 0 if mostLRx < 0 else mostLRx
            mostULy = 0 if mostULy < 0 else mostULy
            mostLRy = 0 if mostLRy < 0 else mostLRy

            rasterize.polygon(pixels, 0)

        print '%i %i %i %i' % (mostULx, mostULy, mostLRx, mostLRy)

        # clipped the output dataset by minimum rect
        clip = preClipDS.GetRasterBand(1).ReadAsArray(0, 0, preClipSize[0], preClipSize[1])[mostULy:mostLRy, mostULx:mostLRx]

        # create mask to clip image by polygon
        mask = imageToArray(rasterPoly)[mostULy:mostLRy, mostULx:mostLRx]

        # Clip the image using the mask
        clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint16)

        finalFile = NamedTemporaryFile(suffix='.tif', prefix=resultImg.imageName+'-'+str(band))
        gdalnumeric.SaveArray(clip, str(finalFile.name) , format="GTiff")

        clippedGeoTransform = [preClipGeoTransform[0] + mostULx*preClipGeoTransform[1],
                                preClipGeoTransform[1],
                                preClipGeoTransform[2],
                                preClipGeoTransform[3] + mostULy*preClipGeoTransform[5],
                                preClipGeoTransform[4],
                                preClipGeoTransform[5]]
        
        ds = gdal.Open(str(finalFile.name), gdal.GA_Update)
        ds.SetGeoTransform(clippedGeoTransform)
        ds.SetProjection(src_srs.ExportToWkt())
     
         # Return HttpResponse Image
        wrapper = FileWrapper(finalFile)
        content_type = mimetypes.guess_type(finalFile.name)[0]
        response = StreamingHttpResponse(wrapper, content_type='content_type')
        response['Content-Disposition'] = "attachment; filename=%s" % finalFile.name

        return response

        # return HttpResponse(json.dumps(dict(out=output_geo_transform,
        #     ext=ext,
        #     finalXSize=finalXSize,
        #     finalYSize=finalYSize)))
        


    raise Http404
Example #22
0
def clip(poly,rasterObj,field,date=0,vNan=numpy.nan):
    '''
    :param poly:geometry in vectorObj
    :param rasterObj: rasterObj to clip
    :param field: rasterObj clip field
    :return: clip rasterObj and mask rasterObj
    '''

    rasterGeoTrans=rasterObj.getGeoTransform()
    rasterProjection=rasterObj.getProjection()
    rasterArray=rasterObj.getData(field=field,date=date)

    minX, maxX, minY, maxY = poly.GetEnvelope()
    indx1, indy1 = world2Pixel(rasterGeoTrans, minX, maxY)
    indx2, indy2 = world2Pixel(rasterGeoTrans, maxX, minY)

    pxWidth = int(indx2 - indx1)
    pxHeight = int(indy2 - indy1)

    clip = rasterArray[indy1:indy2, indx1:indx2]

    geoTrans = list(rasterGeoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    mask=None
    if poly.GetGeometryType()==6:
        for polygon in poly:
            points = []
            pixels = []
            pts = polygon.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(world2Pixel(geoTrans, p[0], p[1]))
            rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(rasterPoly)
            rasterize.polygon(pixels, 0)
            if mask is None:
                mask = imageToArray(rasterPoly)
            else:
                masktemp = imageToArray(rasterPoly)
                mask=mask*masktemp
    elif poly.GetGeometryType()==3:
        points = []
        pixels = []
        pts = poly.GetGeometryRef(0)
        for p in range(pts.GetPointCount()):
            points.append((pts.GetX(p), pts.GetY(p)))
        for p in points:
            pixels.append(world2Pixel(geoTrans, p[0], p[1]))
        rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
        rasterize = ImageDraw.Draw(rasterPoly)
        rasterize.polygon(pixels, 0)
        mask = imageToArray(rasterPoly)

    clip = gdalnumeric.choose(mask,(clip, vNan))

    dx=rasterGeoTrans[1]
    dy=rasterGeoTrans[5]
    x1=rasterGeoTrans[0]+dx*indx1
    y1=rasterGeoTrans[3]+dy*indy1
    clipGeoTrans=(x1,dx,0.0,y1,0.0,dy)

    gdal.ErrorReset()
    clipObj=EarthModule.EarthObj_raster(field=field,geoProjection=rasterProjection,
                                     geoTransform=clipGeoTrans,data=clip)
    maskObj=EarthModule.EarthObj_raster(field=field,geoProjection=rasterProjection,
                                     geoTransform=clipGeoTrans,data=mask)

    return clipObj,maskObj
pixels = Stream(range(kiev_points.GetPointCount())) \
                .map( lambda i: (kiev_points.GetX(i), kiev_points.GetY(i)) ) \
                .map( lambda x, y: world2pixel(transform, x,y) ).list()

rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
rasterize = ImageDraw.Draw(rasterPoly)
rasterize.polygon(pixels, 0)


mask = gdalnumeric.fromstring(rasterPoly.tobytes(),'b')
mask.shape=rasterPoly.im.size[1], rasterPoly.im.size[0]

print "Create mask %.3f sec" % (timer() - t1)

# Clip the image using the mask
clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint16)
gdalnumeric.SaveArray(clip, "kiev.tif", format="GTiff", prototype=raster_path)


dataset = gdal.GetDriverByName('GTiff')\
              .Create('kiev2.tif', pxWidth, pxHeight, 1, gdal.GDT_Byte)


dataset.SetGeoTransform(transform)
dataset.SetProjection(str(raster_proj))
print 'GetBlockSize()', dataset.GetRasterBand(1).GetBlockSize()
dataset.GetRasterBand(1).SetNoDataValue(0);
dataset.GetRasterBand(1).WriteArray(clip)
dataset.FlushCache()

clip = clip.astype(gdalnumeric.uint8)
Example #24
0
def crop(input_file, extents, geo_trans=None, nodata=np.nan):
    """

    Adapted from http://karthur.org/2015/clipping-rasters-in-python.html

    Clips a raster (given as either a gdal.Dataset or as a numpy.array
    instance) to a polygon layer provided by a Shapefile (or other vector
    layer). If a numpy.array is given, a "GeoTransform" must be provided
    (via dataset.GetGeoTransform() in GDAL). Returns an array. Clip features
    must be a dissolved, single-part geometry (not multi-part). Modified from:

    http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html
    #clip-a-geotiff-with-shapefile

    Parameters
    ----------
    rast:            A gdal.Dataset or a NumPy array
    features_path:   The path to the clipping features
    geo_trans:       An optional GDAL GeoTransform to use instead
    nodata:          The NoData value; defaults to -9999
    """
    def image_to_array(i):
        """
        Converts a Python Imaging Library (PIL) array to a gdalnumeric image
        """
        arr = gdalnumeric.fromstring(i.tobytes(), 'b')
        arr.shape = i.im.size[1], i.im.size[0]
        return arr

    raster = gdal.Open(input_file)
    # Can accept either a gdal.Dataset or numpy.array instance
    if not isinstance(raster, np.ndarray):
        if not geo_trans:
            geo_trans = raster.GetGeoTransform()
        raster = raster.ReadAsArray()
    else:
        if not geo_trans:
            raise ValueError('geo transform must be supplied')

    # Convert the layer extent to image pixel coordinates
    min_x, min_y, max_x, max_y = extents
    ul_x, ul_y = world_to_pixel(geo_trans, min_x, max_y)
    lr_x, lr_y = world_to_pixel(geo_trans, max_x, min_y)

    # Calculate the pixel size of the new image
    px_width = int(lr_x - ul_x)
    px_height = int(lr_y - ul_y)

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    if geo_trans[3] < max_y:
        # In such a case... ul_y ends up being negative--can't have that!
        # iY = ul_y
        ul_y = 0

    # Multi-band image?
    try:
        clip = raster[:, ul_y:lr_y, ul_x:lr_x]

    except IndexError:
        clip = raster[ul_y:lr_y, ul_x:lr_x]

    # Create a new geomatrix for the image
    gt2 = list(geo_trans)
    gt2[0] = min_x
    gt2[3] = max_y

    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    points = [(min_x, min_y), (max_x, min_y), (max_x, max_y), (min_y, max_y)]
    pixels = []

    # for point in range(pts.GetPointCount()):
    #     points.append((pts.GetX(point), pts.GetY(point)))

    for point in points:
        pixels.append(world_to_pixel(gt2, point[0], point[1]))

    raster_poly = Image.new('L', size=(px_width, px_height), color=1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0)  # Fill with zeroes

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    # SB: we don't implement clipping for out-of-bounds and ABOVE the raster
    # We might need this down the line when we have looked at `maximum crop` in
    # detail
    # if geo_trans[3] < max_y:
    #     # The clip features were "pushed down" to match the bounds of the
    #     #   raster; this step "pulls" them back up
    #     premask = image_to_array(raster_poly)
    #     # We slice out the piece of our clip features that are "off the map"
    #     mask = np.ndarray((premask.shape[-2] - abs(iY),
    #                        premask.shape[-1]), premask.dtype)
    #     mask[:] = premask[abs(iY):, :]
    #     mask.resize(premask.shape)  # Then fill in from the bottom
    #
    #     # Most importantly, push the clipped piece down
    #     gt2[3] = max_y - (max_y - geo_trans[3])
    #
    # else:
    #     mask = image_to_array(raster_poly)
    mask = image_to_array(raster_poly)

    # Clip the image using the mask
    try:
        clip = gdalnumeric.choose(mask, (clip, nodata))

    # If the clipping features extend out-of-bounds and BELOW the raster...
    except ValueError:
        # We have to cut the clipping features to the raster!
        rshp = list(mask.shape)
        if mask.shape[-2] != clip.shape[-2]:
            rshp[0] = clip.shape[-2]

        if mask.shape[-1] != clip.shape[-1]:
            rshp[1] = clip.shape[-1]

        mask.resize(*rshp, refcheck=False)

        clip = gdalnumeric.choose(mask, (clip, nodata))
    raster = None  # manual close
    return clip, gt2
Example #25
0
def clipRaster(raster_path,shapefile_path):
    
    """
    Cette fonction prend en entrée un Raster et un vecteur puis elle
    renvoie un raster decouper selon l'emprise du vecteur.
    Entree: raster_path,shapefile_path
    Sortie: clip
    """

    #raster_path='MOD13Q1_h17v07_2000_001_NDVI.tif'
    #shapefile_path='Zones_Etudes.shp'
    # Load the source data as a gdalnumeric array
    srcArray = gdalnumeric.LoadFile(raster_path)
    
    # Also load as a gdal image to get geotransform
    # (world file) info
    srcImage = gdal.Open(raster_path)
    geoTrans = srcImage.GetGeoTransform()
    
    # Create an OGR layer from a boundary shapefile
    shapef = ogr.Open(shapefile_path)
    lyr = shapef.GetLayer( os.path.split( os.path.splitext( shapefile_path )[0] )[1] )
    poly = lyr.GetNextFeature()
    
    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)
    
    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)
    
    clip = srcArray[ulY:lrY, ulX:lrX]
    
    #
    # EDIT: create pixel offset to pass to new image Projection info
    #
    xoffset =  ulX
    yoffset =  ulY
    #print "Xoffset, Yoffset = ( %f, %f )" % ( xoffset, yoffset )
    
    # Create a new geomatrix for the image
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY
    
    # Map points to pixels for drawing the
    # boundary on a blank 8-bit,
    # black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
      points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
      pixels.append(world2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly)
    
    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, \
        (clip, 0)).astype(gdalnumeric.int16)
    
    return clip,minX,maxY,pxHeight,pxWidth
Example #26
0
def clip_raster(rast, features_path, gt=None, nodata=-9999):
    '''
    Copyright: http://karthur.org/2015/clipping-rasters-in-python.html
    
    Clips a raster (given as either a gdal.Dataset or as a numpy.array
    instance) to a polygon layer provided by a Shapefile (or other vector
    layer). If a numpy.array is given, a "GeoTransform" must be provided
    (via dataset.GetGeoTransform() in GDAL). Returns an array. Clip features
    must be a dissolved, single-part geometry (not multi-part). Modified from:

    http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html
    #clip-a-geotiff-with-shapefile

    Arguments:
        rast            A gdal.Dataset or a NumPy array
        features_path   The path to the clipping features
        gt              An optional GDAL GeoTransform to use instead
        nodata          The NoData value; defaults to -9999.
    '''
    def array_to_image(a):
        '''
        Converts a gdalnumeric array to a Python Imaging Library (PIL) Image.
        '''
        i = Image.fromstring('L',(a.shape[1], a.shape[0]),
            (a.astype('b')).tostring())
        return i

    def image_to_array(i):
        '''
        Converts a Python Imaging Library (PIL) array to a gdalnumeric image.
        '''
        a = gdalnumeric.fromstring(i.tobytes(), 'b')
        a.shape = i.im.size[1], i.im.size[0]
        return a

    def world_to_pixel(geo_matrix, x, y):
        '''
        Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
        the pixel location of a geospatial coordinate; from:
        http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html#clip-a-geotiff-with-shapefile
        '''
        ulX = geo_matrix[0]
        ulY = geo_matrix[3]
        xDist = geo_matrix[1]
        yDist = geo_matrix[5]
        rtnX = geo_matrix[2]
        rtnY = geo_matrix[4]
        pixel = int((x - ulX) / xDist)
        line = int((ulY - y) / xDist)
        return (pixel, line)

    # Can accept either a gdal.Dataset or numpy.array instance
    if not isinstance(rast, np.ndarray):
        gt = rast.GetGeoTransform()
        rast = rast.ReadAsArray()

    # Create an OGR layer from a boundary shapefile
    features = ogr.Open(features_path)
    if features.GetDriver().GetName() == 'ESRI Shapefile':
        lyr = features.GetLayer(os.path.split(os.path.splitext(features_path)[0])[1])

    else:
        lyr = features.GetLayer()

    # Get the first feature
    poly = lyr.GetNextFeature()

    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world_to_pixel(gt, minX, maxY)
    lrX, lrY = world_to_pixel(gt, maxX, minY)

    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    if gt[3] < maxY:
        # In such a case... ulY ends up being negative--can't have that!
        iY = ulY
        ulY = 0

    # Multi-band image?
    try:
        clip = rast[:, ulY:lrY, ulX:lrX]

    except IndexError:
        clip = rast[ulY:lrY, ulX:lrX]

    # Create a new geomatrix for the image
    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY

    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)

    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))

    for p in points:
        pixels.append(world_to_pixel(gt2, p[0], p[1]))

    raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0) # Fill with zeroes

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    if gt[3] < maxY:
        # The clip features were "pushed down" to match the bounds of the
        #   raster; this step "pulls" them back up
        premask = image_to_array(raster_poly)
        # We slice out the piece of our clip features that are "off the map"
        mask = np.ndarray((premask.shape[-2] - abs(iY), premask.shape[-1]), premask.dtype)
        mask[:] = premask[abs(iY):, :]
        mask.resize(premask.shape) # Then fill in from the bottom

        # Most importantly, push the clipped piece down
        gt2[3] = maxY - (maxY - gt[3])

    else:
        mask = image_to_array(raster_poly)

    # Clip the image using the mask
    try:
        clip = gdalnumeric.choose(mask, (clip, nodata))

    # If the clipping features extend out-of-bounds and BELOW the raster...
    except ValueError:
        # We have to cut the clipping features to the raster!
        rshp = list(mask.shape)
        if mask.shape[-2] != clip.shape[-2]:
            rshp[0] = clip.shape[-2]

        if mask.shape[-1] != clip.shape[-1]:
            rshp[1] = clip.shape[-1]

        mask.resize(*rshp, refcheck=False)

        clip = gdalnumeric.choose(mask, (clip, nodata))

    return (clip, ulX, ulY, gt2)
Example #27
0
    def clip_raster(rast, features_path, gt=None, nodata=-9999):
        """
        Clips a raster (given as either a gdal.Dataset or as a numpy.array
        instance) to a polygon layer provided by a Shapefile (or other vector
        layer). If a numpy.array is given, a "GeoTransform" must be provided
        (via dataset.GetGeoTransform() in GDAL). Returns an array. Clip features
        must be a dissolved, single-part geometry (not multi-part). Modified from:

        http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html
        #clip-a-geotiff-with-shapefile

        Arguments:
            rast            A gdal.Dataset or a NumPy array
            features_path   The path to the clipping features
            gt              An optional GDAL GeoTransform to use instead
            nodata          The NoData value; defaults to -9999.
        """
        print(features_path)

        def array_to_image(a):
            """
            Converts a gdalnumeric array to a Python Imaging Library (PIL) Image.
            """
            i = Image.fromstring('L', (a.shape[1], a.shape[0]),
                                 (a.astype('b')).tostring())
            return i

        def image_to_array(i):
            """
            Converts a Python Imaging Library (PIL) array to a gdalnumeric image.
            """
            a = gdalnumeric.fromstring(i.tobytes(), 'b')
            a.shape = i.im.size[1], i.im.size[0]
            return a

        def world_to_pixel(geo_matrix, x, y):
            """
            Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
            the pixel location of a geospatial coordinate; from:
            http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html#clip-a-geotiff-with-shapefile
            """
            ul_x = geo_matrix[0]
            ul_y = geo_matrix[3]
            xDist = geo_matrix[1]
            yDist = geo_matrix[5]
            rtnX = geo_matrix[2]
            rtnY = geo_matrix[4]
            pixel = int((x - ul_x) / xDist)
            line = int((ul_y - y) / xDist)
            return pixel, line

        # Can accept either a gdal.Dataset or numpy.array instance
        if not isinstance(rast, np.ndarray):
            print("is not an array")
            gt = rast.GetGeoTransform()
            rast = rast.ReadAsArray()

        # Create an OGR layer from a boundary shapefile
        features = ogr.Open(features_path)
        if features.GetDriver().GetName() == 'ESRI Shapefile':
            lyr = features.GetLayer(
                os.path.split(os.path.splitext(features_path)[0])[1])

        else:
            lyr = features.GetLayer()

        # Get the first feature
        poly = lyr.GetNextFeature()

        # Convert the layer extent to image pixel coordinates
        minX, maxX, minY, maxY = lyr.GetExtent()
        ulX, ulY = world_to_pixel(gt, minX, maxY)
        lrX, lrY = world_to_pixel(gt, maxX, minY)

        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)

        # If the clipping features extend out-of-bounds and ABOVE the raster...
        if gt[3] < maxY:
            # In such a case... ulY ends up being negative--can't have that!
            iY = ulY
            ulY = 0

        # Multi-band image?
        try:
            clip = rast[:, ulY:lrY, ulX:lrX]

        except IndexError:
            clip = rast[ulY:lrY, ulX:lrX]

        # Create a new geomatrix for the image
        gt2 = list(gt)
        gt2[0] = minX
        gt2[3] = maxY

        # Map points to pixels for drawing the boundary on a blank 8-bit,
        #   black and white, mask image.
        points = []
        pixels = []
        geom = poly.GetGeometryRef()
        pts = geom.GetGeometryRef(0)

        for p in range(pts.GetPointCount()):
            points.append((pts.GetX(p), pts.GetY(p)))

        for p in points:
            pixels.append(world_to_pixel(gt2, p[0], p[1]))

        raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
        rasterize = ImageDraw.Draw(raster_poly)
        rasterize.polygon(pixels, 0)  # Fill with zeroes

        # If the clipping features extend out-of-bounds and ABOVE the raster...
        if gt[3] < maxY:
            # The clip features were "pushed down" to match the bounds of the
            #   raster; this step "pulls" them back up
            premask = image_to_array(raster_poly)
            # We slice out the piece of our clip features that are "off the map"
            mask = np.ndarray((premask.shape[-2] - abs(iY), premask.shape[-1]),
                              premask.dtype)
            mask[:] = premask[abs(iY):, :]
            mask.resize(premask.shape)  # Then fill in from the bottom

            # Most importantly, push the clipped piece down
            gt2[3] = maxY - (maxY - gt[3])

        else:
            mask = image_to_array(raster_poly)

        # Clip the image using the mask
        try:
            clip = gdalnumeric.choose(mask, (clip, nodata))

        # If the clipping features extend out-of-bounds and BELOW the raster...
        except ValueError:
            # We have to cut the clipping features to the raster!
            rshp = list(mask.shape)
            if mask.shape[-2] != clip.shape[-2]:
                rshp[0] = clip.shape[-2]

            if mask.shape[-1] != clip.shape[-1]:
                rshp[1] = clip.shape[-1]

            mask.resize(*rshp, refcheck=False)

            clip = gdalnumeric.choose(mask, (clip, nodata))

        return (clip, ulX, ulY, gt2)
Example #28
0
data, data_gray, gt, crs = read_raster(r'./使用数据/裁剪用影像.tif')
poly = vector.iloc[0]['geometry']

minX, maxX = min(poly.envelope.exterior.coords.xy[0]), max(
    poly.envelope.exterior.coords.xy[0])
minY, maxY = min(poly.envelope.exterior.coords.xy[1]), max(
    poly.envelope.exterior.coords.xy[1])

uper_left_X, uper_left_Y = geoToPixel((minX, maxY), gt)
lower_right_X, lower_right_Y = geoToPixel((maxX, minY), gt)

## 计算当前裁剪后栅格的GeoTransform
gt2 = list(gt)
gt2[0] = minX
gt2[3] = maxY

pxWidth = int(lower_right_X - uper_left_X)
pxHeight = int(lower_right_Y - uper_left_Y)
clip1 = data.ReadAsArray(int(uper_left_X), int(uper_left_Y), int(pxWidth),
                         int(pxHeight))

ext_pix = np.array(
    [geoToPixel(points, gt2) for points in poly.exterior.coords])
ext_pix = np.expand_dims(ext_pix, axis=0)
mask = np.ones([pxHeight, pxWidth], np.uint8)

mask = cv2.fillPoly(mask, ext_pix, 0)

clip = gdalnumeric.choose(mask, (clip1, 0))
plt.imshow(clip[1])
saveim(r'./输出数据/裁剪.tif', clip, crs, gt)
Example #29
0
def clip_raster(rast, features_path, output_dir, gt, nodata=-9999,
                save2csv=None, save2raster=None, save2shp=None,
                unit_multiplier=None, return_array=False, OutputSRS=3035,
                suffix_namefield=None, add_suffix=None):
    '''
    Clips a raster (given a numpy.array and its geo-transform array) to a
    polygon layer provided by a Shapefile (or other vector layer). Returns an
    array. Clip features can be multi-part geometry and with interior ring
    inside them.

    The code supports most of raster and clip vector arrangements; however,
    it does not support cases in which clip vector extent (envlope of it) goes
    beyond more than 2 sides of the raster.

    Arguments:
        rast               A NumPy array
        features_path      The path to the clipping layer
        gt                 GDAL GeoTransform array
        nodata             The NoData value; defaults to -9999
        save2csv           should the outputs be saved in a csv file as well?
        unit_multiplier    Factor to be multiplied into the summation to
                           output the desired unit.
        suffix_namefield   What to add at the end of the file name. must be field of shape file
    '''

    def image_to_array(i):
        '''
        Converts a Python Imaging Library (PIL) array to a gdalnumeric image.
        '''
        a = gdalnumeric.fromstring(i.tobytes(), 'b')
        a.shape = i.im.size[1], i.im.size[0]
        return a

    def world_to_pixel(geo_matrix, x, y):
        '''
        Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
        the pixel location of a geospatial coordinate;
        '''
        ulX = geo_matrix[0]
        ulY = geo_matrix[3]
        xDist = geo_matrix[1]
        yDist = geo_matrix[5]
        rtnX = geo_matrix[2]
        rtnY = geo_matrix[4]
        pixel = int((x - ulX) / xDist)
        line = int((ulY - y) / xDist)
        return (pixel, line)

    clip_complete = None
    # get shapefile name
    shpName = features_path.replace('\\', '/')
    shpName = shpName.split('/')[-1][0:-4]
    # Create a data array for the output csv
    if save2csv:
        feat = []
        demand = []
    if unit_multiplier is None:
        unit_multiplier = 1.0
    xRes, yRes = rast.shape
    # Create an OGR layer from a boundary shapefile
    features = ogr.Open(features_path)
    if features.GetDriver().GetName() == 'ESRI Shapefile':
        temp = os.path.split(os.path.splitext(features_path)[0])
        lyr = features.GetLayer(temp[1])
    else:
        lyr = features.GetLayer()
    for fid in range(lyr.GetFeatureCount()):
        flag = np.zeros(4)
        '''
        if fid > 40:
            continue
        '''
        poly = lyr.GetFeature(fid)
        geom = poly.GetGeometryRef()
        if suffix_namefield is not None:
            suffix = poly.GetField(suffix_namefield)
            if add_suffix is not None:
                suffix = '_'+ add_suffix + '_'+ suffix
        else:
            suffix = 'feature_' + str(fid)  
        # Convert the feature extent to image pixel coordinates
        minX, maxX, minY, maxY = geom.GetEnvelope()
        ulX, ulY = world_to_pixel(gt, minX, maxY)
        lrX, lrY = world_to_pixel(gt, maxX, minY)
        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)
        # If the clipping features extend out-of-bounds and ABOVE the raster...
        if gt[3] < maxY:
            if gt[3] < minY:
                continue
            else:
                # In such a case. ulY ends up being negative--can't have that!
                ulY = 0
                flag[0] = 1
        if gt[0] > minX:
            if gt[0] > maxX:
                continue
            else:
                ulX = 0
                flag[1] = 1
        rastXmax = gt[0] + yRes * gt[1]
        if rastXmax < maxX:
            if rastXmax < minX:
                continue
            else:
                lrX = yRes
                flag[2] = 1
        rastYmin = gt[3] + xRes * gt[5]
        if rastYmin > minY:
            if rastYmin > maxY:
                continue
            else:
                lrY = xRes
                flag[3] = 1
        flag_sum = np.sum(flag)
        # Multi-band image?
        try:
            clip = rast[:, ulY:lrY, ulX:lrX]
        except IndexError:
            clip = rast[ulY:lrY, ulX:lrX]
        geometry_counts = geom.GetGeometryCount()
        clip_complete = np.zeros((pxHeight, pxWidth), clip.dtype)
        # perform the process for multi-part features
        for i in range(geometry_counts):
            # Do not delete this. Clip is set to None in each iteration and
            # should be initialized here again.
            try:
                clip = rast[:, ulY:lrY, ulX:lrX]
            except IndexError:
                clip = rast[ulY:lrY, ulX:lrX]
            # Create a new geomatrix for the image
            gt2 = list(gt)
            gt2[0] = gt2[1]*int(minX/gt2[1])
            gt2[3] = gt2[1]*int(maxY/gt2[1])
            if gt2[3] < maxY:
                gt2[3] = gt2[1] * int(maxY/gt2[1] + 1)
            # Map points to pixels for drawing the boundary on a blank 8-bit,
            # black and white, mask image.
            points = []
            pixels = []
            # check multi-part geometries
            if geometry_counts > 1:
                geom1 = geom.GetGeometryRef(i)
                # check multi-part geometry with interior ring
                if geom1.GetGeometryName() == 'LINEARRING':
                    pts = geom1
                else:
                    # get outer ring of polygon
                    pts = geom1.GetGeometryRef(0)
                # print(geom1.GetGeometryName() + ' ' + pts.GetGeometryName())
            else:
                # get outer ring of polygon
                pts = geom.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(world_to_pixel(gt2, p[0], p[1]))
            raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(raster_poly)
            # Fill with zeroes
            rasterize.polygon(pixels, 0)
            premask = image_to_array(raster_poly)
            # with the calculated geotransform matrix gt2, clip matrix should
            # have the same dimension as premask
            clip_new = np.zeros_like(premask, clip.dtype)
            if flag_sum == 0:
                mask = premask
                clip_new = gdalnumeric.choose(mask, (clip, nodata))
            else:
                if flag_sum < 3:
                    row_clip, col_clip = clip.shape
                    index = np.array([-flag[0]*row_clip, flag[3]*row_clip,
                                      -flag[1]*col_clip, flag[2]*col_clip]
                                     ).astype(int)
                    mask_index = np.where(index == 0, None, index)
                    mask = premask[mask_index[0]:mask_index[1],
                                   mask_index[2]:mask_index[3]]
                    clip = gdalnumeric.choose(mask, (clip, nodata))
                    clip_new[mask_index[0]:mask_index[1],
                             mask_index[2]:mask_index[3]] = clip
                else:
                    s = 1
#                    raise InputError('Clip for the feature %d is not '
#                                     'supported' % fid)
            m1, n1 = np.nonzero(clip_new)
            clip_stack = set(list(zip(m1, n1)))
            m2, n2 = np.nonzero(clip_complete)
            clip_complete_stack = set(list(zip(m2, n2)))
            intersect_clip = clip_complete_stack.intersection(clip_stack)
            if len(intersect_clip) == 0:
                clip_complete = clip_complete + clip_new
            else:
                clip_complete = clip_complete - clip_new
            mask = None
            premask = None
            raster_poly = None
            rasterize = None
            geom1 = None
            pts = None
            gt3 = gt2
            gt2 = None
            clip = None
            clip_new = None
        if save2csv:
            nuts_region = str(poly.GetField(0))
            dem_sum = np.sum(clip_complete) * unit_multiplier
            if dem_sum > 0:
                feat.append(nuts_region)
                demand.append(dem_sum)
                print('The sum of values within the region %s is: %0.1f'
                      % (nuts_region, dem_sum))
        if save2raster:
            if not save2csv:
                dem_sum = np.sum(clip_complete) * unit_multiplier
            if dem_sum > 0:
                outRasterPath = output_dir + os.sep + shpName + '_feature_' + \
                                str(fid) + '.tif'
                outRasterPath = output_dir + os.sep + shpName + '_' + \
                                suffix + '.tif'
                CM19.main(outRasterPath, gt3, str(clip_complete.dtype),
                          clip_complete, 0)
    if save2csv or save2shp:
        saveCSVorSHP(feat, demand, features_path, output_dir, shpName,
                     save2csv, save2shp, OutputSRS=OutputSRS)
    if return_array:
        return clip_complete, gt3
Example #30
0
def CLIP( shapefile_path, raster_path, outputName ):
    # Load the source data as a gdalnumeric array
    #shapefile_path = "C:/Users/Ray/Desktop/Clip/studyArea.shp"
    shapefile_path = str(shapefile_path)
    raster_path = str(raster_path)
    #raster_path = "C:/Users/Ray/Desktop/Clip/1.tif"
    print shapefile_path
    print raster_path
    srcArray = gdalnumeric.LoadFile(raster_path)

    # Also load as a gdal image to get geotransform
    # (world file) info
    srcImage = gdal.Open(raster_path)
    geoTrans = srcImage.GetGeoTransform()

    # Create an OGR layer from a boundary shapefile
    print shapefile_path

    shapef = ogr.Open(shapefile_path)
    print type(shapef)
    lyr = shapef.GetLayer( os.path.split( os.path.splitext( shapefile_path )[0] )[1] )
    poly = lyr.GetNextFeature()

    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)

    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)

    clip = srcArray[ ulY:lrY, ulX:lrX]

    #
    # EDIT: create pixel offset to pass to new image Projection info
    #
    xoffset =  ulX
    yoffset =  ulY
    print "Xoffset, Yoffset = ( %f, %f )" % ( xoffset, yoffset )

    # Create a new geomatrix for the image
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    # Map points to pixels for drawing the
    # boundary on a blank 8-bit,
    # black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
      points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
      pixels.append(world2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly)

    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, \
        (clip, 0)).astype('float64')


    # Save new tiff
    #
    #  EDIT: instead of SaveArray, let's break all the
    #  SaveArray steps out more explicity so
    #  we can overwrite the offset of the destination
    #  raster
    #
    ### the old way using SaveArray
    #
    # gdalnumeric.SaveArray(clip, "OUTPUT.tif", format="GTiff", prototype=raster_path)
    #
    ###
    #
    gtiffDriver = gdal.GetDriverByName( 'GTiff' )
    if gtiffDriver is None:
        raise ValueError("Can't find GeoTiff Driver")
    gtiffDriver.CreateCopy( outputName,
        OpenArray( clip, prototype_ds=raster_path, xoff=xoffset, yoff=yoffset )
    )

    # Save as an 8-bit jpeg for an easy, quick preview
    clip = clip.astype('float64')
    def clip_by_shape(self, geom_wkt, nodata=-32767):
        '''
  Clip an Imagee by wkt geometry.
  '''
        rast = self._data
        gt = self._metadata['affine_transformation']

        poly = ogr.CreateGeometryFromWkt(geom_wkt)

        # Convert the layer extent to image pixel coordinates
        minX, maxX, minY, maxY = poly.GetEnvelope()
        ulX, ulY = world_to_pixel(gt, minX, maxY)
        lrX, lrY = world_to_pixel(gt, maxX, minY)

        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)

        # If the clipping features extend out-of-bounds and ABOVE the raster...
        if gt[3] < maxY:
            # In such a case... ulY ends up being negative--can't have that!
            iY = ulY
            ulY = 0

        clip = rast[ulY:lrY, ulX:lrX]

        # Create a new geomatrix for the image
        gt2 = list(gt)
        gt2[0] = minX
        gt2[3] = maxY

        # Map points to pixels for drawing the boundary on a blank 8-bit,
        #   black and white, mask image.

        raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
        rasterize = ImageDraw.Draw(raster_poly)

        def rec(poly_geom):
            '''
   Recursive drawing of parts of multipolygons over initialized PIL Image object using ImageDraw.Draw method.
   '''
            if poly_geom.GetGeometryCount() == 0:
                points = []
                pixels = []
                for p in range(poly_geom.GetPointCount()):
                    points.append((poly_geom.GetX(p), poly_geom.GetY(p)))
                for p in points:
                    pixels.append(world_to_pixel(gt2, p[0], p[1]))
                rasterize.polygon(pixels, 0)
            if poly_geom.GetGeometryCount() >= 1:
                for j in range(poly_geom.GetGeometryCount()):
                    rec(poly_geom.GetGeometryRef(j))

        rec(poly)

        mask = image_to_array(raster_poly)

        # Clip the image using the mask
        try:
            clip = gdalnumeric.choose(mask, (clip, nodata))

        # If the clipping features extend out-of-bounds and BELOW the raster...
        except ValueError:
            # We have to cut the clipping features to the raster!
            rshp = list(mask.shape)
            if mask.shape[-2] != clip.shape[-2]:
                rshp[0] = clip.shape[-2]

            if mask.shape[-1] != clip.shape[-1]:
                rshp[1] = clip.shape[-1]

            mask.resize(*rshp, refcheck=False)

            clip = gdalnumeric.choose(mask, (clip, nodata))

        d = {}
        d['affine_transformation'], d['ul_x'], d['ul_y'], d[
            'nodata'] = gt2, ulX, ulY, -32767
        return (clip, d)
Example #32
0
def ObtainPixelsfromShape(field, rasterPath, shapePath, INX):

    # field='zona'
    #img = gdal.Open('Testimg/subset_RGBNIR_affected_trees')
    # shapefile = "Testimg/features.shp"
    # open dataset, also load as a gdal image to get geotransform
    print "Starting clip...."
    start = time.time()

    img = gdal.Open(rasterPath)
    geoTrans = img.GetGeoTransform()
    geoTransaux = img.GetGeoTransform()
    proj = img.GetProjection()
    imgarrayaux = img.ReadAsArray().shape

    #open shapefile
    driver = ogr.GetDriverByName("ESRI Shapefile")
    dataSource = driver.Open(shapePath, 0)
    layer = dataSource.GetLayer()
    clipdic = defaultdict(list)
    count = 0

    #Convert the layer extent to image pixel coordinates, we read only de pixels needed
    for feature in layer:
        minX, maxX, minY, maxY = feature.GetGeometryRef().GetEnvelope()
        geoTrans = img.GetGeoTransform()

        ulX, ulY = world2Pixel(geoTrans, minX, maxY)
        lrX, lrY = world2Pixel(geoTrans, maxX, minY)
        #print ulX,lrX,ulY,lrY

        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)

        if INX == True:
            clip = ReadClipArray(lrY, ulY, lrX, ulX, img)
            clip = NewBands(clip, lrY, ulY, lrX, ulX)

        else:
            #print"Indexes = False"
            clip = ReadClipArray(lrY, ulY, lrX, ulX, img)

        # print clip[0]
        #print"Paso 2"
    #Image and shape to return in the same shape as it needs the classificator algorithms
    # imgReturn = np.concatenate(imgaux.T)
    # shapeReturn = imgaux.shape
    #imgReturn = np.concatenate(imgaux.T)
    # shapeReturn = img.ReadAsArray().shape

    # clip = imgarray[:, ulY:lrY, ulX:lrX]
    # print clip[0]

    #EDIT: create pixel offset to pass to new image Projection info
        xoffset = ulX
        yoffset = ulY
        #print "Xoffset, Yoffset = ( %d, %d )" % ( xoffset, yoffset )

        # Create a new geomatrix for the image
        geoTrans = list(geoTrans)
        geoTrans[0] = minX
        geoTrans[3] = maxY

        # Map points to pixels for drawing the boundary on a blank 8-bit, black and white, mask image.
        points = []
        pixels = []
        geom = feature.GetGeometryRef()
        pts = geom.GetGeometryRef(0)

        [
            points.append((pts.GetX(p), pts.GetY(p)))
            for p in range(pts.GetPointCount())
        ]

        [pixels.append(world2Pixel(geoTrans, p[0], p[1])) for p in points]

        rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
        rasterize = ImageDraw.Draw(rasterPoly)
        rasterize.polygon(pixels, 0)
        mask = imageToArray(rasterPoly)
        #print mask.shape

        # #SHow the clips of the features
        # plt.imshow(mask)
        # plt.show()

        # Clip the image using the mask into a dict
        temp = gdalnumeric.choose(mask, (clip, np.nan))

        # #SHow the clips of the image
        # plt.imshow(temp[4])
        # plt.show()
        temp = np.concatenate(temp.T)
        temp = temp[~np.isnan(temp[:, 0])]

        clipdic[str(feature.GetField(field))].append(temp)
        count += temp.shape[0]
    end = time.time()
    print "Time clipshape:"
    print(end - start)
    return clipdic, count


##########################################################################
Example #33
0
def get_area_by_state(palmmask, geoTrans, stateshppath, yearlabel):
    shapef = ogr.Open(stateshppath)
    lyr = shapef.GetLayer()
    arealist = []  # list which store area infos
    # arealist.append(["Name", "MPOB_area", "palm_area", "Error"])
    npoly = 0
    poly = lyr.GetNextFeature()
    while poly:
        # loop poly in lyr
        # Convert the layer extent to image pixel coordinates
        if npoly > 11:
            break
        pid = poly.GetField("NAME_1")
        npoly = npoly + 1
        # print(npoly, pid)
        geon = poly.GetGeometryRef()
        geontype = geon.GetGeometryType()
        if geon.GetGeometryType() not in [3, 6]:
            raise SystemExit("This module can only load polygon/multipolygons")
        minX, maxX, minY, maxY = geon.GetEnvelope()
        ulX, ulY = world2Pixel(geoTrans, minX, maxY)
        lrX, lrY = world2Pixel(geoTrans, maxX, minY)
        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)
        clip = palmmask[ulY:lrY, ulX:lrX]

        # Create a new geomatrix for the image
        ngeoTrans = list(geoTrans)
        ngeoTrans[0] = minX
        ngeoTrans[3] = maxY

        # Map points to pixels
        points = []
        pixels = []

        # for multipolygons
        geontype = geon.GetGeometryType()
        if geontype == 6:
            # multipolygon
            rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(rasterPoly)
            i = 0

            for geonpart in geon:
                # loop each part polygon
                i = i + 1
                pts = geonpart.GetGeometryRef(0)
                np = pts.GetPointCount()
                points = []
                pixels = []
                if np == 0:
                    continue
                for p in range(pts.GetPointCount()):
                    points.append((pts.GetX(p), pts.GetY(p)))
                for p in points:
                    pixels.append(world2Pixel(ngeoTrans, p[0], p[1]))
                rasterize.polygon(pixels, 0)
            mask = imageToArray(rasterPoly)

        # for polygons
        if geon.GetGeometryType() == 3:
            points = []
            pixels = []
            rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(rasterPoly)
            pts = geon.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(world2Pixel(ngeoTrans, p[0], p[1]))
            rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(rasterPoly)
            rasterize.polygon(pixels, 0)
            mask = imageToArray(rasterPoly)

        # Clip the image using the mask and calculate palm percentage
        cliped = gdalnumeric.choose(mask, (clip, 0))  # .astype(gdalnumeric.uint8)
        x = cliped[cliped > 0]  # watch out >0
        palmnum = len(x)
        palm_area = round(palmnum * 20 * 20 * 0.0001, 2)
        MPOB_area = settings.MPOB_data[yearlabel][pid]
        palm_error = round(100.0 * (palm_area - MPOB_area) / (MPOB_area), 2)
        arealist.append([pid, MPOB_area, palm_area, palm_error])
        poly = lyr.GetNextFeature()
    return arealist
Example #34
0
def main(shapefile_path, raster_path):
    # Load the source data as a gdalnumeric array
    srcArray = gdalnumeric.LoadFile(raster_path)

    # Also load as a gdal image to get geotransform
    # (world file) info
    srcImage = gdal.Open(raster_path)
    geoTrans = srcImage.GetGeoTransform()

    # Create an OGR layer from a boundary shapefile
    shapef = ogr.Open(shapefile_path)
    lyr = shapef.GetLayer(
        os.path.split(os.path.splitext(shapefile_path)[0])[1])
    poly = lyr.GetNextFeature()

    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world2Pixel(geoTrans, minX, maxY)
    lrX, lrY = world2Pixel(geoTrans, maxX, minY)

    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    pxHeight = int(lrY - ulY)

    clip = srcArray[:, ulY:lrY, ulX:lrX]

    #
    # EDIT: create pixel offset to pass to new image Projection info
    #
    xoffset = ulX
    yoffset = ulY
    print
    "Xoffset, Yoffset = ( %f, %f )" % (xoffset, yoffset)

    # Create a new geomatrix for the image
    geoTrans = list(geoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    # Map points to pixels for drawing the
    # boundary on a blank 8-bit,
    # black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)
    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))
    for p in points:
        pixels.append(world2Pixel(geoTrans, p[0], p[1]))
    rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(rasterPoly)
    rasterize.polygon(pixels, 0)
    mask = imageToArray(rasterPoly)

    # Clip the image using the mask
    clip = gdalnumeric.choose(mask, \
                              (clip, 0)).astype(gdalnumeric.uint8)

    # This image has 3 bands so we stretch each one to make them
    # visually brighter
    for i in range(3):
        clip[i, :, :] = stretch(clip[i, :, :])

    # Save new tiff
    #
    #  EDIT: instead of SaveArray, let's break all the
    #  SaveArray steps out more explicity so
    #  we can overwrite the offset of the destination
    #  raster
    #
    ### the old way using SaveArray
    #
    # gdalnumeric.SaveArray(clip, "OUTPUT.tif", format="GTiff", prototype=raster_path)
    #
    ###
    #
    gtiffDriver = gdal.GetDriverByName('GTiff')
    if gtiffDriver is None:
        raise ValueError("Can't find GeoTiff Driver")
    gtiffDriver.CreateCopy(
        "beijing.tif",
        OpenArray(clip, prototype_ds=raster_path, xoff=xoffset, yoff=yoffset))

    # Save as an 8-bit jpeg for an easy, quick preview
    clip = clip.astype(gdalnumeric.uint8)
    gdalnumeric.SaveArray(clip, "beijing.jpg", format="JPEG")

    gdal.ErrorReset()
Example #35
0
def clip(poly, rasterObj, field, date=0, vNan=numpy.nan):
    '''
    :param poly:geometry in vectorObj
    :param rasterObj: rasterObj to clip
    :param field: rasterObj clip field
    :return: clip rasterObj and mask rasterObj
    '''

    rasterGeoTrans = rasterObj.getGeoTransform()
    rasterProjection = rasterObj.getProjection()
    rasterArray = rasterObj.getData(field=field, date=date)

    minX, maxX, minY, maxY = poly.GetEnvelope()
    indx1, indy1 = world2Pixel(rasterGeoTrans, minX, maxY)
    indx2, indy2 = world2Pixel(rasterGeoTrans, maxX, minY)

    pxWidth = int(indx2 - indx1)
    pxHeight = int(indy2 - indy1)

    clip = rasterArray[indy1:indy2, indx1:indx2]

    geoTrans = list(rasterGeoTrans)
    geoTrans[0] = minX
    geoTrans[3] = maxY

    mask = None
    if poly.GetGeometryType() == 6:
        for polygon in poly:
            points = []
            pixels = []
            pts = polygon.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(world2Pixel(geoTrans, p[0], p[1]))
            rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
            rasterize = ImageDraw.Draw(rasterPoly)
            rasterize.polygon(pixels, 0)
            if mask is None:
                mask = imageToArray(rasterPoly)
            else:
                masktemp = imageToArray(rasterPoly)
                mask = mask * masktemp
    elif poly.GetGeometryType() == 3:
        points = []
        pixels = []
        pts = poly.GetGeometryRef(0)
        for p in range(pts.GetPointCount()):
            points.append((pts.GetX(p), pts.GetY(p)))
        for p in points:
            pixels.append(world2Pixel(geoTrans, p[0], p[1]))
        rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
        rasterize = ImageDraw.Draw(rasterPoly)
        rasterize.polygon(pixels, 0)
        mask = imageToArray(rasterPoly)

    clip = gdalnumeric.choose(mask, (clip, vNan))

    dx = rasterGeoTrans[1]
    dy = rasterGeoTrans[5]
    x1 = rasterGeoTrans[0] + dx * indx1
    y1 = rasterGeoTrans[3] + dy * indy1
    clipGeoTrans = (x1, dx, 0.0, y1, 0.0, dy)

    gdal.ErrorReset()
    clipObj = EarthModule.EarthObj_raster(field=field,
                                          geoProjection=rasterProjection,
                                          geoTransform=clipGeoTrans,
                                          data=clip)
    maskObj = EarthModule.EarthObj_raster(field=field,
                                          geoProjection=rasterProjection,
                                          geoTransform=clipGeoTrans,
                                          data=mask)

    return clipObj, maskObj
    def initialClip(self, shapef=None, lyr=None, openfile=True):
        DriverName = "ESRI Shapefile"
        driver = ogr.GetDriverByName(DriverName)

        if openfile:
            # Create an OGR layer from a boundary shapefile
            shapef = driver.Open('%s.shp' % self.countryshp)
            lyr = shapef.GetLayer()

        geoTrans = self.srcImage.GetGeoTransform()
        poly = lyr.GetNextFeature()

        minX, maxX, minY, maxY = poly.GetGeometryRef().GetEnvelope()

        ulX, ulY = self.world2Pixel(geoTrans, minX, maxY)
        lrX, lrY = self.world2Pixel(geoTrans, maxX, minY)

        # Include offset to position correctly within overall image
        xoffset = ulX
        yoffset = ulY

        # Correction for countries that exceed satellite dataset boundaries
        if ulY < 0:
            ulY = 0
            yoffset = 0
            maxY = 75.

        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)

        clip = self.srcArray[ulY:lrY, ulX:lrX]

        # Create a new geomatrix for the image
        geoTrans = list(geoTrans)
        geoTrans[0] = minX
        geoTrans[3] = maxY

        # Create new mask image for each province
        rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)

        geom = poly.GetGeometryRef()

        for ring in range(geom.GetGeometryCount()):
            points = []
            pixels = []
            geom_poly = geom.GetGeometryRef(ring)

            # If picking the feature gets a polygon, there are islands,
            # go down another level to get LINEARRING
            if geom_poly.GetGeometryName() == "POLYGON":
                pts = geom_poly.GetGeometryRef(0)
            else:
                pts = geom.GetGeometryRef(0)
            for p in range(pts.GetPointCount()):
                points.append((pts.GetX(p), pts.GetY(p)))
            for p in points:
                pixels.append(self.world2Pixel(geoTrans, p[0], p[1]))

            rasterize = ImageDraw.Draw(rasterPoly)
            rasterize.polygon(pixels, 0)

            mask = self.imageToArray(rasterPoly)

        # Clip the image using the mask
        try:
            clip = gdalnumeric.choose(mask, \
                (clip, 0)).astype(gdalnumeric.uint32)
        except:
            print('%s exceeds the boundaries of the satellite dataset' %
                  poly.GetField('name'))
            sys.exit()

        # Save clipped province image
        province_name = poly.GetField('name')
        gtiffDriver = gdal.GetDriverByName('GTiff')
        if gtiffDriver is None:
            raise ValueError("Can't find GeoTiff Driver")
        if not os.path.exists(self.output):
            os.makedirs(self.output)
        gtiffDriver.CreateCopy(
            "%s%s.tif" % (self.output, province_name),
            self.OpenArray(clip,
                           prototype_ds=self.raster,
                           xoff=xoffset,
                           yoff=yoffset))

        return '%s%s.tif' % (self.output, province_name)
Example #37
0
def ObtainPixelsfromShape(field, rasterPath, shapePath, INX, *args):

    # field='zona'
    # open dataset, also load as a gdal image to get geotransform
    # INX can be false. If True, uses additional layers.
    print "Starting clip...."
    start = time.time()

    if args:
        texture_train_Path = args[0]
        print texture_train_Path
        img, textArrayShp = createTextureArray(texture_train_Path, rasterPath)

    else:
        #print"Indexes = False"
        img = gdal.Open(rasterPath)

    geoTrans = img.GetGeoTransform()
    geoTransaux = img.GetGeoTransform()
    proj = img.GetProjection()
    # imgarrayaux = img.ReadAsArray().shape
    # print "img.ReadAsArray().shape", img.ReadAsArray().shape

    #open shapefile
    driver = ogr.GetDriverByName("ESRI Shapefile")
    dataSource = driver.Open(shapePath, 0)
    layer = dataSource.GetLayer()
    clipdic = defaultdict(list)
    count = 0

    #Convert the layer extent to image pixel coordinates, we read only de pixels needed
    for feature in layer:
        minX, maxX, minY, maxY = feature.GetGeometryRef().GetEnvelope()
        geoTrans = img.GetGeoTransform()

        ulX, ulY = world2Pixel(geoTrans, minX, maxY)
        lrX, lrY = world2Pixel(geoTrans, maxX, minY)
        #print ulX,lrX,ulY,lrY

        # Calculate the pixel size of the new image
        pxWidth = int(lrX - ulX)
        pxHeight = int(lrY - ulY)

        clip = ReadClipArray(lrY, ulY, lrX, ulX, img)

        #EDIT: create pixel offset to pass to new image Projection info
        xoffset = ulX
        yoffset = ulY
        #print "Xoffset, Yoffset = ( %d, %d )" % ( xoffset, yoffset )

        # Create a new geomatrix for the image
        geoTrans = list(geoTrans)
        geoTrans[0] = minX
        geoTrans[3] = maxY

        # Map points to pixels for drawing the boundary on a blank 8-bit, black and white, mask image.
        points = []
        pixels = []
        geom = feature.GetGeometryRef()
        pts = geom.GetGeometryRef(0)

        [
            points.append((pts.GetX(p), pts.GetY(p)))
            for p in range(pts.GetPointCount())
        ]

        [pixels.append(world2Pixel(geoTrans, p[0], p[1])) for p in points]

        rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
        rasterize = ImageDraw.Draw(rasterPoly)
        rasterize.polygon(pixels, 0)
        mask = imageToArray(rasterPoly)

        #SHow the clips of the features
        # plt.imshow(mask)
        # plt.show()

        # Clip the image using the mask into a dict
        temp = gdalnumeric.choose(mask, (clip, np.nan))

        # #SHow the clips of the image
        # plt.imshow(temp[4])
        # plt.show()
        temp = np.concatenate(temp.T)
        temp = temp[~np.isnan(temp[:, 0])]  #NaN
        #print temp.shape

        clipdic[str(feature.GetField(field))].append(temp)
        count += temp.shape[0]
    end = time.time()
    print "Time clipshape:"
    print(end - start)
    print "count", count
    return clipdic, count
Example #38
0
def clip_raster(rast_path, features_path, gt=None, nodata=-9999):
    def array_to_image(a):
        '''
        Converts a gdalnumeric array to a Python Imaging Library (PIL) Image.
        '''
        i = Image.fromstring('L', (a.shape[1], a.shape[0]),
                             (a.astype('b')).tostring())
        return i

    def image_to_array(i):
        '''
        Converts a Python Imaging Library (PIL) array to a gdalnumeric image.
        '''
        a = gdalnumeric.fromstring(i.tobytes(), 'b')
        a.shape = i.im.size[1], i.im.size[0]
        return a

    def world_to_pixel(geo_matrix, x, y):
        '''
        Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
        the pixel location of a geospatial coordinate; from:
        http://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html#clip-a-geotiff-with-shapefile
        '''
        ulX = geo_matrix[0]
        ulY = geo_matrix[3]
        xDist = geo_matrix[1]
        yDist = geo_matrix[5]
        rtnX = geo_matrix[2]
        rtnY = geo_matrix[4]
        if xDist < 0:
            xDist = -xDist
        if yDist < 0:
            yDist = -yDist
        pixel = int((x - ulX) / xDist)
        # This one probably a bug
        # In the geo_matrix the yDist appears to be negative
        # which doesn't make any f*****g sense
        line = int((ulY - y) / yDist)
        return (pixel, line)

    # Since in the file what we have  is just a path instead of the file
    rast = gdal.Open(rast_path)
    # Can accept either a gdal.Dataset or numpy.array instance
    if not isinstance(rast, np.ndarray):
        gt = rast.GetGeoTransform()
        rast = rast.ReadAsArray()

    # Create an OGR layer from a boundary shapefile

    '''
    Does that mean all I need to do is just get the driver?
    '''
    # TODO: Update the gdal version
    #features = ogr.Open(open(features_path).read())
    features = ogr.Open(features_path)
    if features.GetDriver().GetName() == 'ESRI Shapefile':
        lyr = features.GetLayer(os.path.split(
                                os.path.splitext(features_path)[0])[1])
    else:
        lyr = features.GetLayer()

    # Get the first feature
    poly = lyr.GetNextFeature()

    # Convert the layer extent to image pixel coordinates
    minX, maxX, minY, maxY = lyr.GetExtent()
    ulX, ulY = world_to_pixel(gt, minX, maxY)
    lrX, lrY = world_to_pixel(gt, maxX, minY)

    # print minX, maxX, minY, maxY
    # print ulX, ulY, lrX, lrY
    # Calculate the pixel size of the new image
    pxWidth = int(lrX - ulX)
    '''
    Wow, does this man really run his codes?
    '''
    pxHeight = int(lrY - ulY)

    # print "Debug messages"
    # print pxWidth
    # print pxHeight

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    if gt[3] < maxY:
        # In such a case... ulY ends up being negative--can't have that!
        iY = ulY
        ulY = 0

    # Multi-band image?
    try:
        clip = rast[:, ulY:lrY, ulX:lrX]

    except IndexError:
        clip = rast[ulY:lrY, ulX:lrX]

    # Create a new geomatrix for the image
    gt2 = list(gt)
    gt2[0] = minX
    gt2[3] = maxY

    # Map points to pixels for drawing the boundary on a blank 8-bit,
    #   black and white, mask image.
    points = []
    pixels = []
    geom = poly.GetGeometryRef()
    pts = geom.GetGeometryRef(0)

    for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))

    for p in points:
        pixels.append(world_to_pixel(gt2, p[0], p[1]))

    raster_poly = Image.new('L', (pxWidth, pxHeight), 1)
    rasterize = ImageDraw.Draw(raster_poly)
    rasterize.polygon(pixels, 0)  # Fill with zeroes

    # If the clipping features extend out-of-bounds and ABOVE the raster...
    if gt[3] < maxY:
        # The clip features were "pushed down" to match the bounds of the
        #   raster; this step "pulls" them back up
        premask = image_to_array(raster_poly)
        # We slice out the piece of our clip features that are "off the map"
        mask = np.ndarray((premask.shape[-2] - abs(iY),
                           premask.shape[-1]), premask.dtype)
        mask[:] = premask[abs(iY):, :]
        mask.resize(premask.shape)  # Then fill in from the bottom

        # Most importantly, push the clipped piece down
        gt2[3] = maxY - (maxY - gt[3])

    else:
        mask = image_to_array(raster_poly)

    # Clip the image using the mask
    try:
        # No data is used in here to fill the unbounded areas
        clip = gdalnumeric.choose(mask, (clip, nodata))

    # If the clipping features extend out-of-bounds and BELOW the raster...
    except ValueError:
        # We have to cut the clipping features to the raster!
        rshp = list(mask.shape)
        if mask.shape[-2] != clip.shape[-2]:
            rshp[0] = clip.shape[-2]

        if mask.shape[-1] != clip.shape[-1]:
            rshp[1] = clip.shape[-1]

        mask.resize(*rshp, refcheck=False)

        clip = gdalnumeric.choose(mask, (clip, nodata))

    # return (clip, ulX, ulY, gt2)
    # print clip
    # print gt2
    return clip
Example #39
0
  def apply(self, arg):
    
    # iterate over our input raster dataset, masking each file.
    for raster in self.inputDataset.inputFileArray:

      rasterInput = rasterRaw_input(raster)
      
      # Append a new clip file path for our current raster
      self.outputDataset.append(raster[:raster.rfind(".")]+"clipped"+raster[raster.rfind("."):])

      # Also load as a gdal image to get geotransform 
      # (world file) info

      geoTrans = srcImage.GetGeoTransform()

      # Create an OGR layer from a boundary shapefile
      shapef = ogr.Open("%s.shp" % shp)
      lyr = shapef.GetLayer(shp)
      poly = lyr.GetNextFeature()

      # Convert the layer extent to image pixel coordinates
      minX, maxX, minY, maxY = lyr.GetExtent()
      ulX, ulY = world2Pixel(geoTrans, minX, maxY)
      lrX, lrY = world2Pixel(geoTrans, maxX, minY)

      # Calculate the pixel size of the new image
      pxWidth = int(lrX - ulX)
      pxHeight = int(lrY - ulY)

      clip = srcArray[:, ulY:lrY, ulX:lrX]

      # Create a new geomatrix for the image
      geoTrans = list(geoTrans)
      geoTrans[0] = minX
      geoTrans[3] = maxY

      # Map points to pixels for drawing the 
      # boundary on a blank 8-bit, 
      # black and white, mask image.
      
      points = []
      pixels = []
      geom = poly.GetGeometryRef()
      pts = geom.GetGeometryRef(0)
      for p in range(pts.GetPointCount()):
        points.append((pts.GetX(p), pts.GetY(p)))
      for p in points:
        pixels.append(world2Pixel(geoTrans, p[0], p[1]))
      rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
      rasterize = ImageDraw.Draw(rasterPoly)
      rasterize.polygon(pixels, 0)
      mask = imageToArray(rasterPoly)   

      # Clip the image using the mask
      clip = gdalnumeric.choose(mask, \
          (clip, 0)).astype(gdalnumeric.uint8)

      # This image has 3 bands so we stretch each one to make them
      # visually brighter
      for i in range(3):
        clip[i,:,:] = stretch(clip[i,:,:])

      # Save ndvi as tiff
      gdalnumeric.SaveArray(clip, "%s.tif" % output, \
          format="GTiff", prototype=raster)

      # Save ndvi as an 8-bit jpeg for an easy, quick preview
      clip = clip.astype(gdalnumeric.uint8)
      gdalnumeric.SaveArray(clip, "%s.jpg" % output, format="JPEG")