1.灰度图像直方图

直方图统计是图像处理中的一个非常重要的操作。VTK中实现直方图统计功能的filter是vtkImageAccumulate。其将每个组分的数值范围划分为离散的间隔,然后统计每个灰度间隔上的像素数目。vtkImageAccumulate输入和输出都是vtkImageData类型,因此直方图也可以看做是一幅图像;对于输入图像的像素数据类型可以是任意的,但是最大支持3个组分像素类型,而输出图像的像素数据类型为int型。一个灰度图像的直方图为一个一维图像。
下面代码提供了如何计算灰度图像直方图的方法:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageAccumulate.h>
#include <vtkImageData.h>
#include <vtkIntArray.h>
#include <vtkDataObject.h> //
#include <vtkFieldData.h>  //一起用
#include <vtkBarChartActor.h>
#include <vtkProperty2D.h>
#include <vtkTextProperty.h>
#include <vtkLegendBoxActor.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>int main()
{vtkSmartPointer<vtkJPEGReader> reader =vtkSmartPointer<vtkJPEGReader>::New();reader->SetFileName("lena-gray.jpg");reader->Update();int bins = 16;int comps = 1;vtkSmartPointer<vtkImageAccumulate> histogram =vtkSmartPointer<vtkImageAccumulate>::New();histogram->SetInputData(reader->GetOutput());histogram->SetComponentExtent(0, bins - 1, 0, 0, 0, 0);histogram->SetComponentOrigin(0, 0, 0);histogram->SetComponentSpacing(256.0 / bins, 0, 0);histogram->Update();int* output = static_cast<int*>(histogram->GetOutput()->GetScalarPointer());vtkSmartPointer<vtkIntArray> frequencies =vtkSmartPointer<vtkIntArray>::New();frequencies->SetNumberOfComponents(1);for (int j = 0; j < bins; ++j){for (int i = 0; i<comps; i++){frequencies->InsertNextTuple1(*output++);}}vtkSmartPointer<vtkDataObject> dataObject =vtkSmartPointer<vtkDataObject>::New();dataObject->GetFieldData()->AddArray(frequencies);vtkSmartPointer<vtkBarChartActor> barChart =vtkSmartPointer<vtkBarChartActor>::New();barChart->SetInput(dataObject);barChart->SetTitle("Histogram");barChart->GetPositionCoordinate()->SetValue(0.05, 0.05, 0.0);barChart->GetPosition2Coordinate()->SetValue(0.95, 0.95, 0.0);barChart->GetProperty()->SetColor(0, 0, 0);barChart->GetTitleTextProperty()->SetColor(0, 0, 0);barChart->GetLabelTextProperty()->SetColor(0, 0, 0);barChart->GetLegendActor()->SetNumberOfEntries(dataObject->GetFieldData()->GetArray(0)->GetNumberOfTuples());barChart->LegendVisibilityOff();barChart->LabelVisibilityOff();double colors[3][3] = {{ 1, 0, 0 },{ 0, 1, 0 },{ 0, 0, 1 } };int count = 0;for (int i = 0; i < bins; ++i){for (int j = 0; j < comps; ++j){barChart->SetBarColor(count++, colors[j]); //单通道 红色}}vtkSmartPointer<vtkImageActor> imgActor =vtkSmartPointer<vtkImageActor>::New();imgActor->SetInputData(reader->GetOutput());double imgView[4] = { 0.0, 0.0, 0.5, 1.0 };double barView[4] = { 0.5, 0.0, 1.0, 1.0 };vtkSmartPointer<vtkRenderer> barRender =vtkSmartPointer<vtkRenderer>::New();barRender->SetViewport(barView);barRender->AddActor(barChart);barRender->SetBackground(1.0, 1.0, 1.0);vtkSmartPointer<vtkRenderer> imgRender =vtkSmartPointer<vtkRenderer>::New();imgRender->SetViewport(imgView);imgRender->AddActor(imgActor);imgRender->SetBackground(1.0, 1.0, 1.0);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(barRender);renderWindow->AddRenderer(imgRender);renderWindow->SetSize(640, 320);renderWindow->Render();renderWindow->SetWindowName("Gray-Image Histogram");vtkSmartPointer<vtkRenderWindowInteractor> interactor =vtkSmartPointer<vtkRenderWindowInteractor>::New();interactor->SetRenderWindow(renderWindow);interactor->Initialize();interactor->Start();return 0;
}

下面来分析一下代码。

首先是读入一副灰度图像,一般的灰度图像的灰度范围为0-255。定义了一个变量bins = 16,表示要图像灰度范围上的间隔数目,也可以理解为直方图一维数组的维数。然后定义vtkImageAccumulate对象,并设置输入数据为我们读入的图像数据,接着调用了三个函数:
SetComponentExtent(0,bins-1, 0, 0, 0, 0),该函数设置要计算每个组分的直方图的最小和最大值。vtkImageAccumulate最大支持像素值为三个组分(如RGB图像)的直方图,支持共有六个参数。分别表示每个组分的直方图最小和最大值。该例中由于计算的是灰度图像直方图,只有一个组分,因此第二个和第三个组分都设置为0;而第一组分直方图维数为bins = 16,那么其最小和最大范围为0和bins-1。
SetComponentOrigin(0,0,0),该函数设置的是统计每个组分直方图时的起始灰度值,这里设置为0,表示灰度从0开始统计直方图。同样,vtkImageAccumulate最大支持像素值为三个组分,这里也要设置三个参数。如果图像的灰度范围为[1000, 2000],那么计算直方图时,其起始灰度应该设置为1000。
SetComponentSpacing(16,0, 0),设置直方图每个间隔代表的灰度范围,例如当一个图像灰度范围为[1000, 2000],统计直方图的间隔数bins为100时,那么对应的space应该设置为SetComponentSpacing(100, 0, 0)。
参数设置完毕后执行Update()即可计算直方图前面已经提到过,vtkImageAccumulate的输出结果也是一个vtkImageData类型,这样就可以方便的访问图像的每个数据。图像像素访问前面已经介绍过,这里就不在重述。需要注意的是输出直方图图像的数据类型为int。

这里再顺便简单的介绍一下直方图的显示。

虽然vtkImageAccumulate的输出类型为vtkImageData但是并不能直接按照图像的方式进行显示。VTK中定义了vtkBarChartActor用来显示条形图,因此可以利用其来显示直方图。但是该类接收的数据类型为vtkDataObject类型,因此需要先将直方图数据进行转换。首先将直方图数组存储到vtkIntArray数组frequencies中,通过函数vtkDataObject函数GetFieldData()->AddArray(frequencies)将其添加到vtkDataObject对象中。vtkBarChartActor对象接收vtkDataObject对象作为输入,另外还需要设置图表的名字,颜色等,需要注意两个函数:
barChart->GetPositionCoordinate()->SetValue(0.05,0.05,0.0);
barChart->GetPosition2Coordinate()->SetValue(0.95,0.95,0.0);
这里设置的是窗口中显示图表的所在矩形的左下角点和右上角点坐标,VTK的坐标系原点位于左下角点,设置时需要格外注意。设置完毕后,即可定义相应的vtkRenderer,vtkRenderWindow和vtkRenderWindowInteractor对象显示图像直方图。
本例的显示效果如下:

2.参看资料

1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3.《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》
4.  张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.

VTK修炼之道28:图像统计_灰度直方图计算相关推荐

  1. VTK修炼之道29:图像统计_彩色直方图计算

    1.彩色图像直方图 彩色图像由于内部有三个通道,不能直接计算直方图,需要提取RGB三个通道数据,分别计算直方图.每个通道计算直方图的方法与灰度图像直方图计算方法一致. 实例代码如下: #include ...

  2. VTK修炼之道36:图像平滑_均值滤波器

    1.图像平滑 图像平滑常用于图像的预处理中,如计算梯度时先对图像进行平滑处理,可以减少噪声对梯度的影响.图像平滑一般是通过模板卷积运算实现.模板可以看做是一个大小为nxn的小图像,例如3x3,5x5等 ...

  3. VTK修炼之道14:图像处理_创建

    1.引言:图像数据结构 数字图像文件内容由两个部分组成:图像头信息和数据.图像头信息定义了图像的基本信息,主要包括起点位置(Origin),像素间隔(space)和维数(dimension).通过这三 ...

  4. VTK修炼之道16:图像处理_窗口分割和图像融合(ViewportvtkImageBlend)

    1.前言 前面演示的例子都是在一个窗口中显示一个图像.但是在常见的图像处理软件中,经常会遇到在一个窗口中显示多个图像,这就会用到图像融合技术.图像融合利用图像的alpha通道和不透明度来实现.VTK中 ...

  5. VTK修炼之道62:体绘制_固定点光线投影体绘制与GPU加速光线投影体绘制

    1.固定点光线投影算法 vtkFixedPointVolumeRayCastMapper是一个较好的vtkVolumeRayCastMapper的替代者.该类能够实现基于Alpha合成的体绘制方法和最 ...

  6. VTK修炼之道61:体绘制_光线投影+最大密度投影+等值面法

    1.vtkVolumeMapper vtkVolumeMapper是所有体绘制Mapper类的虚基类,提供接口函数,并由其子类实现具体功能.该类的继承关系如下图所示: 应该掌握一些常用的体绘制类. 2 ...

  7. VTK修炼之道60:体绘制_体绘制管线图形渲染管线

    1.几何渲染与体绘制 1.1 几何渲染 前面练习的渲染技术都是几何渲染技术.所谓的几何渲染技术,就是通过绘制几何图元(顶点.线段.面片等)来渲染数据,例如:绘制图像需要在空间中建立一个四边形图元,然后 ...

  8. VTK修炼之道39:图像平滑_各向异性滤波

    1.各向异性扩散滤波 高斯平滑方法在平滑噪声的同时,模糊了图像的重要边缘图像. 各向异性滤波是一种基于偏微分方程的滤波技术,建立于热量的各向异性扩散理论. 各向异性滤波在图像的平坦区域选择大尺度平滑, ...

  9. VTK修炼之道38:图像平滑_中值滤波器

    1.中值滤波 vtkImageHybridMedian2D实现了对二维图像的中值滤波.其实现原理是,采用一个5x5的模板,逐次将模板中心对应于图像的每个像素上,将模板图像覆盖的像素的中值作为当前像素的 ...

最新文章

  1. php short_open_tag asp_tags
  2. 色诱社报道:昨日,腾讯公司公布了2009年发展策划
  3. 数学之美笔记(二十)
  4. MATLAB从入门到精通-欧拉法与梯形法求解微分方程(含MATLAB源码)
  5. jst获取不到springmvc中model数据
  6. 超级菜鸟如何入门数据分析?
  7. JavaWeb学习总结(十二):Session
  8. 2020年了,再不会Https就老了
  9. Linux开机启动分析与系统配置
  10. NoClassDefFoundError: Could not initialize class com.fasterxml.jackson.databind.ObjectMapper
  11. 跨过Nginx上基于uWSGI部署Django项目的坑
  12. matlab最优化问题
  13. 计算机开机会跳过自检嘛,电脑开机怎样跳过自检
  14. 150款国潮风城市插画
  15. 成功解决 word2019设置背景色为护眼的绿色
  16. Sonic simple服务中设备图片、测试用例运行异常图片、失败录像路径映射配置
  17. 转载 一个小时学会MySQL数据库(2)
  18. Ubuntu查看usb 设备
  19. 多核学习工具箱Shogun的手动编译过程
  20. 不朽凡人 正文 第四百八十章 太厉害了

热门文章

  1. PART 5: INTEGRATING SPRING SECURITY WITH SPRING BOOT WEB
  2. Linux下利用backtrace追踪函数调用堆栈以及定位段错误
  3. WinForm 自定义控件属性
  4. HD 1159 Common Subsequence (最长公共子序列)
  5. java------多线程通信
  6. C++统计难题hdu1251
  7. 类模板非类型形参实现Stack
  8. 常见的加密和解密算法—MD5
  9. 70. Climbing Stairs
  10. Hibernate总结1