#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileDialog>
#include <QDebug>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkJPEGReader.h>
#include <vtkImageData.h>
#include <vtkImageLuminance.h>
#include <vtkImageActor.h>
#include <vtkImageThreshold.h>
#include <vtkInteractorStyleImage.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void openFileSlot();
private:
vtkSmartPointer<vtkRenderer> pSrcGradientRenderer;
vtkSmartPointer<vtkRenderer> pGradientRenderer;
vtkSmartPointer<vtkRenderer> pSrcSobelRenderer;
vtkSmartPointer<vtkRenderer> pSobelXRenderer;
vtkSmartPointer<vtkRenderer> pSobelYRenderer;
vtkSmartPointer<vtkRenderer> pSobelRenderer;
vtkSmartPointer<vtkRenderer> pSrcCandyRenderer;
vtkSmartPointer<vtkRenderer> pCandyRenderer;
vtkSmartPointer<vtkRenderer> pSrcLaplaceRenderer;
vtkSmartPointer<vtkRenderer> pLaplaceRenderer;
vtkSmartPointer<vtkInteractorStyleImage> pImageStyle;
vtkSmartPointer<vtkJPEGReader> pJpegReader;
vtkSmartPointer<vtkImageActor> pSrcGradientImageActor;
vtkSmartPointer<vtkImageActor> pGradientImageActor;
vtkSmartPointer<vtkImageActor> pSrcSobelImageActor;
vtkSmartPointer<vtkImageActor> pSobelXImageActor;
vtkSmartPointer<vtkImageActor> pSobelYImageActor;
vtkSmartPointer<vtkImageActor> pSobelImageActor;
vtkSmartPointer<vtkImageActor> pSrcCandyImageActor;
vtkSmartPointer<vtkImageActor> pCandyImageActor;
vtkSmartPointer<vtkImageActor> pSrcLaplaceImageActor;
vtkSmartPointer<vtkImageActor> pLaplaceImageActor;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <vtkImageGradient.h>
#include <vtkImageMagnitude.h>
#include <vtkImageShiftScale.h>
#include <vtkImageSobel2D.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageMathematics.h>
#include <vtkImageLuminance.h>
#include <vtkImageCast.h>
#include <vtkImageGaussianSmooth.h>
#include <vtkImageNonMaximumSuppression.h>
#include <vtkImageConstantPad.h>
#include <vtkImageToStructuredPoints.h>
#include <vtkLinkEdgels.h>
#include <vtkThreshold.h>
#include <vtkGeometryFilter.h>
#include <vtkSubPixelPositionEdgels.h>
#include <vtkStripper.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkImageLaplacian.h>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
{
pSrcGradientRenderer = vtkSmartPointer<vtkRenderer>::New();
pSrcGradientRenderer->SetBackground(1.0, 0, 0);
pSrcGradientRenderer->SetViewport(0, 0, 0.5, 0.25);
pGradientRenderer = vtkSmartPointer<vtkRenderer>::New();
pGradientRenderer->SetBackground(1.0, 0, 0);
pGradientRenderer->SetViewport(0.5, 0, 1.0, 0.25);
}
{
pSrcSobelRenderer = vtkSmartPointer<vtkRenderer>::New();
pSrcSobelRenderer->SetBackground(0.0, 1.0, 0.0);
pSrcSobelRenderer->SetViewport(0, 0.25, 0.25, 0.5);
pSobelXRenderer = vtkSmartPointer<vtkRenderer>::New();
pSobelXRenderer->SetBackground(0.0, 1.0, 0.0);
pSobelXRenderer->SetViewport(0.25, 0.25, 0.5, 0.5);
pSobelYRenderer = vtkSmartPointer<vtkRenderer>::New();
pSobelYRenderer->SetBackground(0.0, 1.0, 0.0);
pSobelYRenderer->SetViewport(0.5, 0.25, 0.75, 0.5);
pSobelRenderer = vtkSmartPointer<vtkRenderer>::New();
pSobelRenderer->SetBackground(0.0, 1.0, 0.0);
pSobelRenderer->SetViewport(0.75, 0.25, 1.0, 0.5);
}
{
pSrcCandyRenderer = vtkSmartPointer<vtkRenderer>::New();
pSrcCandyRenderer->SetBackground(0.0, 0.0, 1.0);
pSrcCandyRenderer->SetViewport(0, 0.5, 0.5, 0.75);
pCandyRenderer = vtkSmartPointer<vtkRenderer>::New();
pCandyRenderer->SetBackground(0.0, 0.0, 1.0);
pCandyRenderer->SetViewport(0.5, 0.5, 1.0, 0.75);
}
{
pSrcLaplaceRenderer = vtkSmartPointer<vtkRenderer>::New();
pSrcLaplaceRenderer->SetBackground(1.0, 0, 0);
pSrcLaplaceRenderer->SetViewport(0, 0.75, 0.5, 1.0);
pLaplaceRenderer = vtkSmartPointer<vtkRenderer>::New();
pLaplaceRenderer->SetBackground(1.0, 0, 0);
pLaplaceRenderer->SetViewport(0.5, 0.75, 1.0, 1.0);
}
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(openFileSlot()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::openFileSlot()
{
#if 1
QString selectFilePath = QFileDialog::getOpenFileName(this, QString("选择图像文件"), QString(""), QString("图像(*.jpg)"));
#else
QString selectFilePath = QFileDialog::getOpenFileName(this, QString("选择图像文件"), QString(""), QString("图像(*.png)"));
#endif
if(selectFilePath.isEmpty())
{
ui->textBrowser->append("选择图像路径为空!");
return ;
}
else
{
ui->textBrowser->append(selectFilePath);
}
pJpegReader = vtkSmartPointer<vtkJPEGReader>::New();
pJpegReader->SetFileName(selectFilePath.toStdString().c_str());
pJpegReader->Update();
int dims[3];
pJpegReader->GetOutput()->GetDimensions(dims);
qDebug() << "dims = " << dims[0] << ", " << dims[1] << ", " << dims[2];
vtkSmartPointer<vtkImageLuminance> pImageLuminance = vtkSmartPointer<vtkImageLuminance>::New();
pImageLuminance->SetInputData(pJpegReader->GetOutput());
pImageLuminance->Update();
// 计算图像梯度
{
pSrcGradientImageActor = vtkSmartPointer<vtkImageActor>::New();
pSrcGradientImageActor->SetInputData(pJpegReader->GetOutput());
pSrcGradientRenderer->AddActor(pSrcGradientImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSrcGradientRenderer);
vtkSmartPointer<vtkImageGradient> pImageGradient = vtkSmartPointer<vtkImageGradient>::New();
pImageGradient->SetInputData(pImageLuminance->GetOutput());
pImageGradient->SetDimensionality(2);
pImageGradient->Update();
vtkSmartPointer<vtkImageMagnitude> pImageMagnitude = vtkSmartPointer<vtkImageMagnitude>::New();
pImageMagnitude->SetInputData(pImageGradient->GetOutput());
pImageMagnitude->Update();
double range[2];
pImageMagnitude->GetOutput()->GetScalarRange(range);
vtkSmartPointer<vtkImageShiftScale> pImageShift = vtkSmartPointer<vtkImageShiftScale>::New();
pImageShift->SetOutputScalarTypeToUnsignedChar();
pImageShift->SetScale(255 / range[1]);
pImageShift->SetInputData(pImageMagnitude->GetOutput());
pImageShift->Update();
pGradientImageActor = vtkSmartPointer<vtkImageActor>::New();
pGradientImageActor->SetInputData(pImageShift->GetOutput());
pGradientRenderer->AddActor(pGradientImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pGradientRenderer);
}
// Sobel算子
{
pSrcSobelImageActor = vtkSmartPointer<vtkImageActor>::New();
pSrcSobelImageActor->SetInputData(pJpegReader->GetOutput());
pSrcSobelRenderer->AddActor(pSrcSobelImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSrcSobelRenderer);
vtkSmartPointer<vtkImageSobel2D> pImageSobel = vtkSmartPointer<vtkImageSobel2D>::New();
pImageSobel->SetInputData(pImageLuminance->GetOutput());
pImageSobel->Update();
// X 分量
{
vtkSmartPointer<vtkImageExtractComponents> pImageExtract = vtkSmartPointer<vtkImageExtractComponents>::New();
pImageExtract->SetComponents(0); // pImageSobel 包含X, Y方向的梯度,所以需要抽取其中一个
pImageExtract->SetInputData(pImageSobel->GetOutput());
pImageExtract->Update();
vtkSmartPointer<vtkImageMathematics> pImageMath = vtkSmartPointer<vtkImageMathematics>::New();
pImageMath->SetOperationToAbsoluteValue();
pImageMath->SetInput1Data(pImageExtract->GetOutput());
pImageMath->Update();
double range[2];
pImageMath->GetOutput()->GetScalarRange(range);
vtkSmartPointer<vtkImageShiftScale> pImageShift = vtkSmartPointer<vtkImageShiftScale>::New();
pImageShift->SetOutputScalarTypeToUnsignedChar();
pImageShift->SetScale(255 / range[1]);
pImageShift->SetInputData(pImageMath->GetOutput());
pImageShift->Update();
pSobelXImageActor = vtkSmartPointer<vtkImageActor>::New();
pSobelXImageActor->SetInputData(pImageShift->GetOutput());
pSobelXRenderer->AddActor(pSobelXImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSobelXRenderer);
}
// Y分量
{
vtkSmartPointer<vtkImageExtractComponents> pImageExtract = vtkSmartPointer<vtkImageExtractComponents>::New();
pImageExtract->SetComponents(1); // pImageSobel 包含X, Y方向的梯度,所以需要抽取其中一个
pImageExtract->SetInputData(pImageSobel->GetOutput());
pImageExtract->Update();
vtkSmartPointer<vtkImageMathematics> pImageMath = vtkSmartPointer<vtkImageMathematics>::New();
pImageMath->SetOperationToAbsoluteValue();
pImageMath->SetInput1Data(pImageExtract->GetOutput());
pImageMath->Update();
double range[2];
pImageMath->GetOutput()->GetScalarRange(range);
vtkSmartPointer<vtkImageShiftScale> pImageShift = vtkSmartPointer<vtkImageShiftScale>::New();
pImageShift->SetOutputScalarTypeToUnsignedChar();
pImageShift->SetScale(255 / range[1]);
pImageShift->SetInputData(pImageMath->GetOutput());
pImageShift->Update();
pSobelYImageActor = vtkSmartPointer<vtkImageActor>::New();
pSobelYImageActor->SetInputData(pImageShift->GetOutput());
pSobelYRenderer->AddActor(pSobelYImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSobelYRenderer);
}
// 梯度
{
vtkSmartPointer<vtkImageMagnitude> pImageMagnitude = vtkSmartPointer<vtkImageMagnitude>::New();
pImageMagnitude->SetInputData(pImageSobel->GetOutput());
pImageMagnitude->Update();
double range[2];
pImageMagnitude->GetOutput()->GetScalarRange(range);
vtkSmartPointer<vtkImageShiftScale> pImageShift = vtkSmartPointer<vtkImageShiftScale>::New();
pImageShift->SetOutputScalarTypeToUnsignedChar();
pImageShift->SetScale(255 / range[1]);
pImageShift->SetInputData(pImageMagnitude->GetOutput());
pImageShift->Update();
pSobelImageActor = vtkSmartPointer<vtkImageActor>::New();
pSobelImageActor->SetInputData(pImageShift->GetOutput());
pSobelRenderer->AddActor(pSobelImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSobelRenderer);
}
}
// Candy算子
{
pSrcCandyImageActor = vtkSmartPointer<vtkImageActor>::New();
pSrcCandyImageActor->SetInputData(pJpegReader->GetOutput());
pSrcCandyRenderer->AddActor(pSrcCandyImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSrcCandyRenderer);
vtkSmartPointer<vtkImageCast> pImageCast = vtkSmartPointer<vtkImageCast>::New();
pImageCast->SetInputData(pImageLuminance->GetOutput());
pImageCast->SetOutputScalarTypeToFloat();
pImageCast->Update();
vtkSmartPointer<vtkImageGaussianSmooth> pImageGaussianSmooth = vtkSmartPointer<vtkImageGaussianSmooth>::New();
pImageGaussianSmooth->SetInputData(pImageCast->GetOutput());
pImageGaussianSmooth->SetDimensionality(2);
pImageGaussianSmooth->SetRadiusFactors(1, 1, 0);
pImageGaussianSmooth->Update();
vtkSmartPointer<vtkImageGradient> pImageGradient = vtkSmartPointer<vtkImageGradient>::New();
pImageGradient->SetInputData(pImageGaussianSmooth->GetOutput());
pImageGradient->SetDimensionality(2);
pImageGradient->Update();
vtkSmartPointer<vtkImageMagnitude> pImageMagnitude = vtkSmartPointer<vtkImageMagnitude>::New();
pImageMagnitude->SetInputData(pImageGradient->GetOutput());
pImageMagnitude->Update();
vtkSmartPointer<vtkImageNonMaximumSuppression> pImageNonMax = vtkSmartPointer<vtkImageNonMaximumSuppression>::New();
pImageNonMax->SetMagnitudeInputData(pImageMagnitude->GetOutput());
pImageNonMax->SetVectorInputData(pImageGradient->GetOutput());
pImageNonMax->SetDimensionality(2);
pImageNonMax->Update();
vtkSmartPointer<vtkImageConstantPad> pImagePad = vtkSmartPointer<vtkImageConstantPad>::New();
pImagePad->SetInputData(pImageGradient->GetOutput());
pImagePad->SetOutputNumberOfScalarComponents(3);
pImagePad->SetConstant(0);
pImagePad->Update();
vtkSmartPointer<vtkImageToStructuredPoints> pImageStruct = vtkSmartPointer<vtkImageToStructuredPoints>::New();
pImageStruct->SetInputData(pImageNonMax->GetOutput());
pImageStruct->SetVectorInputData(pImagePad->GetOutput());
pImageStruct->Update();
vtkSmartPointer<vtkLinkEdgels> pImageLink = vtkSmartPointer<vtkLinkEdgels>::New();
pImageLink->SetInputData(pImageStruct->GetOutput());
pImageLink->SetGradientThreshold(2);
pImageLink->Update();
vtkSmartPointer<vtkThreshold> pImageThreshold = vtkSmartPointer<vtkThreshold>::New();
pImageThreshold->SetInputData(pImageLink->GetOutput());
pImageThreshold->ThresholdByUpper(10);
pImageThreshold->AllScalarsOff();
pImageThreshold->Update();
vtkSmartPointer<vtkGeometryFilter> pImageGeometry = vtkSmartPointer<vtkGeometryFilter>::New();
pImageGeometry->SetInputConnection(pImageThreshold->GetOutputPort());
pImageGeometry->Update();
vtkSmartPointer<vtkImageToStructuredPoints> pImageStruct2 = vtkSmartPointer<vtkImageToStructuredPoints>::New();
pImageStruct2->SetInputData(pImageMagnitude->GetOutput());
pImageStruct2->SetVectorInputData(pImagePad->GetOutput());
pImageStruct2->Update();
vtkSmartPointer<vtkSubPixelPositionEdgels> pSubImageEdgels = vtkSmartPointer<vtkSubPixelPositionEdgels>::New();
pSubImageEdgels->SetInputData(pImageGeometry->GetOutput());
pSubImageEdgels->SetGradMapsData(pImageStruct2->GetStructuredPointsOutput());
pSubImageEdgels->Update();
vtkSmartPointer<vtkStripper> pStripper = vtkSmartPointer<vtkStripper>::New();
pStripper->SetInputData(pSubImageEdgels->GetOutput());
pStripper->Update();
vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
pPolyDataMapper->SetInputConnection(pStripper->GetOutputPort());
pPolyDataMapper->ScalarVisibilityOff();
pPolyDataMapper->Update();
vtkSmartPointer<vtkActor> planeActor = vtkSmartPointer<vtkActor>::New();
planeActor->SetMapper(pPolyDataMapper);
planeActor->GetProperty()->SetAmbient(1.0);
planeActor->GetProperty()->SetDiffuse(0.0);
planeActor->GetProperty()->SetColor(1.0, 1.0, 1.0);
pCandyRenderer->AddActor(planeActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pCandyRenderer);
}
// Laplace算子
{
pSrcLaplaceImageActor = vtkSmartPointer<vtkImageActor>::New();
pSrcLaplaceImageActor->SetInputData(pJpegReader->GetOutput());
pSrcLaplaceRenderer->AddActor(pSrcLaplaceImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pSrcLaplaceRenderer);
vtkSmartPointer<vtkImageLaplacian> pImageLaplace = vtkSmartPointer<vtkImageLaplacian>::New();
pImageLaplace->SetInputData(pImageLuminance->GetOutput());
pImageLaplace->SetDimensionality(2);
pImageLaplace->Update();
double range[2];
pImageLaplace->GetOutput()->GetScalarRange(range);
vtkSmartPointer<vtkImageShiftScale> pImageShift = vtkSmartPointer<vtkImageShiftScale>::New();
pImageShift->SetOutputScalarTypeToUnsignedChar();
pImageShift->SetScale(255 / range[1]);
pImageShift->SetInputData(pImageLaplace->GetOutput());
pImageShift->Update();
pLaplaceImageActor = vtkSmartPointer<vtkImageActor>::New();
pLaplaceImageActor->SetInputData(pImageShift->GetOutput());
pLaplaceRenderer->AddActor(pLaplaceImageActor);
ui->qvtkWidget->GetRenderWindow()->AddRenderer(pLaplaceRenderer);
}
pImageStyle = vtkSmartPointer<vtkInteractorStyleImage>::New();
ui->qvtkWidget->GetInteractor()->SetInteractorStyle(pImageStyle);
ui->qvtkWidget->GetRenderWindow()->Render();
}
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="2,5">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>选择图像</string>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="textBrowser"/>
</item>
</layout>
</item>
<item>
<widget class="QVTKWidget" name="qvtkWidget"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QVTKWidget</class>
<extends>QWidget</extends>
<header>QVTKWidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>