opencv+GDAL 遥感影像滤波

参考:
1、https://docs.opencv.org/3.2.0/


1、python版

其中m1 参考:http://blog.csdn.net/wc781708249/article/details/78394933

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

"""
数据:遥感图像 16bit 4波段 
对应opencv数据格式为CV_16UC4,转成float32对应的数据格式为CV_32FC4

操作:滤波操作
"""

from scipy import ndimage
try:
    from osgeo import gdal
except:
    import gdal
import gdalnumeric
from osgeo.gdalconst import *
import numpy as np
from datetime import datetime
import m1
import cv2

start_time=datetime.now()
# 为了支持中文路径,请添加下面这句代码
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","NO")

gdal.AllRegister() #注册驱动

img1_path="D:/test.tiff"

img=m1.Multiband2Array(img1_path)

raster_fn="D:/test_2.tif"

# 各种滤波处理
dst=cv2.blur(img,(15,15)) # 均值滤波  可以处理CV_32FC4
dst=cv2.GaussianBlur(img,(5,5),0) # 高斯滤波 可以处理CV_32FC4
dst=cv2.medianBlur(img,5) # 中值滤波  可以处理CV_32FC4

# 双边过滤 只能处理CV_32FC3数据 只取前3个波段处理,处理CV_32FC4报错
dst=cv2.bilateralFilter(img[:,:,:-1],9,75,75)


src_ds = gdal.Open(img1_path,GA_ReadOnly)
geoTrans = src_ds.GetGeoTransform()
srcPro = src_ds.GetProjection()
src_ds=None

# 输出影像
target_ds = gdal.GetDriverByName('GTiff').Create(raster_fn, dst.shape[1], dst.shape[0], dst.shape[2], gdal.GDT_UInt16)
target_ds.SetGeoTransform(geoTrans)  # 设置掩膜的地理参考
target_ds.SetProjection(srcPro)  # 设置掩膜坐标引用
# target_ds.GetRasterBand(1).WriteRaster(0,0,img.shape[1],img.shape[0],img.tobytes())
[target_ds.GetRasterBand(i+1).WriteArray(dst[:,:,i],0,0) for i in range(dst.shape[2])]

target_ds.FlushCache()
target_ds=None

end_time=datetime.now()
print((end_time-start_time).total_seconds())

2、C++版

参考:http://blog.csdn.net/wc781708249/article/details/78479584

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include 
#include   
#include 
#include 
#include 

using namespace std;
using namespace cv;

//创建一个存放影像信息的structure
typedef struct
{
    //GDALDataset *poDataset = NULL;
    int Xsize = 0;
    int Ysize = 0;
    int nbands = 0;
    double *tmpadfGeoTransform = new double[6]; //存储地理6参数
    const char* proj = NULL;//存储投影
    GDALDataType iDataType = GDT_Byte;
}MyStruct;

cv::Mat GDAL2Mat(GDALDataset *poDataset, MyStruct &St);
bool Mat2File(cv::Mat img, MyStruct &St, GDALDataset *poDataset);

int main()
{
    //注册驱动  
    GDALAllRegister();

    string  src_path = "D:/test.tiff";
    string dst_path = "D:/test_2.tif";

    MyStruct St;
    GDALDataset *srcDataset = (GDALDataset *)GDALOpen(src_path.c_str(), GA_ReadOnly);

    St.Xsize = srcDataset->GetRasterXSize();
    St.Ysize = srcDataset->GetRasterYSize();
    St.nbands = srcDataset->GetRasterCount();
    srcDataset->GetGeoTransform(St.tmpadfGeoTransform);
    St.proj = srcDataset->GetProjectionRef();
    //获取数据类型
    St.iDataType = srcDataset->GetRasterBand(1)->GetRasterDataType();

    //影像转Mat
    Mat img = GDAL2Mat(srcDataset, St);

    //判断是否加载成功
    if (!img.data) //或者image.empty()
    {
        cout << src_path << "  cannot open!" << endl;
        return -1;
    }

    //
    /*各种滤波处理*/
    Mat dst;//输出Mat
    //如果将数据转成CV_32FC4,再滤波会出现问题(Python中却不会)
    blur(img, dst, Size(5, 5), Point(-1, -1)); //均匀滤波
    GaussianBlur(img, dst, Size(5, 5), 0, 0); //高斯滤波
    medianBlur(img, dst, 5);                  //中值滤波
    //bilateralFilter(img, dst, 3, 3 * 2, 3 / 2);//双边滤波 

    //注:输入数据的格式CV_16UC4
    //Bilateral filtering is only implemented for 8u and 32f images
    img.convertTo(dst, CV_32FC4); //转成32F类型
    bilateralFilter(dst, dst, 3, 3 * 2, 3 / 2);//双边滤波 
    //src.type() == CV_32FC1 || src.type() == CV_32FC3
    //可以取前3个波段使用双边滤波处理

    /

    //定义输出数据
    GDALDataset *dstDataset;   //GDAL数据集
    GDALDriver *poDriver;      //驱动,用于创建新的文件
    //poDriver = GetGDALDriverManager()->GetDriverByName("ENVI");
    poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");

    if (poDriver == NULL)
        return 0;
    dstDataset = poDriver->Create(dst_path.c_str(), St.Xsize, St.Ysize, St.nbands,
        St.iDataType, NULL);//GDT_Float32

    //重新设置地理参考和投影系
    dstDataset->SetGeoTransform(St.tmpadfGeoTransform);
    dstDataset->SetProjection(St.proj);

    GDALClose((GDALDatasetH)srcDataset);

    //保存Mat到影像
    Mat2File(dst, St, dstDataset);

    GDALClose((GDALDatasetH)dstDataset);


    return 0;
}

//GDAL数据转opencv的Mat格式 
cv::Mat GDAL2Mat(GDALDataset *poDataset, MyStruct &St)  //const QString fileName
{
    //获取数据类型
    //GDALDataType iDataType = poDataset->GetRasterBand(1)->GetRasterDataType();
    //int idepth = GDALGetDataTypeSize((GDALDataType)iDataType);

    //将GDAL的数据类型与Mat的数据类型对应起来
    auto MdataType = NULL;
    auto MdataTypes = NULL;

    if (St.iDataType == GDT_Byte)
    {
        MdataType = CV_MAKETYPE(CV_8U, 1);
        MdataTypes = CV_MAKETYPE(CV_8U, St.nbands);
    }
    if (St.iDataType == GDT_UInt16)
    {
        MdataType = CV_MAKETYPE(CV_16U, 1);
        MdataTypes = CV_MAKETYPE(CV_16U, St.nbands);
    }


    //QVector  imgMat;  
    vector imgMat;// 每个波段
    float *pafScan = new float[St.Xsize*St.Ysize];   // 存储数据

    for (int i = 0; i< St.nbands; i++)
    {
        GDALRasterBand *pBand = poDataset->GetRasterBand(i + 1);
        //pafScan = new float[tmpCols*tmpRows];
        pBand->RasterIO(GF_Read, 0, 0, St.Xsize, St.Ysize, pafScan,
            St.Xsize, St.Ysize, St.iDataType, 0, 0); //GDT_Float32
        cv::Mat tmpMat = cv::Mat(St.Ysize, St.Xsize, MdataType, pafScan);//CV_32FC1
        imgMat.push_back(tmpMat.clone());
    }
    delete[]pafScan;
    pafScan = NULL;

    cv::Mat img;
    img.create(St.Ysize, St.Xsize, MdataTypes);// CV_32FC(St.nbands)
    //cv::merge(imgMat.toStdVector(), img);
    cv::merge(imgMat, img);
    //释放内存
    imgMat.clear();
    //GDALClose((GDALDatasetH)poDataset);
    return img;
}

//Mat 数据保存成影像
bool Mat2File(cv::Mat img, MyStruct &St, GDALDataset *poDataset)//const QString fileName
{
    if (img.empty())    //    判断是否为空
        return 0;

    const int nBandCount = St.nbands;
    const int nImgSizeX = St.Xsize;
    const int nImgSizeY = St.Ysize;

    //    将通道分开
    //  imgMat每个通道数据连续
    std::vector imgMat(nBandCount);
    cv::split(img, imgMat);

    //  分波段写入文件
    GDALAllRegister();


    //  循环写入文件
    GDALRasterBand *pBand = NULL;
    float *ppafScan = new float[nImgSizeX*nImgSizeY];
    cv::Mat tmpMat;// = cv::Mat(nImgSizeY,nImgSizeX,CV_32FC1);

    for (int i = 1; i <= nBandCount; i++)
    {
        pBand = poDataset->GetRasterBand(i);
        tmpMat = imgMat.at(i - 1);
        if (tmpMat.isContinuous())
        {
            if (St.iDataType == GDT_Byte)
                memmove(ppafScan, (void*)tmpMat.ptr(0), sizeof(unsigned char)*nImgSizeX*nImgSizeY);//GDT_Byte
            if (St.iDataType == GDT_UInt16)
                memmove(ppafScan, (void*)tmpMat.ptr(0), sizeof(unsigned short)*nImgSizeX*nImgSizeY);//GDT_Uint16
                                                                                                    //memmove(ppafScan, (void*)tmpMat.ptr(0),sizeof(float)*nImgSizeX*nImgSizeY);//GDT_Float32
        }
        else
            return false;

        CPLErr err = pBand->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, ppafScan,
            nImgSizeX, nImgSizeY, St.iDataType, 0, 0);
    }
    delete[] ppafScan;
    ppafScan = NULL;
    imgMat.clear();
    //GDALClose(poDataset);
    return 1;
}

你可能感兴趣的:(opencv,gdal,opencv,gdal)