基于GDAL的栅格图像空间插值预处理

本文介绍如何使用GDAL库进行栅格图像的空间插值预处理,包括读取DEM和坡向数据、处理站点信息,并通过加权回归分析计算温度递减率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自 基于GDAL的栅格图像空间插值预处理——C语言版

 

基于GDAL的栅格图像预处理

前言

        栅格数据和矢量数据构成空间数据的主要来源,怎样以开源方式读取并处理这些空间数据?目前有多种开源支持包,这里只介绍GDAL包。GDAL包的优点是支持库简洁、支持栅格和矢量、与多种开发平台结合。OpenGis方式读取空间数据,有利于自己编写程序进行图像预处理和智能识别等等,比如:遥感影像的降噪、锐化;红外图像的林火识别;工厂监控视频识别等等。本文中利用GDAL包读取高程栅格DEM,并添加气象自动站点的数据,进行空间插值研究。

 

一、程序主要程序功能实现过程

第一步:读取栅格数据,包含坡向和DEM

第二步:读入站点信息数据

第三步:按照行列号读取栅格单元到内存,不考虑高程为0的单元

第三步:每一个坡向情况中,参考固定数目的气象站点。首先确定搜索范围,获取定量数目的监测站点。

第四步:在同一个计算窗口内,通过给各个因子赋权重,依据海拔高程回归关系与加权回归分析得到

温度递减率。

第五步:计算单个站点的温度预测值,然后计算所有站点的距离权重因子,根据因子大小确定综合

影响后的温度值

第四步:开辟新内存存储处理后的栅格数据,然后新建一个tiff格式的文件,把内存

数据导出到该文件中

 二、代码示例

    int _tmain(int argc, _TCHAR* argv[])    
    {  
        /* 
        DEM、坡向栅格数据的数据框大小 
        */  
        int XsizeDEM;  
        int YsizeDEM;  
        int XsizeAspect;  
        int YsizeAspect;  
        //double geoTransform[6];  
        //double Xp,Yp;  
      
      
        /* 
        DEM、坡向栅格单元对象的VALUE值 
        */  
        short int *pmemDEM;  
        float *pmemAspect;  
        float *pmemNew;  
      
        //GDAL注册  
        GDALAllRegister();  
      
        /* 
        栅格单元的底图来源文件名:DEM/ASPECT 
        */  
        const char *pszFileDEM;  
        pszFileDEM="F:\\beijing_dem\\bj25_CopyRaster11.img";  
        const char *pszFileAspect;  
        pszFileAspect="F:\\beijing_dem\\aspect_bj.tif";  
      
        /*读取站点信息*/  
        int n,m;  
        float site[32][6];  
      
        FILE *fp;  
        if((fp=fopen("F:\\beijing_dem\\site_36\\information.txt","r"))== NULL)  
        {  
            printf("cannot open this file\n");  
            exit(0);  
        }  
        for(n=0;n<32;n++) {  
            for(m=0;m<6;m++) {  
                fscanf(fp,"%f",&site[n][m]);  
            }  
        }  
      
      
        for(n=0;n<32;n++) {  
            for(m=0;m<6;m++) {  
                printf("%f",site[n][m]);/*注意这里*/;  
                printf("  ");  
            }  
            printf("\n");    //每输出一行,输出一个换行符  
        }  
        fclose(fp);  
      
      
      
        /* 
        DEM/ASPECT的数据集读取器 
        */  
      
        GDALDataset *poDatasetDEM;  
        GDALRasterBand *poBandDEM;  
        GDALDataset *poDatasetAspect;  
        GDALRasterBand *poBandAspect;  
      
      
        /* 
        判断DEM/ASPECT文件是否存在,不存在错误提示 
        */  
        poDatasetDEM=(GDALDataset*)GDALOpen(pszFileDEM,GA_ReadOnly);  
        if(poDatasetDEM==NULL)  
        {  
            printf("File: %s不能打开",pszFileDEM);  
            return 0;  
        }  
      
        poDatasetAspect=(GDALDataset*)GDALOpen(pszFileAspect,GA_ReadOnly);  
        if(poDatasetAspect==NULL)  
        {  
      
            printf("File: %s不能打开",pszFileAspect);  
            return 0;  
        }  
      
        /* 
        判断DEM/ASPECT文件如果存在,就把文件输入到波段第一层 
        */  
        poBandDEM=poDatasetDEM->GetRasterBand(1);  
        poBandAspect=poDatasetAspect->GetRasterBand(1);  
      
        /* 
        被处理栅格单元对象的数据框大小的提取 
        */  
        XsizeDEM=poBandDEM->GetXSize();  
        YsizeDEM=poBandDEM->GetYSize();  
        XsizeAspect=poBandAspect->GetXSize();  
        YsizeAspect=poBandAspect->GetYSize();  
      
        /* 
        被处理栅格单元对象的内存开辟 
        */  
        pmemDEM=(short int *)CPLMalloc(sizeof(short int)*XsizeDEM*YsizeDEM);  
        poBandDEM->RasterIO(GF_Read,0,0,XsizeDEM,YsizeDEM,pmemDEM,XsizeDEM,YsizeDEM,GDT_Int16,0,0);  
      
        pmemAspect=(float*)CPLMalloc(sizeof(float)*XsizeAspect*YsizeAspect);  
        poBandAspect->RasterIO(GF_Read,0,0,XsizeAspect,YsizeAspect,pmemAspect,XsizeAspect,YsizeAspect,GDT_Float32,0,0);  
      
      
        /* 
        被处理栅格单元对象的类型提示 
        */  
        printf("Type is: %s\n",GDALGetDataTypeName(poBandDEM->GetRasterDataType()));  
      
        //开辟新栅格内存空间  
        pmemNew=(float *)CPLMalloc(sizeof(float)*XsizeDEM*YsizeDEM);  
      
          
        for(int i=0;i<YsizeDEM;i++)  
        {  
            for(int j=0;j<XsizeDEM;j++)  
            {  
                int flag=0;  
                float H_value;  
                float A_value;  
                H_value=pmemDEM[i*XsizeDEM+j];  
                A_value=pmemAspect[i*XsizeDEM+j];  
      
                //单个栅格插值处理  
                //高程没有值的特殊情况  
                if(H_value==0)  
                {  
                    pmemNew[i*XsizeDEM+j]=0;  
                }  
      
                else  
                {  
                    //平地无坡向的情况  
                    if(A_value==-1)  
                    {  
                        //处理站点和插值单元重合的情况,插值单元的值等于站点监测值  
                        for(n=0;n<32;n++)   
                        {  
                            if(((site[n][4]-i)*(site[n][4]-i)+(site[n][5]-j)*(site[n][5]-j))==0)  
                            {  
                                float x1=site[n][0],x2=site[n][3];  
                                pmemNew[i*XsizeDEM+j]=site[n][3];  
                                printf("%f   平地站点数据: ",x1);  
                                printf("%f\n",x2);  
                                flag=1;  
                            }  
                        }  
      
                        if(flag==0)  
                        {  
                        pmemNew[i*XsizeDEM+j]=plain_calculate(site,H_value,i,j);  
                        //pmemNew[i*XsizeDEM+j]=3;  
                        }  
                    }   
      
                    else   
                    {  
                        //处理站点和插值单元重合的情况,插值单元的值等于站点监测值  
                        for(n=0;n<32;n++)   
                        {  
                            if(((site[n][4]-i)*(site[n][4]-i)+(site[n][5]-j)*(site[n][5]-j))==0)  
                            {  
                                float x1=site[n][0],x2=site[n][3];  
                                pmemNew[i*XsizeDEM+j]=site[n][3];  
                                printf("%f   非平地站点数据: ",x1);  
                                printf("%f\n",x2);  
                                flag=1;  
                            }  
                        }  
      
                        if(flag==0)  
                        {  
                            //每一个栅格单元进行插值计算  
                            pmemNew[i*XsizeDEM+j]=calculate(site,H_value,A_value,i,j);  
                            //pmemNew[i*XsizeDEM+j]=1;  
                        }  
                    }  
                }  
                //poDatasetDEM->GetGeoTransform( geoTransform);  
                //Xp = geoTransform[0] +j*geoTransform[1]+i*geoTransform[2];  
                //Yp = geoTransform[3] + j*geoTransform[4] + i*geoTransform[5];  
      
      
            }  
        }  
      
        /** 
        创建新的空TIFF栅格文件 
        */  
        GDALAllRegister();  
        GDALDriver *poDriver;  
        poDriver=GetGDALDriverManager()->GetDriverByName("GTiff");//AAIGrid(Arc/Info ASCII Grid)         HFA (img no lim)  
        if(poDriver==NULL)  
            exit(1);  
        GDALDataset *poDstDS;  
        poDstDS=poDriver->Create("F:\\beijing_dem\\beijing_mix513.tiff",XsizeDEM,YsizeDEM,1,GDT_Float32,NULL);  
      
        double trans[6]={219323.300357,100.00,0.00,4680250.0000,0.0,-100.000};  
        //如果图像不含地理坐标信息,默认返回值是:(0,1,0,0,0,1)  
        //In a north up image,  
        //左上角点坐标(padfGeoTransform[0],padfGeoTransform[3]);  
        //padfGeoTransform[1]是像元宽度(影像在宽度上的分辨率);  
        //padfGeoTransform[5]是像元高度(影像在高度上的分辨率);  
        //如果影像是指北的,padfGeoTransform[2]和padfGeoTransform[4]这两个参数的值为0。  
      
        poDstDS->SetGeoTransform(trans);  
        GDALClose((GDALDatasetH)poDstDS);  
      
      
        /* 
        //处理后的数据层保存 
        */  
        GDALDataset *poDatasetNew;  
        poDatasetNew=(GDALDataset*)GDALOpen("F:\\beijing_dem\\beijing_mix513.tiff",GA_Update);  
        GDALRasterBand *poBandNew;  
        poBandNew=poDatasetNew->GetRasterBand(1);  
        poBandNew->RasterIO(GF_Write,0,0,XsizeDEM,YsizeDEM,pmemNew,XsizeDEM,YsizeDEM,GDT_Float32,0,0);  
        GDALClose((GDALDatasetH)poDatasetNew);  
      
      
      
      
        //释放数据  
        CPLFree(pmemDEM);  
        CPLFree(pmemNew);  
        printf("处理结束\n");  
      
      
      
      
    }  

 

 三、插值结果

 

 

 

<think>好的,我需要帮助用户解决图像预处理中去除黑边并调整到统一尺寸的问题。首先,用户提到了参考站内的三个引用,其中涉及Copy Raster工具、setnull工具以及旋转导致黑边的情况。我需要结合这些引用内容,提供有效的方法和工具。 首先,去除黑边的常见方法有哪些?根据引用[1],Copy Raster工具可以处理多波段和单波段数据,去除黑边。这可能涉及到裁剪或替换无效值。引用[2]提到setnull工具,可以将黑边像素设置为无效,再替换为透明或其他值。引用[3]指出旋转导致的黑边,可能需要填充有效区域或扩展画布。 接下来调整尺寸,常用的工具有Pillow、OpenCV等库,或者使用ImageMagick命令行工具。需要确保调整时保持宽高比,避免变形,可能还需要填充或裁剪。 然后需要分步骤解释方法,比如先去除黑边再调整尺寸,或同时处理。可能需要具体说明每个工具的使用步骤,例如GDALgdal_translate命令,或者Python代码示例。同时要注意引用中的内容,比如Copy Raster和setnull的具体应用,以及如何处理旋转后的黑边。 用户可能需要具体代码示例,比如使用Python的Pillow库裁剪黑边并调整尺寸。另外,引用[2]提到setnull工具需要后续处理,比如转为透明,可能需要结合其他步骤。 最后,生成相关问题,可能涉及不同工具的对比、自动化处理、保持宽高比的方法,以及处理不同格式图像的注意事项等。</think>### 图像预处理中去除黑边并调整尺寸的方法 #### 一、去除黑边的核心方法 1. **基于无效值替换** - **GDAL工具链**:使用`gdal_translate`命令裁剪黑边区域,或通过`Copy Raster`工具将黑边(如0值)替换为透明通道。例如: ```bash gdal_translate -a_nodata 0 input.tif output.tif # 将0值标记为无效区域[^1] ``` - **SetNull工具**:在ArcGIS或QGIS中,使用栅格计算将黑边像素设为无效值,再转换为透明背景[^2]。 2. **基于图像裁剪** - **OpenCV/Pillow裁剪**:通过检测非黑边区域的边界框(如像素值>0的极值点),直接裁剪有效区域。例如Python代码: ```python from PIL import Image import numpy as np img = np.array(Image.open("input.jpg")) mask = img.sum(axis=2) > 0 # 检测非全黑区域 coords = np.where(mask) xmin, xmax = coords[1].min(), coords[1].max() cropped = img[:, xmin:xmax] # 裁剪横向黑边 ``` 3. **旋转黑边处理** 旋转时扩展区域默认填充0值,可通过以下方式避免: - **扩展画布**:使用`ImageMagick`的`-extent`参数填充背景色(如白色): ```bash convert input.jpg -background white -rotate 30 -extent 100%x100% output.jpg[^3] ``` #### 二、调整至固定尺寸的常用工具 1. **Python库** - **Pillow**:通过`resize()`调整尺寸,结合`thumbnail()`保持宽高比。 ```python from PIL import Image img = Image.open("input.jpg") img.thumbnail((256, 256)) # 保持比例缩放到最大边256 new_img = Image.new("RGB", (256, 256), (255,255,255)) # 创建白色背景 new_img.paste(img, ((256-img.width)//2, (256-img.height)//2)) # 居中填充 ``` - **OpenCV**:使用`cv2.resize()`,需注意插值算法选择(如`cv2.INTER_AREA`缩小图像)。 2. **命令行工具** - **ImageMagick**:通过`-resize`和`-gravity`参数实现填充式缩放: ```bash convert input.jpg -resize 256x256^ -gravity center -extent 256x256 output.jpg ``` #### 三、推荐流程 1. **先去除黑边** → **再调整尺寸**,避免无效区域干扰缩放计算。 2. **自动化脚本**:结合OpenCV/Pillow编写批处理脚本,统一处理多文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值