一、需要引用的库
下载链接:
链接:https://pan.baidu.com/s/1j-z0raXz5Af615js0U-MTQ?pwd=irxn 提取码:irxn
二、具体思路
本思路仅提供各位打开思维,并非最优解。
图一如下,显示了数据源shp的字段有多个:
using OpenCvSharp;
using OSGeo.OGR;
using OSGeo.OSR;
using OSGeo.GDAL;
private void button6_Click(object sender, EventArgs e)
{
ColormapTypes color;
string sColor = "Jet";//默认选择Jet色带
switch (sColor)
{
case "Autumn":
color = ColormapTypes.Autumn;
break;
case "Bone":
color = ColormapTypes.Bone;
break;
case "Jet":
color = ColormapTypes.Jet;
break;
case "Winter":
color = ColormapTypes.Winter;
break;
case "Rainbow":
color = ColormapTypes.Rainbow;
break;
case "Ocean":
color = ColormapTypes.Ocean;
break;
case "Summer":
color = ColormapTypes.Summer;
break;
case "Spring":
color = ColormapTypes.Spring;
break;
case "Cool":
color = ColormapTypes.Cool;
break;
case "Hsv":
color = ColormapTypes.Hsv;
break;
case "Pink":
color = ColormapTypes.Pink;
break;
case "Hot":
color = ColormapTypes.Hot;
break;
case "Parula":
color = ColormapTypes.Parula;
break;
case "Magma":
color = ColormapTypes.Magma;
break;
case "Inferno":
color = ColormapTypes.Inferno;
break;
case "Plasma":
color = ColormapTypes.Plasma;
break;
case "Viridis":
color = ColormapTypes.Viridis;
break;
case "Cividis":
color = ColormapTypes.Cividis;
break;
case "Twilight":
color = ColormapTypes.Twilight;
break;
case "TwilightShifted":
color = ColormapTypes.TwilightShifted;
break;
default:
color = ColormapTypes.Jet;
break;
}
string sOut = "D:\\PS\\cfgs.shp";//输入文件 这个shp 有6个字段可以筛选 详见图1
string sIn3 = "D:\\PS\\1_Result.tif";//基准tif 主要是为了shp提供图幅长宽和投影坐标系 可不提供,不提供的方法见ShpToTiff函数中的注释
string[] sTitle = null;
//这一步主要为了在同级目录下生成彩色色带
string sFileDir = sOut.Substring(0, sOut.LastIndexOf("\\"));//文件所在文件夹
string sFileName = sOut.Substring(sOut.LastIndexOf("\\") + 1, sOut.LastIndexOf(".") - sOut.LastIndexOf("\\") - 1);//源文件名称
string sFileSuffix = sOut.Substring(sOut.LastIndexOf("."));//文件后缀名 .shp
int nRtn = 6;//可以手动指定 也可以用gdal读取 读取方法暂不更新,不会的可以私聊询问
for (int i = 0; i < nRtn; i++)
{
//按顺序读取
string path1 = sFileDir + "\\" + sFileName + "_" + i.ToString() + ".tif";
ShpToTiff(sOut, sIn3, path1, sTitle[i]);//将当前数值输出为tif
string sOutColor = sFileDir + "\\" + sFileName + "_" + i.ToString() + "_Result_Color.tif";//保存位置
getColorMapFile(path1, color, sOutColor);//色带生成 JET
}
return;
}
private void ShpToTiff(string strInFile, string strInFile2, string strOutFile, string sTitle)
{
int m_nImageWidth = 1440;//默认值
int m_nImageHeight = 720;//默认值
Osr.SetPROJSearchPath(Environment.GetEnvironmentVariable("PROJ_LIB"));
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
OSGeo.GDAL.Gdal.AllRegister();
Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); //支持中文路径
OSGeo.OGR.Ogr.RegisterAll();
OSGeo.OGR.DataSource shpData = OSGeo.OGR.Ogr.Open(strInFile, 1);//0表示只读,1表示可修改
if (shpData == null)
{
return;
}
OSGeo.OGR.Layer shpLayer = shpData.GetLayerByIndex(0);
if (shpLayer == null)
{
return;
}
Envelope env = new Envelope();
shpLayer.GetExtent(env,1);//获取图层的坐标范围到env指向的内存中
SpatialReference pOgrSRS = shpLayer.GetSpatialRef();
string pPrj = "";
string[] sTemps = null;
if (pOgrSRS != null)
{
pOgrSRS.ExportToWkt(out pPrj, sTemps);
}
OSGeo.GDAL.Driver poDriver = OSGeo.GDAL.Gdal.GetDriverByName("GTIFF");
if (poDriver == null)
{
return;//驱动不可用
}
Dataset InputTif1 = Gdal.Open(strInFile2, Access.GA_ReadOnly);
OSGeo.GDAL.DataType datatype = InputTif1.GetRasterBand(1).DataType;
//获取列数 按照参考tiff读取
int cols = InputTif1.GetRasterBand(1).XSize;
//获取行数 按照参考tiff读取
int rows = InputTif1.GetRasterBand(1).YSize;
m_nImageWidth = cols;
m_nImageHeight = rows;
Dataset poNewDS = poDriver.Create(strOutFile, m_nImageWidth, m_nImageHeight, 1, DataType.GDT_Float32, null);
poNewDS.GetRasterBand(1).SetNoDataValue(255);//设置nodata值为255
double[] adfGeoTransform = new double[6];
adfGeoTransform[0] = env.MinX;//左上角经度
adfGeoTransform[1] = (env.MaxX - env.MinX) / m_nImageWidth;//像元宽度(影像在宽度上的分辨率)
adfGeoTransform[2] = 0; //如果影像是指北的, 这个参数的值为0
adfGeoTransform[3] = env.MaxY;//左上角纬度
adfGeoTransform[4] = 0; //如果影像是指北的, 这个参数的值为0。
adfGeoTransform[5] = (env.MinY - env.MaxY) / m_nImageHeight; //像元高度(影像在高度上的分辨率)
poNewDS.SetGeoTransform(adfGeoTransform);
if (pOgrSRS != null)
{
poNewDS.SetProjection(pPrj);
}
int[] pnbandlist = new int[1];
pnbandlist[0] = 1;
//OSGeo.OGR.Layer[] player = new OSGeo.OGR.Layer[1];
//player[0] = shpLayer;
string[] papszOptions;
papszOptions = new string[] { "ATTRIBUTE=" + sTitle };
//Gdal.RasterizeLayer(outputDataset, 1, bandlist, layer, IntPtr.Zero, IntPtr.Zero, 1, burnValues, rasterizeOptions, null, null);
OSGeo.GDAL.Gdal.RasterizeLayer(poNewDS, 1, pnbandlist, shpLayer, IntPtr.Zero, IntPtr.Zero, 0, null, papszOptions, null, null);
shpData.Dispose();
InputTif1.Dispose();
poNewDS.Dispose();
shpData.Dispose();
shpData.Dispose();
return;
}
public void getColorMapFile(string infile, ColormapTypes colormap, string outfile = "")
{
//本案例的输入是浮点型 因此是MatType.CV_32FC1
//色带映射
Mat im_gray = Cv2.ImRead(infile, ImreadModes.Unchanged);
Mat im_mask = new Mat();
im_mask = new Mat(im_gray.Size(), MatType.CV_8UC1);
for (int i = 0; i < im_gray.Size().Height; i++)//制作掩码数组
{
for (int j = 0; j < im_gray.Size().Width; j++)
{
float dTemp = im_gray.At<float>(i, j);
if (dTemp == 255.0)//上一步的nodata 255 的值设置0
{
im_mask.Set<int>(i, j, 0);
}
else
{
im_mask.Set<int>(i, j, 1);//有效值设置1
}
}
}
//int[] a = new int[1] { 2 };
//int[] b = new int[1] { 660 };
Mat im_color = new Mat(im_gray.Size(), MatType.CV_8UC3); //3通道 RGB 这里我生成的文件时8位的 各位可以根据需求改为16位等等
//TODO:判断输入是否是八位
Mat im_gray_clip = new Mat();
if (im_gray.Type() == MatType.CV_32FC1)//浮点型,如地热反演的情况
{
double min, max;
Cv2.MinMaxIdx(im_gray, out min, out max,a,b,im_mask);//掩码处理 不将没有数值的内容进行色带变色
double alpha = (byte.MaxValue-1) / (max - min);
double beta = -min * alpha;
//浮点转整型:线性拉伸
im_gray.ConvertTo(im_gray_clip, MatType.CV_8UC1, alpha, beta);
}
Cv2.ApplyColorMap(im_gray_clip, im_color, colormap);
for (int i = 0; i < im_gray_clip.Size().Height; i++)
{
for (int j = 0; j < im_gray_clip.Size().Width; j++)
{
int dTemp = im_gray_clip.At<Byte>(i, j);
if (dTemp == 255)//255 是nodata的值
{
Vec3b bgr = new Vec3b(0, 0, 0);//根据灰色值255 修改色带的nodata 显示效果 背景色为黑色
im_color.At<Vec3b>(i, j) = bgr;
}
else
{
int n = 000;
}
}
}
//
//
//string outfile1 = "D:\\PS\\1_Test2_1_Result_Color1.tif";
Cv2.ImWrite(outfile, im_color);
//Cv2.ImWrite(outfile1, im_gray_clip);
Osr.SetPROJSearchPath(Environment.GetEnvironmentVariable("PROJ_LIB"));
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
OSGeo.GDAL.Gdal.AllRegister();
Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); //支持中文路径
OSGeo.OGR.Ogr.RegisterAll();
OSGeo.GDAL.Driver oDriver = OSGeo.GDAL.Gdal.GetDriverByName("GTIFF");
//Dataset dataset = Gdal.Open(infile, Access.GA_ReadOnly);
//OSGeo.GDAL.DataType datatype = dataset.GetRasterBand(1).DataType;
获取波段数
//int rasterCount = dataset.RasterCount;
获取列数
//int cols = dataset.GetRasterBand(1).XSize;
获取行数
//int rows = dataset.GetRasterBand(1).YSize;
地理坐标系信息
//double[] adfGeoTransform = new double[6];
//dataset.GetGeoTransform(adfGeoTransform);
获取投影信息
//string pProjection = dataset.GetProjectionRef();
//GDAL读取输入影像投影信息
Osr.SetPROJSearchPath(Environment.GetEnvironmentVariable("PROJ_LIB"));
Dataset dsInput = Gdal.Open(infile, Access.GA_ReadOnly);
string inSpatialRef = dsInput.GetProjection();
double[] transform = new double[6];
dsInput.GetGeoTransform(transform);
//GDAL填写输出影像
Dataset dsOutput = Gdal.Open(outfile, Access.GA_Update);
dsOutput.SetGeoTransform(transform);
dsOutput.SetProjection(inSpatialRef);
//dsOutput.CreateMaskBand;
//dsOutput.GetRasterBand(1).SetNoDataValue(128);
//dsOutput.GetRasterBand(2).SetNoDataValue(0);
//dsOutput.GetRasterBand(3).SetNoDataValue(0);
dsOutput.FlushCache();
dsOutput.Dispose();
dsOutput = null;
return ;
}
三、解释下掩码的逻辑
在图像处理中,经常会碰到掩膜(Mask)这个词。那么这个词到底是什么意思呢?下面来简单解释一下。
1.什么是掩膜
首先我们从物理的角度来看看mask到底是什么过程。
在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),其作用是:在硅片上选定的区域中对一个不透明的图形模板遮盖,继而下面的腐蚀或扩散将只影响选定的区域以外的区域。
图像掩膜与其类似,用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。
2.掩膜的用法
2.1 提取感兴趣区:用预先制作的感兴趣区掩膜与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0;
2.2 屏蔽作用:用掩膜对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计;
2.3 结构特征提取:用相似性变量或图像匹配方法检测和提取图像中与掩膜相似的结构特征;
2.4 特殊形状图像的制作。
3.掩膜运算的一个小实例
以图和掩膜的与运算为例:
原图中的每个像素和掩膜中的每个对应像素进行与运算。比如1 & 1 = 1;1 & 0 = 0;
4.小结
用一句话总结,掩膜就是两幅图像之间进行的各种位运算操作。