How to speed rendering of histogram?

hello,

I’m beginner and i just code my first vtk plot link with QT.

This plot should represent the histogram of an image.

So the input data will just be a std::vector with a size of 65 536.

The problem that i encounter is the fact that this plot slow down the code a lot.

More, when the plot is done, moving axis or zooming into the plot is also slow (something like 0.5fps).

maybe i did something wrong. If not did someone know how can i speed this plot which should be really easy and really fast normally (like with matplotlib in python).

thank you in advance !

here the code:

void PlotWidget::plotHistogram(std::vector<double>* histo)
{
	vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
	vtkNew<vtkChartXY> chart;
	vtkNew<vtkContextView> view;

	this->ui->qvtkWidget->setRenderWindow(renderWindow);

	//-------Axe X----------------
	vtkAxis* xAxis = chart->GetAxis(vtkAxis::BOTTOM);
	xAxis->SetGridVisible(true);

	//-------Axe Y----------------
	vtkAxis* yAxis = chart->GetAxis(vtkAxis::LEFT);
	yAxis->SetGridVisible(true);

	//-------view-----------------
	view->SetRenderWindow(renderWindow);
	view->GetRenderWindow()->SetSize(640, 480);
	view->GetScene()->AddItem(chart);

	vtkNew<vtkTable> table;

	vtkNew<vtkIntArray> pix;
	pix->SetName("depth");
	table->AddColumn(pix);

	vtkNew<vtkIntArray> count;
	count->SetName("count");
	table->AddColumn(count);

	table->SetNumberOfRows(histo->size());

	for (int depth = 0; depth < histo->size(); depth++) {
		table->SetValue(depth, 0, depth);
		table->SetValue(depth, 1, histo->at(depth));
	}

	vtkPlot* line = 0;
	line = chart->AddPlot(vtkChart::BAR);
	line->SetInputData(table, 0, 1);

	this->ui->qvtkWidget->setRenderWindow(view->GetRenderWindow());

}

Hello,

Where is that method being called? Why are you calling this->ui->qvtkWidget->setRenderWindow() twice?

regards,

PC

Hello,

I call the function in the MainWindow class in the function open:

void MainWindow::open() {

    QString path_of_file = explorer(this, false);
    Image* image = Image::getInstance(&path_of_file);
    this->displayW->loadInTheMainLabel(image);
    this->plotW->plotHistogram(&image->getHisto());
    delete image;

}

where plotW is an Object PlotWidget* plotW.
and displayW represent just a widget which display images.
image->getHisto() return the histogram as std::vector.

yes i realised after that this->ui->qvtkWidget->setRenderWindow(view->GetRenderWindow());

is useless. i just tried to reproduce the exemple present on this page https://kitware.github.io/vtk-examples/site/Cxx/Qt/BarChartQt/

but same if i delete this line, nothing change. But the problem do not come from my code:

If i comment this->plotW->plotHistogram(&image->getHisto()) the code is fast. Im not event able to see any latences by eyes. With this line, the image and the histogram is display after 2s

Also i call plotHistogram just one time and all lines in this function take in average 2ms.

Is it possible that it’s slow because i compile vtk with BUILD_SHARED_LIBS with true (as dynamical librairy)?

I tried myself, and it’s slow just as you described. BUILD_SHARED_LIBS is definitely not the problem, vtkChartXY simply can’t render 65536 bins as fast as you need. I’m not surprised that matplotlib is faster, though.

I suspect that the only way to speed things up is to create a table that has fewer values than your histogram. For example, use only every 100th value. This isn’t an ideal solution, of course, because you lose detail.

	table->SetNumberOfRows(histo->size()/100);

	for (int depth = 0; depth < histo->size(); depth += 100) {
		table->SetValue(depth/100, 0, depth);
		table->SetValue(depth/100, 1, histo->at(depth));
	}

thank you for your response that helped me a lot.

You said that vtkChartXY is not able to render 65536 bins that fast. So i changed vtkChart::BAR by vtkChart::LINE and now the code is much faster. I think they are still some small latences but it’s clearly acceptable and moving axis now is much more fluid.

I have two questions for the futur.

The first one:
Do you know some other enum of vtkChart which can even be faster? maybe scatter?

the second question (which also contain two question):
as i want that the user can be able de manually choose the dynamical range on the plot of the graph, do you know how can i interact with it via a cursor maybe, and second how can i have a better control on the movement of axis (i dont want users can move the graph just by clicking on it. i would like to set up the graph at the beginning than, allow user to make some zoom but nothing more)

I don’t know the answers to your questions, I’ve only used vtkChartXY for very simple plots and I’m not familiar with all its features.

But I did a quick search for ‘vtk chart range handle’ and came up with this: vtkPlotRangeHandlesItem.

Someone like @mwestphal might be more familiar with chart interaction.

Edit: fixed link

I did work on it but did not run any benchmark on the different types of plots.

@antoine1 you will have to dig into it.

Computing a histogram is a slow operation since it requires ordering the data set for binning. Also, I wonder why do you need 65k+ bins. Tens of bins are more than enough to draw conclusions. Once the histogram is computed, plotting it in 2ms is a good figure. You can get 500fps with that. I don’t see any problems.

If your dataset is large, decimating it is a good strategy to get fast histograms. In petroleum industry we do this all the time. We have seismic cubes with around a trillion data cells. Histograms with only a 0.01% sampling rate or less are quite common.

Hello,

I have 65k because the flux measured by a pixels on an image is coded into 16bits (8 bits for some cameras and format) 65k is qui small data for a computer and i compute the histogram my self.

It’s ok now. histograms are just one time of representation but a simple line can also do the job and it’s faster.

thanks. I will try to make a benchmark about which type of plots are faster later.