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

1.彩色图像直方图

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

#include <vtkSmartPointer.h>
#include <vtkBMPReader.h>
#include <vtkImageData.h>
#include <vtkXYPlotActor.h>
#include <vtkProperty2D.h>
#include <vtkTextProperty.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageAccumulate.h>

#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

int main()
{
	vtkSmartPointer<vtkBMPReader> reader =
		vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("lena.bmp");
	reader->Update();

	int numComponents = reader->GetOutput()->GetNumberOfScalarComponents();

	//
	vtkSmartPointer<vtkXYPlotActor> plot =
		vtkSmartPointer<vtkXYPlotActor>::New();
	plot->ExchangeAxesOff();
	plot->SetLabelFormat("%g");
	plot->SetXTitle("灰度值");
	plot->SetYTitle("像素频率");
	plot->SetXValuesToValue();
	plot->GetProperty()->SetColor(1.0, 1.0, 1.0);
	plot->GetAxisLabelTextProperty()->SetColor(0, 0, 0);
	plot->GetAxisTitleTextProperty()->SetColor(0, 0, 0);

	double colors[3][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
	const char* labels[3] = { "Red", "Green", "Blue" };
	int xmax = 0;
	int ymax = 0;
	for (int i = 0; i < numComponents; ++i)
	{
		vtkSmartPointer<vtkImageExtractComponents> extract =
			vtkSmartPointer<vtkImageExtractComponents>::New();
		extract->SetInputConnection(reader->GetOutputPort());
		extract->SetComponents(i);
		extract->Update();

		double range[2];
		extract->GetOutput()->GetScalarRange(range);
		int extent = static_cast<int> (range[1]) - static_cast<int>(range[0]) - 1;
		
		vtkSmartPointer<vtkImageAccumulate> histogram =
			vtkSmartPointer<vtkImageAccumulate>::New();
		histogram->SetInputConnection(reader->GetOutputPort());
		histogram->SetComponentExtent(0,extent, 0, 0, 0, 0);
		histogram->SetComponentOrigin(range[0], 0, 0);
		histogram->SetComponentSpacing(1, 0, 0);
		histogram->SetIgnoreZero(1);
		histogram->Update();

		if (range[1] > xmax)
		{
			xmax = range[1];
		}
		if (histogram->GetOutput()->GetScalarRange()[1] > ymax)
		{
			ymax = histogram->GetOutput()->GetScalarRange()[1];
		}
		plot->AddDataSetInput(histogram->GetOutput());
		plot->SetPlotColor(i, colors[i]);
		plot->SetPlotLabel(i, labels[i]);
		plot->LegendOn();
	}
	plot->SetXRange(0, xmax);
	plot->SetYRange(0, ymax);
	/
	vtkSmartPointer<vtkImageActor> imgActor =
		vtkSmartPointer<vtkImageActor>::New();
	imgActor->SetInputData(reader->GetOutput());
	
	double imgView[4] = { 0.0, 0.0, 0.5, 1.0 };
	double histView[4] = { 0.5, 0.0, 1.0, 1.0 };
	vtkSmartPointer<vtkRenderer> imgRender =
		vtkSmartPointer<vtkRenderer>::New();
	imgRender->SetViewport(imgView);
	imgRender->AddActor(imgActor);
	imgRender->SetBackground(1.0, 0.0, 0.0);

	vtkSmartPointer<vtkRenderer> histRender =
		vtkSmartPointer<vtkRenderer>::New();
	histRender->SetViewport(histView);
	histRender->AddActor(plot);
	histRender->SetBackground(1.0, 1.0, 1.0);
	/
	vtkSmartPointer<vtkRenderWindow> rw =
		vtkSmartPointer<vtkRenderWindow>::New();
	rw->AddRenderer(imgRender);
	rw->AddRenderer(histRender);
	rw->SetSize(640, 320);
	rw->SetWindowName("RGB-Image Histogram");

	vtkSmartPointer<vtkRenderWindowInteractor> rwi =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	rwi->SetRenderWindow(rw);
	rwi->Initialize();

	rwi->Start();
	return 0;
}

上面代码说明了怎样计算彩色图像直方图。
计算直方图的主要代码段是27-61行。由于彩色图像不能直接计算直方图,因此需要先通过vtkImageExtractComponents来提取每个通道图像,然后再利用vtkImageAccumulate统计直方图。在本例中计算直方图的间隔取(1, 0, 0),即每个灰度计算统计一个频率,而且灰度起点为图像的最小灰度值,这样间隔的个数即为:最大灰度值减去最小灰度值,再减1,如第37行代码。同时,设置了SetIgnoreZero()为1,即在统计直方图时,像素值为0的像素不进行统计。
在灰度图像直方图实例中,我们使用的是vtkBarChartActor柱状图来显示直方图,在本例中则使用vtkXYPlotActor曲线来表示直方图。
vtkXYPlotActor类可以用来显示二维曲线,它可以接收多个输入数据,如本例中我们输入了三条曲线,分别是图像红色分量直方图区域,绿色分量直方图曲线和蓝色分量直方图曲线。SetXRange()和SetYRange()用来设置X轴和Y轴的数据范围,另外还可以设置X轴和Y轴的名字,曲线的标题等属性,详细可以查阅vtkXYPlotActor类的文档。vtkXYPlotActor类是一个vtkActor2D的子类,因此定义相应的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.
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页