影像显示原理
显示遥感影像在业界做得比较牛逼的有ENVI,Erdas,以及ArcGIS软件。其实我并不想列举ArcGIS软件,但是ArcGIS毕竟是行业的大佬,所以。。
遥感影像一般小到几百兆大到几个G,像这个么大的数据ENVI以及Erdas等软件是如何将它们显示出来呢!其实我一开始也比较好奇,同时也比较纳闷。这么大的数据,加载进来,软件居然一点都不卡,响应效率非常高,他们是怎么做到的。
于是我去查看杜会建老师等团队写的idlviewer_useenvi源码,里面居然调用了IDL写好的接口,我表示很难受。居然他们把这条路堵死了,那只好我自己另寻它路。一开始我使用MFC来作为显示,GDAL读取影像,但这样的方式使得我花费了很长时间将读取出来的数据构建成图片,并将它在MFC的视图View中显示出来,于是我就寻思这样显示是不是有点问题,但是就感觉不到问题出现在哪里。知道后来我接触到了Qt,并使用了里面的QGraphicsView,才发现原来显示图像有这么好的“工具”,因为QGraphicsView自带缩放,而且平移事件只需要写一点点代码就可以完成,于是我将自己原来写的代码推翻,重新在Qt下面进行重构,最后发现原来显示图像可以这么简单。这时候,我感觉我将影像显示的部分做得很完美,因为我测试的时候仅仅使用的是ENVI里面的一个小数据进行测试,发现显示起来贼快,而且显示的效果和ENVI里面的效果一模一样,当时可把自己兴奋坏了。但是当我使用大影像去跑的时候,发现显示速度很慢,一个600M的资源卫星数据,显示出来居然要15秒,我顿时感觉自己的“成就”就是一坨屎。
为了解决这个问题,于是我去调试分析,结果才发现我是一次性将数据全部读到内存当中,然后再显示出来。现在想想,这样不卡我名字倒着写。既然发现了问题所在,我又找解决方法,找着找着,突然灵光一闪,能不能显示多大就读取多大的数据进行初始化显示,但是这样的话又会存在一个难题,也就是平移缩放等事件都要自己去处理,而不能使用QGraphicsView原来的方法。现在也就是方法已经找到了,但是实现起来可能会有点难度,但是为了将影像显示出来,再复杂也要把它干掉。
于是我将QGraphicsView的缩放以及平移事件都进行了重写,并利用高分数据进行测试,发现效果还可以哈!居然顺畅多了,无论是打开平移还是缩放的速度都很快,几乎感觉不到有什么卡顿的情况。但是当我加载多个数据之后(因为我想测试一下多个数据会不会有什么问题)问题又有了。那就是利用任务管理器查看程序占用的内存,发现每次打开一个数据,内存都会往上跳一个,按理来说,上升的内存不应该有这么大,于是我还是去找问题所在,找啊找,找啊找,可惜的是还是没有找到原因。
于是去找以前MFC编写的程序,两个进行了一个对比,诶,发现了问题,我用MFC写的程序,加载数据内存增加与Qt增加的内存明显少了很多,于是我自己new了一个QGraphicsItem出来,发现原来这个东西居然耗费的内存也不小。我也真是想骂人了。没办法了,只能使用最后一招了,读取显示都用自己来写了。不能用QGraphicsView显示图像,更不能用QGraphicsItem来作为影像显示的载体了。
只能直接在QWidget上面直接绘制影像,一开始在绘制的时候,没有考虑缩放和平移,做了一个简单的版本出来,发现效果还可以,在这个基础上,慢慢的加上了平移和缩放,但是在平移和缩放都是需要用代码来控制,这个就不容易了,一直思考这个怎么解决,但是一直都没有想到好的办法。后面我想了想,是不是自己的思路有问题,反过头来想,如果直接把设备坐标转为投影坐标,然后影像直接通过投影坐标进行显示,这样是不是就解决了,果不其然,还真是这样。将设备坐标转为投影坐标,再利用投影坐标的显示范围与图像的整个坐标范围进行求交,就可以得到影像的显示范围,在通过影像的显示范围坐标转为影像的行列号,将数据读取出来,进显示出来。
经过自己不断努力,最终写出了一个自己还比较满意的显示影像的软件。后期就会往里面添加各种功能。在此,展示一下显示的效果:
这个图是与envi软件打开数据之后的对比,缩放比例都是1:1,可以清楚的看到显示的效果几乎一样。
打开数据:
影像漫游:
影像拉伸显示:
影像保存:
软件更新:
2021年04月06号:
(1)、打开软件之后,原点默认在视口的中心;
(2)、优化坐标显示,原来是鼠标往上移动时,Y的值变小,现在改往下移动Y的值变小。这样更符合坐标系统。
(3)、优化影像打开时,默认以影像的中心与视图的中心重合;
(4)、添加软件设置,包含了
1、保存上一次打开的路径;
2、数据打开之后,数据管理窗口是否自动打开以及波段是否自动展开
3、加载数据之后,数据窗口是否自动关闭
2021年10月01号:
(1)、优化影像处理出现进度条崩溃bug;
(2)、优化打开含有中文字符的波段出现乱码;
(3)、优化显示的波段与图层列表中显示的不一致;
(4)、优化读取高分3号数据失败bug;
(5)、添加影像拉伸(百分比拉伸,直方图均衡化);
(6)、优化影像放大之后,出现影像不会布满全屏的白边;
(7)、将GDAL版本从233升级到了330版本(主要是想使用坐标投影)
备注:
此版本升级主要是优化显示,提高显示速度,并且优化构建金字塔。整体下来,显示3.3G的数据建金字塔花费了10秒不到的时间,显示更是1秒不到。而且还添加了影像拉伸等功能。
显示不到1秒的原因主要是因为以前使用的是GDAL的影像统计,现在改为自己编写的统计方法,包括平均值,标准差,最大值以及最小值等。
2021年10月02号:
(1)、添加软件地理坐标显示,以前都是以像素行列号进行显示的;
(2)、没有投影信息的影像,那么不会显示坐标信息;
备注:
2021年10月06号:
(1)、添加光谱曲线图,并且可以按照波段索引或者波长进行曲线图显示;
(2)、同时可以显示多个影像的曲线图;
(3)、在工具条中添加平移按钮(针对鼠标中键不好用的,比如我自己);
2021年10月18号:
(1)、添加绘制多边形感兴趣区;
(2)、添加绘制矩形感兴趣区;
(3)、优化没有坐标投影绘制感兴趣区出现漂移;
2021年10月26号:
(1)、优化没有显示的影像也会显示光谱曲线;
(2)、添加实时鼠标对应的像素值;
2021年10月31号:
(1)、优化切换ROI类型后,第一个绘制没有颜色;
(2)、添加保存ROI到txt文件;
(3)、添加读取ROI到图面;
(4)、实现目录树上移出数据功能;
2021年11月22号:
(1)、优化获取当前鼠标像素值(单波段会显示两个像素值);
(2)、优化获取当前显示的波段(单波段获取显示波段时,第三个波段的值为0)
(3)、优化ROI对话框确定和取消按钮无效
2021年12月24号:
(1)、优化软件界面;
2023年07月09号:
(1)、添加透明度显示
(2)、添加蜕化显示
(3)、添加默认不显示无效值
2023年12月22号:
(1)、移除自定义工具条,添加工具栏面板(更贴切ENVI界面)
(2)、优化影像放大时读取的内存大小;
void GisEntsHelper::CalculateRasterRange(GeoPoint2d &pos, UInt2 &read, UInt2 &size, UInt2 &buf, UInt2 &show, GisDatasetRaster *pRaster, double dScale, const GeoExtents &exts)
{
GeoMatrix3d trans; pRaster->getGeoTransform(trans);
GeoExtents showExt = exts ^ trans; //读取的像素范围
size.x = ceil(showExt.width() - GisPrecision::GisEps());
size.y = ceil(showExt.height() - GisPrecision::GisEps());
read.x = floor(showExt.minPoint().rx()), read.y = (showExt.minPoint().ry());
if(read.x + size.x < showExt.maxPoint().rx() - GisPrecision::GisEps()) size.x += 1;
if(read.y + size.y < showExt.maxPoint().ry() - GisPrecision::GisEps()) size.y += 1;
pos = GeoPoint2d(read.x, read.y) * trans;
double xScale = fabs(trans.value(0, 0)), yScale = fabs(trans.value(1, 1));
show.x = ceil(size.x * 1.0 / dScale * xScale);
show.y = ceil(size.y * 1.0 / dScale * xScale);
buf.x = dScale > 1.0 ? show.x : size.x;
buf.y = dScale > 1.0 ? show.y : size.y;
}
(3)、优化影像显示(改进拉伸),使得浏览速度更快;
影像现在拉伸方式为(时间为0.1秒):
GisEntsHelper::GisLineStretchImage(mats1, pImpObject->histArray, sType, 0);
现在改为(时间为:0.014秒):
GisEntsHelper::GisLineStretchImageEx(mats, pImpObject->histArray, sType, 0);
优化效率从0.1秒
(4)、影像拉伸、蜕化、透明度设置都是针对单个影像,从而可以控制每个显示的影像状态;
(5)、 重构底层代码;
2024年01月05号:
1、软件版本升级1.1
1、软件支持绘制功能区,目录树上控制是否显示。
2、优化影像处理接口(支持进度条显示任务名称)
3、进度条支持多重任务进行
4、支持执行任务时,界面还可以浏览数据
2、整理软件目录结构
2024年01月06号:
1、添加对数拉伸
2、添加均平方根拉伸
3、优化单波段也可以进行透明度显示
4、优化像素值显示
Video_2024-01-06_035302
5、优化忽略无效值显示效果(之前是将每个波段的无效值赋值为255,现在改为每个波段无效值的交集作赋值为255)
6、优化输出数据时带投影信息
Video_2024-01-06_040011
7、波段运算支持四则运算(加减乘除)
波段运算
下面列出软件的svn地址以及软件运行介绍:
软件地址(SVN):软件下载地址
SVN账号:temp
SVN密码:temp