Romi-知行合一

轻轻的风轻轻的梦,轻轻的晨晨昏昏, 淡淡的云淡淡的泪,淡淡的年年岁岁。
  博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

图像ROI显示

Posted on 2012-11-21 23:31  romi  阅读(5800)  评论(0编辑  收藏  举报

要实现图像的ROI显示,即选择图像中的某一区域,显示该区域的原图像。其核心的问题归纳有如下三个:

①.得到缩略图像

②.实现鼠标事件,获取鼠标的坐标

③.将坐标转换为原图像中的坐标,从而就找到了需要的原图像数据区,将它读出来

1,缩略图

显示出原图缩略图的关键是找到缩小倍数,缩小倍数根据显示控件和原图像的大小决定。假设显示区的宽和高相同

原则:原图像宽>高时,缩略图的宽为显示区的宽,缩略图的高通过计算得出(小于显示区的宽);反之,源图像宽<高时,则缩略图的高为显示区的高,缩略图的宽通过计算得出(小于显示区的宽)

通过缩略图的大小就可以得出缩小倍数

然后通过缩小倍数读出缩略图所需数据,以下是RasterIO接口详解

原图像大小:sizeX*sizeY      缩略图大小:width*height    缩小倍数zoom

1 unsigned char *data=new unsigned char[width*height];
2 poBand->RasterIO(GF_Read,
3                  0,0,
4                  sizeX,sizeY,
5                  data,
6                  width,height,
7                  GDT_Byte,
8                  0,0);

这样需要的数据就读到data中了,RasterIO最后两个参数为0为什么这样至今任未明白,按照参考文档应该是具体的字节值才是,但是经过很多次的测试,只有都为0时才能正确显示图像。

注:显示图像使用的是QImage,图像中波段组织形式为RGB888,即三个波段,每个波段8位。上面data只是8位的灰度数据,要显示出来还需复制两个波段,使每个波段像素值都相等,这样形成灰度图像。不知道使用qt有没有其他的方法显示图像,VC可以显示1个波段的图像,QT好像不可以(有待验证),至少目前没有找到方法,要是可以的话在上图像数据量比较大时可以节约内存。

2.鼠标事件

鼠标事件在基类中是虚函数,没有实现的(见帮助文档),要捕获鼠标事件,必须重写函数,如下几个与鼠标事件有关:

这里只需要处理mousePressEvent(鼠标按下)和mouseReleaseEvent(鼠标释放)事件。

因为显示缩略图的控件QLabel只是主界面的子部件,因此重写主界面类(派生自QMainWindow)的鼠标事件,而不是在QLabel派生类中实现。在QLabel派生类中实现的话,很难将信息传递给主界面类,程序的功能是在主界面类中实现的。缩略图中的鼠标事件要实时获取,而在QLabel中点击鼠标,QMainWindow派生类中的鼠标事件可以获取到。而有些部件(比如QGraphicsView)就不能获取,在这些部件上处理鼠标事件在后面图像拖拽时讲解。

需要的坐标信息如下:菜单栏和工具栏的高度,缩略图显示区大小,缩略图大小,缩略图显示区左上角坐标(其值时相对于主窗口区的),鼠标按下和释放时的坐标(其值时相对于整个界面的)。根据如上几个数据信息就可以计算出鼠标按下和释放所包含的范围,即起始点(鼠标按下时)在缩略图中的坐标位置和终止点(鼠标释放时)在缩略图中的坐标位置。

3.原图区域显示

得到了鼠标在缩略图中的坐标位置,根据缩小倍数zoom,既可以得到在源图像中的坐标位置(×zoom),然后用RasterIO读取区域中的数据。如何读区域数据就不多说了,请参照RasterIO的使用http://www.cnblogs.com/Romi/archive/2012/03/29/2424073.html

读取出数据后显示出来,这里使用了QGraphicsView框架,使用其显示内存中图像数据的方法如下:

1 QImage *img=new QImage(.......);//将内存中data数据组织为可显示的QImage对象
2 QPixmap pixmap=QPixmap::fromImage(*img);
3 QGraphicsScene *scene=new QGraphicsScene;
4 QGraphicsPixmapItem *pixmapItem=new QGraphicsPixmapItem;
5 pixmapItem=scene->addPixmap(pixmap);
6 ui.graphicsView->setScene(scene);
7 ui.graphicsView->show();