├── 高级生物医学图像处理 ├── testImage │ ├── Cruyff.jpg │ └── Lena.bmp └── medImgViewer-src │ ├── origin.jpg │ ├── histogramdialog.h │ ├── mainwindow.ui │ ├── mainwindow.h │ ├── CMakeLists.txt │ ├── mainwindow.cpp │ ├── tabboard.cpp │ ├── tabboard.h │ ├── viewer.h │ ├── histogramdialog.cpp │ ├── main.cpp │ └── viewer.cpp ├── 多维医学图像处理与可视化 ├── pca │ ├── CMakeLists.txt │ └── pca.cpp └── sphereKdTree │ ├── CMakeLists.txt │ └── sphereKdTree.cpp ├── README.md └── .gitignore /高级生物医学图像处理/testImage/Cruyff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluencyLiu/SJTU_BME_Master_FinalProjectsCollection/HEAD/高级生物医学图像处理/testImage/Cruyff.jpg -------------------------------------------------------------------------------- /高级生物医学图像处理/testImage/Lena.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluencyLiu/SJTU_BME_Master_FinalProjectsCollection/HEAD/高级生物医学图像处理/testImage/Lena.bmp -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/origin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluencyLiu/SJTU_BME_Master_FinalProjectsCollection/HEAD/高级生物医学图像处理/medImgViewer-src/origin.jpg -------------------------------------------------------------------------------- /多维医学图像处理与可视化/pca/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | PROJECT(pca) 4 | 5 | find_package(VTK REQUIRED) 6 | include(${VTK_USE_FILE}) 7 | 8 | add_executable(pca pca.cpp) 9 | 10 | if(VTK_LIBRARIES) 11 | target_link_libraries(pca ${VTK_LIBRARIES}) 12 | else() 13 | target_link_libraries(pca vtkHybrid vtkWidgets) 14 | endif() -------------------------------------------------------------------------------- /多维医学图像处理与可视化/sphereKdTree/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | PROJECT(sphereKdTree) 4 | 5 | find_package(VTK REQUIRED) 6 | include(${VTK_USE_FILE}) 7 | 8 | add_executable(sphereKdTree sphereKdTree.cpp) 9 | 10 | if(VTK_LIBRARIES) 11 | target_link_libraries(sphereKdTree ${VTK_LIBRARIES}) 12 | else() 13 | target_link_libraries(sphereKdTree vtkHybrid vtkWidgets) 14 | endif() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 上海交通大学生物医学工程学院医学图像处理方向研究生课程期末大作业合集 2 | 3 | 一段聊胜于无的简单的说明。 4 | 5 | ## 多维医学图像处理与可视化 6 | 个人认为这门课改名“VTK基础编程”更合适,这门课期末作业的内容每学期都会变。一般情况下,参考VTK官方提供的Examples,根据作业要求略微修改一下就可以完成作业。 7 | 8 | ## 高级生物医学图像处理 9 | 基于Qt5.5、VTK、和ITK,在Windows上用CPP实现了一个简单的图像浏览器和一些基本的图像处理操作。 10 | 11 | ## 一点微小的提醒 12 | 1. 项目代码是期末临时赶工的结果,所以相关库文件的路径都是根据自己PC当时的配置直接写在CmakeLists.txt里的。如果要自己编译,在用CMake生成solution文件之前要根据实际情况进行修改。 13 | 2. 相关代码仅供参考,请勿直接Copy。 -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/histogramdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef HISTOGRAMDIALOG_H 2 | #define HISTOGRAMDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "itkImage.h" 9 | 10 | typedef itk::Image ImageType; 11 | typedef itk::Image ImageTypeProcess; 12 | 13 | class histogramDialog : public QMainWindow 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit histogramDialog(ImageType::Pointer itkImg, QWidget *parent = 0); 18 | 19 | private: 20 | 21 | signals: 22 | 23 | public slots: 24 | 25 | 26 | }; 27 | 28 | #endif // HISTOGRAMDIALOG_H 29 | -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | MainWindow 3 | 4 | 5 | 6 | 0 7 | 0 8 | 400 9 | 300 10 | 11 | 12 | 13 | MainWindow 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "itkImage.h" 9 | #include "histogramdialog.h" 10 | 11 | namespace Ui { 12 | class MainWindow; 13 | } 14 | 15 | typedef itk::Image ImageType; 16 | typedef itk::Image ImageTypeProcess; 17 | 18 | class MainWindow : public QMainWindow 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit MainWindow(QWidget *parent = 0); 24 | ~MainWindow(); 25 | QSplitter* splitter; 26 | QWidget *mainWidget; 27 | QWidget *leftWidget; 28 | QWidget *rightWidget; 29 | QVBoxLayout *lLayout; 30 | QVBoxLayout *rLayout; 31 | 32 | public slots: 33 | void showHistogram(ImageType::Pointer itkImg); 34 | 35 | private: 36 | Ui::MainWindow *ui; 37 | }; 38 | 39 | #endif // MAINWINDOW_H 40 | -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.11) 2 | 3 | project(medImgViewer) 4 | 5 | # Find includes in corresponding build directories 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | # Instruct CMake to run moc automatically when needed. 8 | set(CMAKE_AUTOMOC ON) 9 | 10 | 11 | # Find the QtWidgets library 12 | set (CMAKE_PREFIX_PATH "C:\\Qt\\Qt5.5.0\\5.5\\msvc2013_64\\") 13 | find_package(Qt5Widgets REQUIRED) 14 | 15 | # Tell CMake to create the medImgViewer executable 16 | 17 | file(GLOB SRC_FILES "./*.cpp") 18 | file(GLOB HEAD_FILES "./*.h") 19 | file(GLOB UI_FILES "./*.ui") 20 | qt5_wrap_ui(WRAP_FILES ${UI_FILES}) 21 | qt5_wrap_cpp(MOCSrcs ${QT_WRAP}) 22 | 23 | set(ITK_DIR "E:/ITK-Box/ITK-Build") 24 | set(VTK_DIR "E:/VTK-Box/VTK-Build") 25 | list(APPEND env{path} "E:/VTK-Box/VTK-Build/bin/Debug") 26 | find_package(ITK REQUIRED) 27 | include(${ITK_USE_FILE}) 28 | 29 | if (ITKVtkGlue_LOADED) 30 | find_package(VTK REQUIRED) 31 | include(${VTK_USE_FILE}) 32 | else() 33 | find_package(ItkVtkGlue REQUIRED) 34 | include(${ItkVtkGlue_USE_FILE}) 35 | set(Glue ItkVtkGlue) 36 | endif() 37 | 38 | add_executable(medImgViewer WIN32 ${SRC_FILES} ${HEAD_FILES} ${WRAP_FILES} ${MOCSrcs}) 39 | 40 | # Use the ITK VTK and Widgets module from Qt 5. 41 | target_link_libraries(medImgViewer Qt5::Widgets ${Glue} ${ITK_LIBRARIES} ${VTK_LIBRARIES}) -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include 4 | #include 5 | #include 6 | 7 | MainWindow::MainWindow(QWidget *parent) : 8 | QMainWindow(parent), 9 | ui(new Ui::MainWindow) 10 | { 11 | ui->setupUi(this); 12 | 13 | this->setMinimumSize(800, 500); 14 | 15 | this->mainWidget = new QWidget(this); 16 | this->setCentralWidget(mainWidget); 17 | this->mainWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 18 | QHBoxLayout* layout = new QHBoxLayout(this); 19 | splitter = new QSplitter(Qt::Horizontal, this->mainWidget); 20 | splitter->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 21 | splitter->show(); 22 | layout->addWidget(splitter); 23 | 24 | this->leftWidget = new QWidget(splitter); 25 | this->rightWidget = new QWidget(splitter); 26 | this->leftWidget->setGeometry(0,0,300,500); 27 | this->rightWidget->setGeometry(300,0,500,500); 28 | this->splitter->childrenCollapsible(); 29 | //this->leftWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 30 | //this->rightWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 31 | 32 | mainWidget->setLayout(layout); 33 | this->update(); 34 | 35 | } 36 | 37 | MainWindow::~MainWindow() 38 | { 39 | delete ui; 40 | } 41 | 42 | void MainWindow::showHistogram(ImageType::Pointer itkImg) 43 | { 44 | histogramDialog *hisDialog = new histogramDialog(itkImg); 45 | hisDialog->show(); 46 | } -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/tabboard.cpp: -------------------------------------------------------------------------------- 1 | #include "tabboard.h" 2 | #include "QIntValidator" 3 | 4 | tabBoard::tabBoard(QWidget *parent) : QTabWidget(parent) 5 | { 6 | lineEdit->setValidator(new QIntValidator(0, 255, this)); 7 | slider->setMinimum(0); 8 | slider->setMaximum(255); 9 | slider->setValue(50); 10 | connect(this->slider, SIGNAL(valueChanged(int)), this, SLOT(setLineEditValue(int))); 11 | connect(this->lineEdit, SIGNAL(textChanged(QString)), this, SLOT(setSiderValue(QString))); 12 | this->widgetLayout->addWidget(lineEdit); 13 | this->widgetLayout->addWidget(slider); 14 | this->container->setLayout(this->widgetLayout); 15 | this->pageLayout1->addWidget(this->container); 16 | this->pageLayout1->addWidget(histogramButton); 17 | this->pageLayout1->addWidget(thresholdButton1); 18 | this->pageLayout1->addWidget(thresholdButton2); 19 | this->pageLayout1->addWidget(thresholdButton3); 20 | this->page1->setLayout(this->pageLayout1); 21 | 22 | this->pageLayout2->addWidget(reloadButton); 23 | this->pageLayout2->addWidget(edgeButton); 24 | this->pageLayout2->addWidget(denoiseButton); 25 | this->page2->setLayout(this->pageLayout2); 26 | 27 | this->pageLayout3->addWidget(erodeButton); 28 | this->pageLayout3->addWidget(dilateButton); 29 | this->pageLayout3->addWidget(openButton); 30 | this->pageLayout3->addWidget(closeButton); 31 | this->page3->setLayout(this->pageLayout3); 32 | 33 | this->pageLayout4->addWidget(binaryDTButton); 34 | this->pageLayout4->addWidget(skeletonButton); 35 | this->pageLayout4->addWidget(restorteButton); 36 | this->pageLayout4->addWidget(morEdgeButton); 37 | this->pageLayout4->addWidget(morGradientButton); 38 | this->pageLayout4->addWidget(condDilateButton); 39 | this->pageLayout4->addWidget(grayRestorateButton); 40 | this->page4->setLayout(this->pageLayout4); 41 | 42 | this->addTab(page1, "Page1"); 43 | this->addTab(page2, "Page2"); 44 | this->addTab(page3, "Page3"); 45 | this->addTab(page4, "Page4"); 46 | 47 | this->show(); 48 | } 49 | 50 | void tabBoard::setLineEditValue(int value) 51 | { 52 | QString str = QString("%1").arg(value); 53 | this->lineEdit->setText(str); 54 | } 55 | 56 | void tabBoard::setSiderValue(QString text) 57 | { 58 | int value = text.toInt(); 59 | this->slider->setValue(value); 60 | } -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/tabboard.h: -------------------------------------------------------------------------------- 1 | #ifndef TABBOARD_H 2 | #define TABBOARD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class tabBoard : public QTabWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit tabBoard(QWidget *parent = 0); 16 | QWidget *page1 = new QWidget(); 17 | QVBoxLayout *pageLayout1 = new QVBoxLayout(); 18 | QHBoxLayout *widgetLayout = new QHBoxLayout(); 19 | QWidget *container = new QWidget(); 20 | QLineEdit *lineEdit = new QLineEdit("50"); 21 | QSlider *slider = new QSlider(Qt::Horizontal); 22 | QPushButton *histogramButton = new QPushButton("Show Grayscale Histogram"); 23 | QPushButton *thresholdButton1 = new QPushButton("Binary Threshold"); 24 | QPushButton *thresholdButton2 = new QPushButton("Otsu"); 25 | QPushButton *thresholdButton3 = new QPushButton("Entropy"); 26 | 27 | QWidget *page2 = new QWidget(); 28 | QVBoxLayout *pageLayout2 = new QVBoxLayout(); 29 | QPushButton *reloadButton = new QPushButton("Reload"); 30 | QPushButton *edgeButton = new QPushButton("Edge Detection"); 31 | QPushButton *denoiseButton = new QPushButton("Denoising"); 32 | 33 | QWidget *page3 = new QWidget(); 34 | QVBoxLayout *pageLayout3 = new QVBoxLayout(); 35 | QPushButton *erodeButton = new QPushButton("Erosion"); 36 | QPushButton *dilateButton = new QPushButton("Dilation"); 37 | QPushButton *openButton = new QPushButton("Opening"); 38 | QPushButton *closeButton = new QPushButton("Closing"); 39 | 40 | QWidget *page4 = new QWidget(); 41 | QVBoxLayout *pageLayout4 = new QVBoxLayout(); 42 | QPushButton *binaryDTButton = new QPushButton("Distance Transform"); 43 | QPushButton *skeletonButton = new QPushButton("Skeletonize"); 44 | QPushButton *restorteButton = new QPushButton("Binary Restoration"); 45 | QPushButton *morEdgeButton = new QPushButton("Edge Detection"); 46 | QPushButton *morGradientButton = new QPushButton("Morphological Gradient"); 47 | QPushButton *condDilateButton = new QPushButton("Conditional Dilation "); 48 | QPushButton *grayRestorateButton = new QPushButton("Grayscale Restoration"); 49 | 50 | signals: 51 | 52 | public slots : 53 | void setLineEditValue(int value); 54 | void setSiderValue(QString text); 55 | 56 | }; 57 | 58 | #endif // TABBOARD_H -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/viewer.h: -------------------------------------------------------------------------------- 1 | #ifndef VIEWER_H 2 | #define VIEWER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "itkImage.h" 16 | 17 | typedef itk::Image ImageType; 18 | typedef itk::Image ImageTypeProcess; 19 | 20 | class viewer : public QLabel 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | explicit viewer(QWidget *parent = 0); 26 | ~viewer(); 27 | QImage *img = new QImage(); 28 | ImageType::Pointer itkImg; 29 | ImageTypeProcess::Pointer itkImgProcess; 30 | ImageType::Pointer itkDTM = ImageType::New(); 31 | QPixmap pixMap; 32 | int processType; 33 | bool haveDTM = false; 34 | 35 | void loadImg(QImage *sourceImg); 36 | void setProcessType(int processType); 37 | void viewer::resizeEvent(QResizeEvent *event); 38 | void viewer::dragEnterEvent(QDragEnterEvent *event); 39 | void viewer::dropEvent(QDropEvent *event); 40 | 41 | void refreshImg(QImage *newImg); 42 | 43 | public slots: 44 | void reloadImg(QImage *newImg); 45 | void sendReload(); 46 | void thresholding(); 47 | void thresholding(int thresholdValue); 48 | void edgeDetect(); 49 | void denosing(); 50 | void erode(); 51 | void dilate(); 52 | void openOpr(); 53 | void closeOpr(); 54 | void binaryDistanceTrans(); 55 | void skeletonize(); 56 | void skRestorate(); 57 | void morphEdge(); 58 | void sendMask(); 59 | void sendItk(); 60 | void maskDilate(ImageType::Pointer itkMaskImg, ImageTypeProcess::Pointer itkMaskImgProcess); 61 | 62 | signals: 63 | void imgChange(QImage *newImg); 64 | void reloadInfo(QImage *newImg); 65 | void maskInfo(ImageType::Pointer itkMaskImg, ImageTypeProcess::Pointer itkMaskImgProcess); 66 | void itkInfo(ImageType::Pointer itkImg); 67 | 68 | private: 69 | ImageType::Pointer qImg2itkImg(QImage *qImg); 70 | QImage itk2qImg(ImageType::Pointer itkImg); 71 | ImageTypeProcess::Pointer itkShow2process(ImageType::Pointer itkImg); 72 | ImageType::Pointer itkProcess2show(ImageTypeProcess::Pointer itkImgProcess); 73 | bool viewer::isThreshold(ImageType::Pointer itkImg); 74 | bool viewer::isImgEmpty(ImageType::Pointer itkImg); 75 | 76 | }; 77 | 78 | #endif // VIEWER_H 79 | -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/histogramdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "histogramdialog.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | histogramDialog::histogramDialog(ImageType::Pointer itkImg, QWidget *parent) : QMainWindow(parent) 21 | { 22 | typedef itk::ImageToVTKImageFilter ConnectorType; 23 | ConnectorType::Pointer connector = ConnectorType::New(); 24 | connector->SetInput(itkImg); 25 | connector->Update(); 26 | 27 | int numComponents = connector->GetOutput()->GetNumberOfScalarComponents(); 28 | 29 | vtkSmartPointer plot = 30 | vtkSmartPointer::New(); 31 | plot->ExchangeAxesOff(); 32 | plot->SetLabelFormat("%g"); 33 | plot->SetXTitle("Intensity"); 34 | plot->SetYTitle("Frequency"); 35 | plot->SetXValuesToValue(); 36 | 37 | double xmax = 0.; 38 | double ymax = 0.; 39 | 40 | double colors[3][3] = { 41 | { 1, 0, 0 }, 42 | { 0, 1, 0 }, 43 | { 0, 0, 1 } 44 | }; 45 | 46 | const char* labels[3] = { "Red", "Green", "Blue" }; 47 | for (int i = 0; i < numComponents; ++i) 48 | { 49 | vtkSmartPointer extract = 50 | vtkSmartPointer::New(); 51 | extract->SetInputData(connector->GetOutput()); 52 | extract->SetComponents(i); 53 | extract->Update(); 54 | double range[2]; 55 | extract->GetOutput()->GetScalarRange(range); 56 | vtkSmartPointer histogram = 57 | vtkSmartPointer::New(); 58 | histogram->SetInputConnection(extract->GetOutputPort()); 59 | histogram->SetComponentExtent( 60 | 0, 61 | static_cast(range[1]) - static_cast(range[0]) - 1, 0, 0, 0, 0); 62 | histogram->SetComponentOrigin(range[0], 0, 0); 63 | histogram->SetComponentSpacing(1, 0, 0); 64 | int ignoreZero = 0; 65 | histogram->SetIgnoreZero(ignoreZero); 66 | histogram->Update(); 67 | if (range[1] > xmax) 68 | { 69 | xmax = range[1]; 70 | } 71 | if (histogram->GetOutput()->GetScalarRange()[1] > ymax) 72 | { 73 | ymax = histogram->GetOutput()->GetScalarRange()[1]; 74 | } 75 | plot->AddDataSetInputConnection(histogram->GetOutputPort()); 76 | 77 | if (numComponents > 1) 78 | { 79 | plot->SetPlotColor(i, colors[i]); 80 | plot->SetPlotLabel(i, labels[i]); 81 | plot->LegendOn(); 82 | } 83 | } 84 | 85 | 86 | 87 | plot->SetXRange(0, xmax); 88 | plot->SetYRange(0, ymax); 89 | 90 | vtkSmartPointer histRenderer = 91 | vtkSmartPointer::New(); 92 | histRenderer->AddActor(plot); 93 | 94 | this->resize(600, 600); 95 | QVTKWidget *widget = new QVTKWidget; 96 | 97 | this->setCentralWidget(widget); 98 | 99 | widget->GetRenderWindow()->AddRenderer(histRenderer); 100 | widget->show(); 101 | this->show(); 102 | } -------------------------------------------------------------------------------- /多维医学图像处理与可视化/sphereKdTree/sphereKdTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | int main() 20 | { 21 | 22 | std::cout << "please input the coordinate of a point (e.g. 1 1 1):\n"; 23 | int xSearch, ySearch, zSearch; 24 | std::cin >> xSearch >> ySearch >> zSearch; 25 | double pointSearch[3] = {xSearch, ySearch, zSearch}; 26 | // Create a sphere 27 | vtkSmartPointer sphereSource[50]; 28 | vtkSmartPointer points = vtkSmartPointer::New(); 29 | int spColor[50];//set color of the spheres. red, green and blue is represented by 0, 1, 2 seperately. 30 | for (int i = 0; i < 50; i++) 31 | { 32 | double xSp = rand() % 100; 33 | double ySp = rand() % 100; 34 | double zSp = rand() % 100; 35 | sphereSource[i] = vtkSmartPointer::New(); 36 | sphereSource[i]->SetCenter(xSp, ySp, zSp); 37 | double rSp = rand() % 6 + 5; 38 | sphereSource[i]->SetRadius(rSp); 39 | double centerSp[3] = { xSp, ySp, zSp }; 40 | points->InsertNextPoint(centerSp); 41 | spColor[i] = rand() % 3; 42 | } 43 | 44 | //find the closest point to input point 45 | vtkSmartPointer pointTree = vtkSmartPointer::New(); 46 | pointTree->BuildLocatorFromPoints(points); 47 | vtkSmartPointer result =vtkSmartPointer::New(); 48 | pointTree->FindClosestNPoints(1, pointSearch, result); 49 | 50 | vtkIdType resultSearchInd = result->GetId(0); 51 | double resultSearch[3]; 52 | points->GetPoint(resultSearchInd, resultSearch); 53 | std::cout << "Closest point to (" << pointSearch[0] << ", " << pointSearch[1] << ", " << pointSearch[2] << ") is points No." 54 | << resultSearchInd << ". And its coordinate is (" << resultSearch[0] << ", " << resultSearch[1] << ", " << resultSearch[2] << ").\n"; 55 | std::cout << "The radius is " << sphereSource[resultSearchInd]->GetRadius() << ". And its color is "; 56 | switch (spColor[resultSearchInd]) 57 | { 58 | case 0: 59 | std::cout << "red."; 60 | break; 61 | case 1: 62 | std::cout << "green."; 63 | break; 64 | case 2: 65 | std::cout << "blue."; 66 | break; 67 | default: 68 | std::cout << "error while setting color for spheres."; 69 | break; 70 | } 71 | 72 | //show items on the screen. 73 | vtkSmartPointer mapper[50]; 74 | vtkSmartPointer actor[50]; 75 | vtkSmartPointer renderer = 76 | vtkSmartPointer::New(); 77 | vtkSmartPointer renderWindow = 78 | vtkSmartPointer::New(); 79 | renderWindow->AddRenderer(renderer); 80 | vtkSmartPointer renderWindowInteractor = 81 | vtkSmartPointer::New(); 82 | renderWindowInteractor->SetRenderWindow(renderWindow); 83 | 84 | //generate a 100*100*100 cubic space to show the space which contain all the centers of the spheres. 85 | vtkSmartPointer cubeSource = 86 | vtkSmartPointer::New(); 87 | cubeSource->SetBounds(0,99,0,99,0,99); 88 | cubeSource->Update(); 89 | 90 | // Create a mapper and actor. 91 | vtkSmartPointer spaceMapper = 92 | vtkSmartPointer::New(); 93 | spaceMapper->SetInputConnection(cubeSource->GetOutputPort()); 94 | 95 | vtkSmartPointer spaceActor = 96 | vtkSmartPointer::New(); 97 | spaceActor->SetMapper(spaceMapper); 98 | spaceActor->GetProperty()->SetOpacity(0.1); 99 | renderer->AddActor(spaceActor); 100 | 101 | //add spheres on the window. 102 | for (int i = 0; i < 50; i++) 103 | { 104 | mapper[i] = vtkSmartPointer::New(); 105 | mapper[i]->SetInputConnection(sphereSource[i]->GetOutputPort()); 106 | actor[i] = vtkSmartPointer::New(); 107 | actor[i]->SetMapper(mapper[i]); 108 | switch (spColor[i]) 109 | { 110 | case 0: 111 | actor[i]->GetProperty()->SetColor(1, 0, 0); 112 | break; 113 | case 1: 114 | actor[i]->GetProperty()->SetColor(0, 1, 0); 115 | break; 116 | case 2: 117 | actor[i]->GetProperty()->SetColor(0, 0, 1); 118 | break; 119 | default: 120 | std::cout << "error while setting color for spheres."; 121 | return EXIT_FAILURE; 122 | break; 123 | } 124 | renderer->AddActor(actor[i]); 125 | } 126 | 127 | renderer->SetBackground(0.5, 0.5, 0.5); 128 | renderWindow->Render(); 129 | renderWindowInteractor->Start(); 130 | 131 | return EXIT_SUCCESS; 132 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | # ========================= 255 | # Operating System Files 256 | # ========================= 257 | 258 | # OSX 259 | # ========================= 260 | 261 | .DS_Store 262 | .AppleDouble 263 | .LSOverride 264 | 265 | # Thumbnails 266 | ._* 267 | 268 | # Files that might appear in the root of a volume 269 | .DocumentRevisions-V100 270 | .fseventsd 271 | .Spotlight-V100 272 | .TemporaryItems 273 | .Trashes 274 | .VolumeIcon.icns 275 | 276 | # Directories potentially created on remote AFP share 277 | .AppleDB 278 | .AppleDesktop 279 | Network Trash Folder 280 | Temporary Items 281 | .apdisk 282 | 283 | # Windows 284 | # ========================= 285 | 286 | # Windows image file caches 287 | Thumbs.db 288 | ehthumbs.db 289 | 290 | # Folder config file 291 | Desktop.ini 292 | 293 | # Recycle Bin used on file shares 294 | $RECYCLE.BIN/ 295 | 296 | # Windows Installer files 297 | *.cab 298 | *.msi 299 | *.msm 300 | *.msp 301 | 302 | # Windows shortcuts 303 | *.lnk 304 | -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "viewer.h" 3 | #include "tabboard.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | QApplication app(argc, argv); 17 | QFont font("helianthus_lu", 12); 18 | app.setFont(font); 19 | MainWindow w; 20 | w.setWindowTitle("Medical Image Viewer"); 21 | 22 | //Specify widgets of the left part. 23 | tabBoard *tabPanel = new tabBoard(); 24 | tabPanel->setFixedWidth(300); 25 | tabPanel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 26 | 27 | w.lLayout = new QVBoxLayout; 28 | w.lLayout->addWidget(tabPanel); 29 | w.leftWidget->setLayout(w.lLayout); 30 | 31 | //Specify layout of the right parrts. 32 | QWidget *subWidget1 = new QWidget(w.rightWidget); 33 | QHBoxLayout *subLayout1 = new QHBoxLayout; 34 | QWidget *subWidget2 = new QWidget(w.rightWidget); 35 | QHBoxLayout *subLayout2 = new QHBoxLayout; 36 | w.rLayout = new QVBoxLayout; 37 | w.rLayout->addWidget(subWidget1); 38 | w.rLayout->addWidget(subWidget2); 39 | w.rightWidget->setLayout(w.rLayout); 40 | 41 | //Specify 4 subwindows of this app. 42 | QImage sourceImg("E:\\Code\\medImgViewer\\medImgViewer-qt5\\origin.jpg"); 43 | QImage image = sourceImg.convertToFormat(QImage::Format::Format_Grayscale8); 44 | viewer* originViewer = new viewer(subWidget1); 45 | originViewer->setAlignment(Qt::AlignCenter); 46 | //originViewer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 47 | originViewer->setFrameShape(QFrame::Box); 48 | originViewer->setAcceptDrops(true); 49 | originViewer->loadImg(&image); 50 | 51 | viewer* viewer1 = new viewer(subWidget1); 52 | viewer1->setAlignment(Qt::AlignCenter); 53 | //viewer1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 54 | viewer1->setFrameShape(QFrame::Box); 55 | viewer1->loadImg(&image); 56 | viewer1->setProcessType(0); 57 | 58 | viewer* viewer2 = new viewer(subWidget2); 59 | viewer2->setAlignment(Qt::AlignCenter); 60 | //viewer2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 61 | viewer2->setFrameShape(QFrame::Box); 62 | viewer2->loadImg(&image); 63 | viewer2->setProcessType(1); 64 | 65 | viewer* viewer3 = new viewer(subWidget2); 66 | viewer3->setAlignment(Qt::AlignCenter); 67 | //viewer3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 68 | viewer3->setFrameShape(QFrame::Box); 69 | viewer3->loadImg(&image); 70 | viewer3->setProcessType(2); 71 | 72 | subLayout1->addWidget(originViewer); 73 | subLayout1->addWidget(viewer1); 74 | subLayout2->addWidget(viewer2); 75 | subLayout2->addWidget(viewer3); 76 | subWidget1->setLayout(subLayout1); 77 | subWidget2->setLayout(subLayout2); 78 | 79 | //splitter seeting. 80 | w.splitter->setStretchFactor(0, 0); 81 | w.splitter->setStretchFactor(1, 1); 82 | w.splitter->setOpaqueResize(false); 83 | w.splitter->update(); 84 | w.splitter->show(); 85 | 86 | //specify signal and slot connection. 87 | //load new images 88 | QObject::connect(originViewer, SIGNAL(imgChange(QImage*)), viewer1, 89 | SLOT(reloadImg(QImage*))); 90 | QObject::connect(originViewer, SIGNAL(imgChange(QImage*)), viewer2, 91 | SLOT(reloadImg(QImage*))); 92 | QObject::connect(originViewer, SIGNAL(imgChange(QImage*)), viewer3, 93 | SLOT(reloadImg(QImage*))); 94 | //show histogram 95 | QObject::connect(tabPanel->histogramButton, SIGNAL(clicked()), originViewer, 96 | SLOT(sendItk())); 97 | QObject::connect(originViewer, SIGNAL(itkInfo(ImageType::Pointer)), &w, 98 | SLOT(showHistogram(ImageType::Pointer))); 99 | //thresholding 100 | QObject::connect(tabPanel->slider, SIGNAL(valueChanged(int)), viewer1, 101 | SLOT(thresholding(int))); 102 | QObject::connect(tabPanel->thresholdButton1, SIGNAL(clicked()), viewer1, 103 | SLOT(thresholding())); 104 | QObject::connect(tabPanel->thresholdButton2, SIGNAL(clicked()), viewer2, 105 | SLOT(thresholding())); 106 | QObject::connect(tabPanel->thresholdButton3, SIGNAL(clicked()), viewer3, 107 | SLOT(thresholding())); 108 | //reload image 109 | QObject::connect(tabPanel->reloadButton, SIGNAL(clicked()), originViewer, 110 | SLOT(sendReload())); 111 | QObject::connect(originViewer, SIGNAL(reloadInfo(QImage*)), viewer1, 112 | SLOT(reloadImg(QImage*))); 113 | QObject::connect(originViewer, SIGNAL(reloadInfo(QImage*)), viewer2, 114 | SLOT(reloadImg(QImage*))); 115 | QObject::connect(originViewer, SIGNAL(reloadInfo(QImage*)), viewer3, 116 | SLOT(reloadImg(QImage*))); 117 | //convolution 118 | QObject::connect(tabPanel->edgeButton, SIGNAL(clicked()), viewer1, 119 | SLOT(edgeDetect())); 120 | QObject::connect(tabPanel->edgeButton, SIGNAL(clicked()), viewer2, 121 | SLOT(edgeDetect())); 122 | QObject::connect(tabPanel->edgeButton, SIGNAL(clicked()), viewer3, 123 | SLOT(edgeDetect())); 124 | QObject::connect(tabPanel->denoiseButton, SIGNAL(clicked()), viewer2, 125 | SLOT(denosing())); 126 | QObject::connect(tabPanel->denoiseButton, SIGNAL(clicked()), viewer3, 127 | SLOT(denosing())); 128 | //erode 129 | QObject::connect(tabPanel->erodeButton, SIGNAL(clicked()), viewer1, 130 | SLOT(erode())); 131 | QObject::connect(tabPanel->erodeButton, SIGNAL(clicked()), viewer2, 132 | SLOT(erode())); 133 | QObject::connect(tabPanel->erodeButton, SIGNAL(clicked()), viewer3, 134 | SLOT(erode())); 135 | //dilate 136 | QObject::connect(tabPanel->dilateButton, SIGNAL(clicked()), viewer1, 137 | SLOT(dilate())); 138 | QObject::connect(tabPanel->dilateButton, SIGNAL(clicked()), viewer2, 139 | SLOT(dilate())); 140 | QObject::connect(tabPanel->dilateButton, SIGNAL(clicked()), viewer3, 141 | SLOT(dilate())); 142 | //open 143 | QObject::connect(tabPanel->openButton, SIGNAL(clicked()), viewer1, 144 | SLOT(openOpr())); 145 | QObject::connect(tabPanel->openButton, SIGNAL(clicked()), viewer2, 146 | SLOT(openOpr())); 147 | QObject::connect(tabPanel->openButton, SIGNAL(clicked()), viewer3, 148 | SLOT(openOpr())); 149 | //close 150 | QObject::connect(tabPanel->closeButton, SIGNAL(clicked()), viewer1, 151 | SLOT(closeOpr())); 152 | QObject::connect(tabPanel->closeButton, SIGNAL(clicked()), viewer2, 153 | SLOT(closeOpr())); 154 | QObject::connect(tabPanel->closeButton, SIGNAL(clicked()), viewer3, 155 | SLOT(closeOpr())); 156 | //Binary mophology 157 | QObject::connect(tabPanel->binaryDTButton, SIGNAL(clicked()), viewer1, 158 | SLOT(binaryDistanceTrans())); 159 | QObject::connect(tabPanel->binaryDTButton, SIGNAL(clicked()), viewer2, 160 | SLOT(binaryDistanceTrans())); 161 | QObject::connect(tabPanel->binaryDTButton, SIGNAL(clicked()), viewer3, 162 | SLOT(binaryDistanceTrans())); 163 | QObject::connect(tabPanel->skeletonButton, SIGNAL(clicked()), viewer1, 164 | SLOT(skeletonize())); 165 | QObject::connect(tabPanel->skeletonButton, SIGNAL(clicked()), viewer2, 166 | SLOT(skeletonize())); 167 | QObject::connect(tabPanel->skeletonButton, SIGNAL(clicked()), viewer3, 168 | SLOT(skeletonize())); 169 | QObject::connect(tabPanel->restorteButton, SIGNAL(clicked()), viewer1, 170 | SLOT(skRestorate())); 171 | QObject::connect(tabPanel->restorteButton, SIGNAL(clicked()), viewer2, 172 | SLOT(skRestorate())); 173 | QObject::connect(tabPanel->restorteButton, SIGNAL(clicked()), viewer3, 174 | SLOT(skRestorate())); 175 | //Complex morphology 176 | QObject::connect(tabPanel->morEdgeButton, SIGNAL(clicked()), viewer1, 177 | SLOT(morphEdge())); 178 | QObject::connect(tabPanel->morEdgeButton, SIGNAL(clicked()), viewer2, 179 | SLOT(morphEdge())); 180 | QObject::connect(tabPanel->morEdgeButton, SIGNAL(clicked()), viewer3, 181 | SLOT(morphEdge())); 182 | QObject::connect(tabPanel->morGradientButton, SIGNAL(clicked()), viewer1, 183 | SLOT(morphEdge())); 184 | QObject::connect(tabPanel->morGradientButton, SIGNAL(clicked()), viewer2, 185 | SLOT(morphEdge())); 186 | QObject::connect(tabPanel->morGradientButton, SIGNAL(clicked()), viewer3, 187 | SLOT(morphEdge())); 188 | //Reconstraction 189 | QObject::connect(tabPanel->condDilateButton, SIGNAL(clicked()), viewer1, 190 | SLOT(sendMask())); 191 | QObject::connect(tabPanel->grayRestorateButton, SIGNAL(clicked()), originViewer, 192 | SLOT(sendMask())); 193 | QObject::connect(viewer1, SIGNAL(maskInfo(ImageType::Pointer, ImageTypeProcess::Pointer)), viewer2, 194 | SLOT(maskDilate(ImageType::Pointer, ImageTypeProcess::Pointer))); 195 | QObject::connect(viewer1, SIGNAL(maskInfo(ImageType::Pointer, ImageTypeProcess::Pointer)), viewer3, 196 | SLOT(maskDilate(ImageType::Pointer, ImageTypeProcess::Pointer))); 197 | QObject::connect(originViewer, SIGNAL(maskInfo(ImageType::Pointer, ImageTypeProcess::Pointer)), viewer2, 198 | SLOT(maskDilate(ImageType::Pointer, ImageTypeProcess::Pointer))); 199 | QObject::connect(originViewer, SIGNAL(maskInfo(ImageType::Pointer, ImageTypeProcess::Pointer)), viewer3, 200 | SLOT(maskDilate(ImageType::Pointer, ImageTypeProcess::Pointer))); 201 | 202 | w.show(); 203 | return app.exec(); 204 | } 205 | -------------------------------------------------------------------------------- /多维医学图像处理与可视化/pca/pca.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | void clacBinaryImageCenter(vtkSmartPointer inputImage, double result[3]); 34 | vtkSmartPointer binaryImagePCA(vtkSmartPointer inputImage); 35 | void getEigenInfo(vtkSmartPointer pcaStatistics, double eigenvalueVect[3], int indexEig[3], double eigenvectorVect[3][3]); 36 | 37 | int main() 38 | { 39 | //for there may be overlapping of different spheres, some error will occur if we apply PCA to poly data directly. 40 | //in order to eliminate this effect, a convert from poly data into binary image data is necessay. 41 | //and there are also some spheres of which centers are at the boundary of the 100*100*100 space, some part of them may not be covered by the 100*100*100 space totally. 42 | //in case of that, we extend the space to 120*120*120. 43 | std::srand((unsigned)time(NULL)); 44 | //set black image, which will be set to. 45 | vtkSmartPointer blackImage = vtkSmartPointer::New(); 46 | double spacing[3]; // desired volume spacing 47 | spacing[0] = 1; 48 | spacing[1] = 1; 49 | spacing[2] = 1; 50 | blackImage->SetSpacing(spacing); 51 | 52 | // set dimensions 53 | //if there are some spheres of which centers are at the boundary of the 100*100*100 space, 54 | //a part of them may not be covered by the 100*100*100 space. 55 | int dim[3] = { 120, 120, 120 }; 56 | blackImage->SetDimensions(dim); 57 | 58 | double origin[3]; 59 | origin[0] = 0; 60 | origin[1] = 0; 61 | origin[2] = 0; 62 | blackImage->SetOrigin(origin); 63 | 64 | #if VTK_MAJOR_VERSION <= 5 65 | blackImage->SetScalarTypeToUnsignedChar(); 66 | blackImage->AllocateScalars(); 67 | #else 68 | blackImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1); 69 | #endif 70 | 71 | // fill the image with background voxels: 72 | unsigned char inval = 1; 73 | unsigned char outval = 0; 74 | vtkIdType count = blackImage->GetNumberOfPoints(); 75 | for (vtkIdType i = 0; i < count; ++i) 76 | { 77 | blackImage->GetPointData()->GetScalars()->SetTuple1(i, outval); 78 | } 79 | 80 | // create spheres 81 | vtkSmartPointer sphereSource[50]; 82 | vtkSmartPointer points = vtkSmartPointer::New(); 83 | int spColor[50];//set color of the spheres. red, green and blue is represented by 0, 1, 2 seperately. 84 | for (int i = 0; i < 50; i++) 85 | { 86 | /*if there are some spheres of which centers are at the boundary of the 100*100*100 space, 87 | a part of them may not be covered by the 100*100*100 space. in case of that, we extend the space to 120*120*120, 88 | and make some related modification on the coordinate for new space. */ 89 | double xSp = std::rand() % 100 + 10; 90 | double ySp = std::rand() % 100 + 10; 91 | double zSp = std::rand() % 100 + 10; 92 | sphereSource[i] = vtkSmartPointer::New(); 93 | sphereSource[i]->SetCenter(xSp, ySp, zSp); 94 | double rSp = std::rand() % 6 + 5; 95 | sphereSource[i]->SetRadius(rSp); 96 | double centerSp[3] = { xSp, ySp, zSp }; 97 | points->InsertNextPoint(centerSp); 98 | spColor[i] = std::rand() % 3; 99 | sphereSource[i]->Update(); 100 | } 101 | 102 | //use an image stencil iteratively to convert sphere poly data into image data. 103 | vtkSmartPointer pd = vtkSmartPointer::New(); 104 | vtkSmartPointer pol2stenc = vtkSmartPointer::New(); 105 | vtkSmartPointer imgstenc = vtkSmartPointer::New(); 106 | 107 | //add the rest of spheres in the image stencil. 108 | for (int i = 1; i < 50; i++) 109 | { 110 | pd = vtkSmartPointer::New(); 111 | pd = sphereSource[i]->GetOutput(); 112 | 113 | #if VTK_MAJOR_VERSION <= 5 114 | pol2stenc->SetInput(pd); 115 | #else 116 | pol2stenc->SetInputData(pd); 117 | #endif 118 | pol2stenc->SetOutputOrigin(origin); 119 | pol2stenc->SetOutputSpacing(spacing); 120 | pol2stenc->SetOutputWholeExtent(blackImage->GetExtent()); 121 | pol2stenc->Update(); 122 | 123 | #if VTK_MAJOR_VERSION <= 5 124 | imgstenc->SetInput(blackImage); 125 | imgstenc->SetStencil(pol2stenc->GetOutput()); 126 | #else 127 | imgstenc->SetInputData(blackImage); 128 | imgstenc->SetStencilConnection(pol2stenc->GetOutputPort()); 129 | #endif 130 | imgstenc->ReverseStencilOn(); 131 | imgstenc->SetBackgroundValue(inval); 132 | imgstenc->Update(); 133 | blackImage = imgstenc->GetOutput(); 134 | } 135 | 136 | //calculate the mass center of the binary image. 137 | double massCenter[3]; 138 | clacBinaryImageCenter(blackImage, massCenter); 139 | 140 | //pca analysis 141 | vtkSmartPointer pcaStatistics = vtkSmartPointer::New(); 142 | pcaStatistics = binaryImagePCA(blackImage); 143 | double eigenvalueVect[3]; 144 | int indexEig[3] = { 0, 1, 2 }; 145 | double eigenvectorVect[3][3]; 146 | getEigenInfo(pcaStatistics, eigenvalueVect, indexEig, eigenvectorVect); 147 | 148 | //show items on the screen. 149 | vtkSmartPointer renderer = 150 | vtkSmartPointer::New(); 151 | vtkSmartPointer renderWindow = 152 | vtkSmartPointer::New(); 153 | renderWindow->AddRenderer(renderer); 154 | vtkSmartPointer renderWindowInteractor = 155 | vtkSmartPointer::New(); 156 | renderWindowInteractor->SetRenderWindow(renderWindow); 157 | 158 | //generate a 100*100*100 cubic space to show the space which contain all the centers of the spheres. 159 | vtkSmartPointer cubeSource = 160 | vtkSmartPointer::New(); 161 | cubeSource->SetBounds(10, 109, 10, 109, 10, 109); 162 | cubeSource->Update(); 163 | 164 | // Create a mapper and actor. 165 | vtkSmartPointer spaceMapper = 166 | vtkSmartPointer::New(); 167 | spaceMapper->SetInputConnection(cubeSource->GetOutputPort()); 168 | 169 | vtkSmartPointer spaceActor = 170 | vtkSmartPointer::New(); 171 | spaceActor->SetMapper(spaceMapper); 172 | spaceActor->GetProperty()->SetOpacity(0.1); 173 | renderer->AddActor(spaceActor); 174 | 175 | //show the major axis 176 | double majorVect[3] = { eigenvectorVect[indexEig[2]][0], eigenvectorVect[indexEig[2]][1], eigenvectorVect[indexEig[2]][2] }; 177 | double pMajor0[3] = { massCenter[0] + 100 * majorVect[0], massCenter[1] + 100 * majorVect[1], massCenter[2] + 100 * majorVect[2] }; 178 | double pMajor1[3] = { massCenter[0] - 100 * majorVect[0], massCenter[1] - 100 * majorVect[1], massCenter[2] - 100 * majorVect[2] }; 179 | 180 | vtkSmartPointer majorLineSource = 181 | vtkSmartPointer::New(); 182 | majorLineSource->SetPoint1(pMajor0); 183 | majorLineSource->SetPoint2(pMajor1); 184 | majorLineSource->Update(); 185 | 186 | vtkSmartPointer majorLineMapper = 187 | vtkSmartPointer::New(); 188 | majorLineMapper->SetInputConnection(majorLineSource->GetOutputPort()); 189 | vtkSmartPointer majorLineActor = 190 | vtkSmartPointer::New(); 191 | majorLineActor->SetMapper(majorLineMapper); 192 | majorLineActor->GetProperty()->SetLineWidth(2); 193 | majorLineActor->GetProperty()->SetColor(0.5, 0.5, 1); 194 | renderer->AddActor(majorLineActor); 195 | 196 | //show the minor axis 197 | double minorVect[3] = { eigenvectorVect[indexEig[0]][0], eigenvectorVect[indexEig[0]][1], eigenvectorVect[indexEig[0]][2] }; 198 | double pMinor0[3] = { massCenter[0] + 50 * minorVect[0], massCenter[1] + 50 * minorVect[1], massCenter[2] + 50 * minorVect[2] }; 199 | double pMinor1[3] = { massCenter[0] - 50 * minorVect[0], massCenter[1] - 50 * minorVect[1], massCenter[2] - 50 * minorVect[2] }; 200 | 201 | vtkSmartPointer minorLineSource = 202 | vtkSmartPointer::New(); 203 | minorLineSource->SetPoint1(pMinor0); 204 | minorLineSource->SetPoint2(pMinor1); 205 | minorLineSource->Update(); 206 | 207 | vtkSmartPointer minorLineMapper = 208 | vtkSmartPointer::New(); 209 | minorLineMapper->SetInputConnection(minorLineSource->GetOutputPort()); 210 | vtkSmartPointer minorLineActor = 211 | vtkSmartPointer::New(); 212 | minorLineActor->SetMapper(minorLineMapper); 213 | minorLineActor->GetProperty()->SetLineWidth(2); 214 | minorLineActor->GetProperty()->SetColor(1, 0.5, 0.5); 215 | renderer->AddActor(minorLineActor); 216 | 217 | //show the third axis 218 | double thirdVect[3] = { eigenvectorVect[indexEig[1]][0], eigenvectorVect[indexEig[1]][1], eigenvectorVect[indexEig[1]][2] }; 219 | double pThird0[3] = { massCenter[0] + 70 * thirdVect[0], massCenter[1] + 70 * thirdVect[1], massCenter[2] + 70 * thirdVect[2] }; 220 | double pThird1[3] = { massCenter[0] - 70 * thirdVect[0], massCenter[1] - 70 * thirdVect[1], massCenter[2] - 70 * thirdVect[2] }; 221 | 222 | vtkSmartPointer thirdLineSource = 223 | vtkSmartPointer::New(); 224 | thirdLineSource->SetPoint1(pThird0); 225 | thirdLineSource->SetPoint2(pThird1); 226 | thirdLineSource->Update(); 227 | 228 | vtkSmartPointer thirdLineMapper = 229 | vtkSmartPointer::New(); 230 | thirdLineMapper->SetInputConnection(thirdLineSource->GetOutputPort()); 231 | vtkSmartPointer thirdLineActor = 232 | vtkSmartPointer::New(); 233 | thirdLineActor->SetMapper(thirdLineMapper); 234 | thirdLineActor->GetProperty()->SetLineWidth(2); 235 | thirdLineActor->GetProperty()->SetColor(0.5, 1, 0.5); 236 | renderer->AddActor(thirdLineActor); 237 | 238 | //show x, y and z axis 239 | double pX0[3] = { 10, 10, 10 }; 240 | double pX1[3] = { 125, 10, 10 }; 241 | 242 | vtkSmartPointer xLineSource = 243 | vtkSmartPointer::New(); 244 | xLineSource->SetPoint1(pX0); 245 | xLineSource->SetPoint2(pX1); 246 | xLineSource->Update(); 247 | 248 | vtkSmartPointer xLineMapper = 249 | vtkSmartPointer::New(); 250 | xLineMapper->SetInputConnection(xLineSource->GetOutputPort()); 251 | vtkSmartPointer xLineActor = 252 | vtkSmartPointer::New(); 253 | xLineActor->SetMapper(xLineMapper); 254 | xLineActor->GetProperty()->SetLineWidth(2); 255 | xLineActor->GetProperty()->SetColor(0.5, 1, 1);//cyan 256 | renderer->AddActor(xLineActor); 257 | 258 | double pY0[3] = { 10, 10, 10 }; 259 | double pY1[3] = { 10, 125, 10 }; 260 | 261 | vtkSmartPointer yLineSource = 262 | vtkSmartPointer::New(); 263 | yLineSource->SetPoint1(pY0); 264 | yLineSource->SetPoint2(pY1); 265 | yLineSource->Update(); 266 | 267 | vtkSmartPointer yLineMapper = 268 | vtkSmartPointer::New(); 269 | yLineMapper->SetInputConnection(yLineSource->GetOutputPort()); 270 | vtkSmartPointer yLineActor = 271 | vtkSmartPointer::New(); 272 | yLineActor->SetMapper(yLineMapper); 273 | yLineActor->GetProperty()->SetLineWidth(2); 274 | yLineActor->GetProperty()->SetColor(1, 0.5, 1);//pink 275 | renderer->AddActor(yLineActor); 276 | 277 | double pZ0[3] = { 10, 10, 10 }; 278 | double pZ1[3] = { 10, 10, 125 }; 279 | 280 | vtkSmartPointer zLineSource = 281 | vtkSmartPointer::New(); 282 | zLineSource->SetPoint1(pZ0); 283 | zLineSource->SetPoint2(pZ1); 284 | zLineSource->Update(); 285 | 286 | vtkSmartPointer zLineMapper = 287 | vtkSmartPointer::New(); 288 | zLineMapper->SetInputConnection(zLineSource->GetOutputPort()); 289 | vtkSmartPointer zLineActor = 290 | vtkSmartPointer::New(); 291 | zLineActor->SetMapper(zLineMapper); 292 | zLineActor->GetProperty()->SetLineWidth(2); 293 | zLineActor->GetProperty()->SetColor(1, 1, 0.5);//light yellow 294 | renderer->AddActor(zLineActor); 295 | 296 | //show spheres on the screen. 297 | vtkSmartPointer spMapper[50]; 298 | vtkSmartPointer spActor[50]; 299 | for (int i = 0; i < 50; i++) 300 | { 301 | spMapper[i] = vtkSmartPointer::New(); 302 | spMapper[i]->SetInputConnection(sphereSource[i]->GetOutputPort()); 303 | spActor[i] = vtkSmartPointer::New(); 304 | spActor[i]->SetMapper(spMapper[i]); 305 | switch (spColor[i]) 306 | { 307 | case 0: 308 | spActor[i]->GetProperty()->SetColor(1, 0, 0); 309 | break; 310 | case 1: 311 | spActor[i]->GetProperty()->SetColor(0, 1, 0); 312 | break; 313 | case 2: 314 | spActor[i]->GetProperty()->SetColor(0, 0, 1); 315 | break; 316 | default: 317 | std::cout << "error while setting color for spheres."; 318 | return EXIT_FAILURE; 319 | break; 320 | } 321 | renderer->AddActor(spActor[i]); 322 | } 323 | 324 | renderer->SetBackground(0.5, 0.5, 0.5); 325 | renderWindow->Render(); 326 | renderWindowInteractor->Start(); 327 | return EXIT_SUCCESS; 328 | } 329 | 330 | void clacBinaryImageCenter(vtkSmartPointer inputImage, double result[3]) 331 | { 332 | vtkIdType numTotal = inputImage->GetNumberOfPoints(); 333 | double sumX = 0; 334 | double sumY = 0; 335 | double sumZ = 0; 336 | double numBlack = 0; 337 | double blackPoint[3]; 338 | for (vtkIdType i = 0; i < numTotal; i++) 339 | { 340 | double valVol = inputImage->GetPointData()->GetScalars()->GetTuple1(i); 341 | if (valVol == 1) 342 | { 343 | inputImage->GetPoint(i, blackPoint); 344 | sumX += blackPoint[0]; 345 | sumY += blackPoint[1]; 346 | sumZ += blackPoint[2]; 347 | numBlack++; 348 | } 349 | } 350 | result[0] = sumX / numBlack; 351 | result[1] = sumY / numBlack; 352 | result[2] = sumZ / numBlack; 353 | } 354 | 355 | vtkSmartPointer binaryImagePCA(vtkSmartPointer inputImage) 356 | { 357 | // These will be all of your "x" values. 358 | const char m0Name[] = "M0"; 359 | vtkSmartPointer dataset0Arr = 360 | vtkSmartPointer::New(); 361 | dataset0Arr->SetNumberOfComponents(1); 362 | dataset0Arr->SetName(m0Name); 363 | // These will be all of your "y" values. 364 | const char m1Name[] = "M1"; 365 | vtkSmartPointer dataset1Arr = 366 | vtkSmartPointer::New(); 367 | dataset1Arr->SetNumberOfComponents(1); 368 | dataset1Arr->SetName(m1Name); 369 | // These will be all of your "z" values. 370 | const char m2Name[] = "M2"; 371 | vtkSmartPointer dataset2Arr = 372 | vtkSmartPointer::New(); 373 | dataset2Arr->SetNumberOfComponents(1); 374 | dataset2Arr->SetName(m2Name); 375 | 376 | int count = inputImage->GetNumberOfPoints(); 377 | for (vtkIdType i = 0; i < count; ++i) 378 | { 379 | if (inputImage->GetPointData()->GetScalars()->GetTuple1(i) == 1) 380 | { 381 | double forePonit[3]; 382 | inputImage->GetPoint(i, forePonit); 383 | dataset0Arr->InsertNextValue(forePonit[0]); 384 | dataset1Arr->InsertNextValue(forePonit[1]); 385 | dataset2Arr->InsertNextValue(forePonit[2]); 386 | } 387 | } 388 | 389 | vtkSmartPointer datasetTable = 390 | vtkSmartPointer::New(); 391 | datasetTable->AddColumn(dataset0Arr); 392 | datasetTable->AddColumn(dataset1Arr); 393 | datasetTable->AddColumn(dataset2Arr); 394 | 395 | vtkSmartPointer pcaStatistics = 396 | vtkSmartPointer::New(); 397 | #if VTK_MAJOR_VERSION <= 5 398 | pcaStatistics->SetInput(vtkStatisticsAlgorithm::INPUT_DATA, datasetTable); 399 | #else 400 | pcaStatistics->SetInputData(vtkStatisticsAlgorithm::INPUT_DATA, datasetTable); 401 | #endif 402 | 403 | pcaStatistics->SetColumnStatus("M0", 1); 404 | pcaStatistics->SetColumnStatus("M1", 1); 405 | pcaStatistics->SetColumnStatus("M2", 1); 406 | pcaStatistics->RequestSelectedColumns(); 407 | pcaStatistics->SetDeriveOption(true); 408 | pcaStatistics->Update(); 409 | 410 | return pcaStatistics; 411 | } 412 | 413 | void getEigenInfo(vtkSmartPointer pcaStatistics, double eigenvalueVect[3], int indexEig[3], double eigenvectorVect[3][3]) 414 | { 415 | //eigenvalues. 416 | vtkSmartPointer eigenvalues = 417 | vtkSmartPointer::New(); 418 | pcaStatistics->GetEigenvalues(eigenvalues); 419 | for (vtkIdType i = 0; i < eigenvalues->GetNumberOfTuples(); i++) 420 | { 421 | eigenvalueVect[i] = eigenvalues->GetValue(i); 422 | } 423 | 424 | //order the eigenvalues. 425 | double mediaValue; 426 | for (int i = 0; i < 3; i++) 427 | { 428 | for (int j = 0; j < 2 - i; j++) 429 | { 430 | if (eigenvalueVect[j] > eigenvalueVect[j + 1]) 431 | { 432 | mediaValue = eigenvalueVect[j + 1]; 433 | eigenvalueVect[j + 1] = eigenvalueVect[j]; 434 | eigenvalueVect[j] = mediaValue; 435 | 436 | mediaValue = indexEig[j + 1]; 437 | indexEig[j + 1] = indexEig[j]; 438 | indexEig[j] = mediaValue; 439 | } 440 | } 441 | } 442 | 443 | //eigenvectors 444 | vtkSmartPointer eigenvectors = 445 | vtkSmartPointer::New(); 446 | 447 | pcaStatistics->GetEigenvectors(eigenvectors); 448 | for (vtkIdType i = 0; i < eigenvectors->GetNumberOfTuples(); i++) 449 | { 450 | double* evec = new double[eigenvectors->GetNumberOfComponents()]; 451 | eigenvectors->GetTuple(i, evec); 452 | vtkSmartPointer eigenvectorSingle = 453 | vtkSmartPointer::New(); 454 | pcaStatistics->GetEigenvector(i, eigenvectorSingle); 455 | for (vtkIdType j = 0; j < eigenvectors->GetNumberOfComponents(); j++) 456 | { 457 | eigenvectorVect[i][j] = evec[j]; 458 | } 459 | delete[] evec; 460 | } 461 | } -------------------------------------------------------------------------------- /高级生物医学图像处理/medImgViewer-src/viewer.cpp: -------------------------------------------------------------------------------- 1 | #include "viewer.h" 2 | 3 | #include "itkImageDuplicator.h" 4 | #include "itkImageToHistogramFilter.h" 5 | #include "itkBinaryThresholdImageFilter.h" 6 | #include "itkOtsuThresholdImageFilter.h" 7 | #include 8 | #include "itkConvolutionImageFilter.h" 9 | #include "itkStatisticsImageFilter.h" 10 | #include "itkDiscreteGaussianImageFilter.h" 11 | #include "itkMedianImageFilter.h" 12 | #include "itkBinaryErodeImageFilter.h" 13 | #include 14 | #include 15 | #include "itkBinaryDilateImageFilter.h" 16 | #include 17 | #include "itkBinaryMorphologicalOpeningImageFilter.h" 18 | #include "itkBinaryMorphologicalClosingImageFilter.h" 19 | #include "itkFlatStructuringElement.h" 20 | #include "itkSignedMaurerDistanceMapImageFilter.h" 21 | #include "itkBinaryThinningImageFilter.h" 22 | #include "itkRescaleIntensityImageFilter.h" 23 | #include "itkSubtractImageFilter.h" 24 | #include 25 | #include 26 | 27 | 28 | viewer::viewer(QWidget *parent) : 29 | QLabel(parent) 30 | { 31 | this->setAcceptDrops(false); 32 | } 33 | 34 | viewer::~viewer(){} 35 | 36 | void viewer::loadImg(QImage *sourceImg) 37 | { 38 | delete this->img; 39 | QImage *image = new QImage(sourceImg->width(), sourceImg->height(), QImage::Format::Format_Grayscale8); 40 | *image = sourceImg->convertToFormat(QImage::Format::Format_Grayscale8); 41 | this->img = image; 42 | 43 | this->pixMap = QPixmap::fromImage(*(this->img)); 44 | QPixmap fitPixMap = pixMap.scaled(this->size(), Qt::KeepAspectRatio); 45 | this->setPixmap(fitPixMap); 46 | this->show(); 47 | 48 | this->itkImg = qImg2itkImg(this->img); 49 | this->itkImgProcess = itkShow2process(this->itkImg); 50 | this->haveDTM = false; 51 | } 52 | 53 | void viewer::refreshImg(QImage *newImg) 54 | { 55 | delete this->img; 56 | QImage *image = new QImage(newImg->width(), newImg->height(), QImage::Format::Format_Grayscale8); 57 | *image = newImg->convertToFormat(QImage::Format::Format_Grayscale8); 58 | this->img = image; 59 | 60 | this->pixMap = QPixmap::fromImage(*(this->img)); 61 | QPixmap fitPixMap = pixMap.scaled(this->size(), Qt::KeepAspectRatio); 62 | this->setPixmap(fitPixMap); 63 | this->show(); 64 | } 65 | 66 | void viewer::setProcessType(int processType) 67 | { 68 | this->processType = processType; 69 | } 70 | 71 | void viewer::resizeEvent(QResizeEvent *event) 72 | { 73 | QWidget::resizeEvent(event); 74 | QPixmap fitPixMap = pixMap.scaled(this->size(), Qt::KeepAspectRatio); 75 | this->setPixmap(fitPixMap); 76 | } 77 | 78 | void viewer::dragEnterEvent(QDragEnterEvent *event) 79 | { 80 | QList urls = event->mimeData()->urls(); 81 | if(urls.isEmpty() || urls.size() > 1) 82 | return; 83 | foreach(QUrl url, urls) 84 | { 85 | QString file_name = url.toLocalFile(); 86 | std::string urlString = file_name.toStdString(); 87 | std::string suffixStr = urlString.substr(urlString.find_last_of('.') + 1); 88 | if (suffixStr == "jpg" || suffixStr == "png" || suffixStr == "gif" || suffixStr == "jpeg" || suffixStr == "bmp") 89 | event->acceptProposedAction(); 90 | } 91 | } 92 | 93 | void viewer::dropEvent(QDropEvent *event) 94 | { 95 | QList urls = event->mimeData()->urls(); 96 | if(urls.isEmpty()) 97 | return; 98 | foreach(QUrl url, urls) 99 | { 100 | QString file_name = url.toLocalFile(); 101 | QByteArray qName=file_name.toLatin1(); 102 | char *imgName=qName.data(); 103 | QImage image(imgName); 104 | this->loadImg(&image); 105 | emit imgChange(&image); 106 | } 107 | } 108 | 109 | //private function 110 | ImageType::Pointer viewer::qImg2itkImg(QImage *qImg) 111 | { 112 | ImageType::IndexType start; 113 | start[0] = start[1] = 0; 114 | ImageType::SizeType size; 115 | size[0] = qImg->width(); 116 | size[1] = qImg->height(); 117 | ImageType::RegionType region; 118 | region.SetSize(size); 119 | region.SetIndex(start); 120 | ImageType::IndexType index; 121 | unsigned char pixValue; 122 | 123 | ImageType::Pointer itkImg = ImageType::New(); 124 | itkImg->SetRegions(region); 125 | itkImg->Allocate(); 126 | unsigned char *buffer = qImg->bits(); 127 | 128 | for (int i = 0; iSetPixel(index, pixValue); 136 | } 137 | } 138 | 139 | return itkImg; 140 | } 141 | 142 | QImage viewer::itk2qImg(ImageType::Pointer itkImg) 143 | { 144 | ImageType::RegionType region = itkImg->GetLargestPossibleRegion(); 145 | ImageType::SizeType size = region.GetSize(); 146 | ImageType::PixelType pixelValue; 147 | ImageType::IndexType index; 148 | int qIndex; 149 | 150 | int width = size[0]; 151 | int height = size[1]; 152 | QImage image(width, height, QImage::Format::Format_Grayscale8); 153 | unsigned char *buffer = image.bits(); 154 | 155 | for (int i = 0; iGetPixel(index); 162 | *(buffer + j*size[0] + i) = pixelValue; 163 | } 164 | } 165 | 166 | return image; 167 | } 168 | 169 | ImageTypeProcess::Pointer viewer::itkShow2process(ImageType::Pointer itkImg) 170 | { 171 | ImageType::RegionType regionOri = itkImg->GetLargestPossibleRegion(); 172 | ImageType::SizeType sizeOri = regionOri.GetSize(); 173 | int width = sizeOri[0]; 174 | int height = sizeOri[1]; 175 | 176 | ImageTypeProcess::IndexType start; 177 | start[0] = start[1] = 0; 178 | ImageTypeProcess::SizeType size; 179 | size[0] = width; 180 | size[1] = height; 181 | ImageTypeProcess::RegionType region; 182 | region.SetSize(size); 183 | region.SetIndex(start); 184 | ImageTypeProcess::Pointer itkImgProcess = ImageTypeProcess::New(); 185 | itkImgProcess->SetRegions(region); 186 | itkImgProcess->Allocate(); 187 | 188 | ImageTypeProcess::PixelType pixelValueProcess; 189 | ImageTypeProcess::IndexType index; 190 | ImageType::PixelType pixelValue; 191 | ImageType::IndexType indexOri; 192 | 193 | for (int i = 0; iGetPixel(indexOri); 202 | pixelValueProcess = static_cast (itkImg->GetPixel(indexOri)); 203 | itkImgProcess->SetPixel(index, pixelValueProcess); 204 | } 205 | } 206 | 207 | return itkImgProcess; 208 | } 209 | 210 | ImageType::Pointer viewer::itkProcess2show(ImageTypeProcess::Pointer itkImgProcess) 211 | { 212 | /*ImageTypeProcess::RegionType regionProcess = itkImgProcess->GetLargestPossibleRegion(); 213 | ImageTypeProcess::SizeType sizeProcess = regionProcess.GetSize(); 214 | int width = sizeProcess[0]; 215 | int height = sizeProcess[1]; 216 | 217 | ImageType::IndexType start; 218 | start[0] = start[1] = 0; 219 | ImageType::SizeType size; 220 | size[0] = width; 221 | size[1] = height; 222 | ImageType::RegionType region; 223 | region.SetSize(size); 224 | region.SetIndex(start); 225 | ImageType::Pointer itkImg = ImageType::New(); 226 | itkImg->SetRegions(region); 227 | itkImg->Allocate(); 228 | 229 | ImageType::PixelType pixelValue; 230 | ImageType::IndexType indexOri; 231 | ImageTypeProcess::PixelType pixelValueProcess; 232 | ImageTypeProcess::IndexType index; 233 | 234 | typedef itk::StatisticsImageFilter< ImageTypeProcess > StatisticsFilterType; 235 | StatisticsFilterType::Pointer statistics = StatisticsFilterType::New(); 236 | statistics->SetInput(itkImgProcess); 237 | statistics->Update(); 238 | float max = statistics->GetMaximum(); 239 | float min = statistics->GetMinimum(); 240 | float range = max - min; 241 | 242 | for (int i = 0; iGetPixel(index); 251 | pixelValueProcess = (pixelValueProcess - min) / range * 255; 252 | pixelValue = static_cast (pixelValueProcess); 253 | itkImg->SetPixel(indexOri, pixelValue); 254 | } 255 | }*/ 256 | 257 | typedef itk::RescaleIntensityImageFilter< ImageTypeProcess, ImageType > RescaleType; 258 | RescaleType::Pointer rescaler = RescaleType::New(); 259 | rescaler->SetInput(itkImgProcess); 260 | rescaler->SetOutputMinimum(0); 261 | rescaler->SetOutputMaximum(255); 262 | rescaler->Update(); 263 | 264 | return rescaler->GetOutput(); 265 | } 266 | 267 | //slots 268 | void viewer::reloadImg(QImage *newImg) 269 | { 270 | loadImg(newImg); 271 | } 272 | 273 | void viewer::sendReload() 274 | { 275 | emit reloadInfo(this->img); 276 | } 277 | 278 | // image processing 279 | bool viewer::isThreshold(ImageType::Pointer itkImg) 280 | { 281 | ImageType::RegionType region = itkImg->GetLargestPossibleRegion(); 282 | ImageType::SizeType size = region.GetSize(); 283 | ImageType::PixelType pixelValue; 284 | ImageType::IndexType index; 285 | int qIndex; 286 | 287 | int width = size[0]; 288 | int height = size[1]; 289 | 290 | for (int i = 0; iGetPixel(index); 297 | if (pixelValue != 0 && pixelValue != 255) 298 | { 299 | return false; 300 | } 301 | } 302 | } 303 | 304 | return true; 305 | } 306 | 307 | void viewer::thresholding() 308 | { 309 | switch (this->processType) 310 | { 311 | case 0: 312 | { 313 | this->itkImg = qImg2itkImg(this->img); 314 | this->itkImgProcess = itkShow2process(this->itkImg); 315 | break; 316 | } 317 | case 1: 318 | { 319 | if (!this->isThreshold(this->itkImg)) 320 | { 321 | typedef itk::OtsuThresholdImageFilter OtsuFilterType; 322 | OtsuFilterType::Pointer otsuFilter = OtsuFilterType::New(); 323 | otsuFilter->SetInput(this->itkImg); 324 | otsuFilter->SetInsideValue(0); 325 | otsuFilter->SetOutsideValue(255); 326 | otsuFilter->Update(); 327 | 328 | this->itkImg = otsuFilter->GetOutput(); 329 | this->itkImgProcess = itkShow2process(this->itkImg); 330 | QImage image = itk2qImg(this->itkImg); 331 | this->refreshImg(&image); 332 | } 333 | break; 334 | } 335 | case 2: 336 | { 337 | if (!this->isThreshold(this->itkImg)) 338 | { 339 | typedef itk::MaximumEntropyThresholdImageFilter EntropyFilterType; 340 | EntropyFilterType::Pointer entropyFilter = EntropyFilterType::New(); 341 | entropyFilter->SetInput(this->itkImg); 342 | entropyFilter->SetInsideValue(0); 343 | entropyFilter->SetOutsideValue(255); 344 | entropyFilter->Update(); 345 | 346 | this->itkImg = entropyFilter->GetOutput(); 347 | this->itkImgProcess = itkShow2process(this->itkImg); 348 | QImage image = itk2qImg(this->itkImg); 349 | this->refreshImg(&image); 350 | } 351 | break; 352 | } 353 | default: 354 | { 355 | break; 356 | } 357 | } 358 | } 359 | 360 | void viewer::thresholding(int thresholdValue) 361 | { 362 | typedef itk::BinaryThresholdImageFilter FilterType; 363 | FilterType::Pointer filter = FilterType::New(); 364 | filter->SetInput(this->itkImg); 365 | filter->SetOutsideValue(0); 366 | filter->SetInsideValue(255); 367 | filter->SetLowerThreshold(thresholdValue); 368 | filter->SetUpperThreshold(255); 369 | filter->Update(); 370 | ImageType::Pointer mediateImg = filter->GetOutput(); 371 | QImage image = itk2qImg(mediateImg); 372 | this->refreshImg(&image); 373 | } 374 | 375 | void viewer::edgeDetect() 376 | { 377 | ImageTypeProcess::Pointer kernel = ImageTypeProcess::New(); 378 | ImageTypeProcess::IndexType start; 379 | start.Fill(0); 380 | ImageTypeProcess::SizeType size; 381 | size.Fill(3); 382 | ImageTypeProcess::RegionType region; 383 | region.SetSize(size); 384 | region.SetIndex(start); 385 | kernel->SetRegions(region); 386 | kernel->Allocate(); 387 | ImageTypeProcess::IndexType index; 388 | kernel->FillBuffer(0); 389 | index[0] = 0; index[1] = 0; 390 | kernel->SetPixel(index, 1); 391 | index[0] = 0; index[1] = 1; 392 | kernel->SetPixel(index, 1); 393 | index[0] = 0; index[1] = 2; 394 | kernel->SetPixel(index, 1); 395 | 396 | index[0] = 2; index[1] = 0; 397 | kernel->SetPixel(index, -1); 398 | index[0] = 2; index[1] = 1; 399 | kernel->SetPixel(index, -1); 400 | index[0] = 2; index[1] = 2; 401 | kernel->SetPixel(index, -1); 402 | 403 | typedef itk::ConvolutionImageFilter ConvFilterType; 404 | ConvFilterType::Pointer convFilter = ConvFilterType::New(); 405 | convFilter->SetInput(this->itkImgProcess); 406 | convFilter->SetKernelImage(kernel); 407 | convFilter->Update(); 408 | this->itkImgProcess = convFilter->GetOutput(); 409 | 410 | this->itkImg = itkProcess2show(this->itkImgProcess); 411 | QImage image = itk2qImg(this->itkImg); 412 | this->refreshImg(&image); 413 | } 414 | 415 | void viewer::denosing() 416 | { 417 | switch (this->processType) 418 | { 419 | case 0: 420 | { 421 | break; 422 | } 423 | case 1: 424 | { 425 | double variance = 4.0; 426 | typedef itk::DiscreteGaussianImageFilter GaussianFilterType; 427 | GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New(); 428 | gaussianFilter->SetInput(this->itkImgProcess); 429 | gaussianFilter->SetVariance(variance); 430 | //gaussianFilter->SetMaximumKernelWidth(kernelWidth); 431 | gaussianFilter->Update(); 432 | this->itkImgProcess = gaussianFilter->GetOutput(); 433 | 434 | this->itkImg = itkProcess2show(this->itkImgProcess); 435 | QImage image = itk2qImg(this->itkImg); 436 | this->refreshImg(&image); 437 | break; 438 | } 439 | case 2: 440 | { 441 | int radium = 3; 442 | typedef itk::MedianImageFilter MedianFilterType; 443 | MedianFilterType::Pointer medianFilter = MedianFilterType::New(); 444 | medianFilter->SetInput(this->itkImgProcess); 445 | MedianFilterType::InputSizeType radius; 446 | radius.Fill(radium); 447 | medianFilter->SetRadius(radius); 448 | medianFilter->Update(); 449 | this->itkImgProcess = medianFilter->GetOutput(); 450 | 451 | this->itkImg = itkProcess2show(this->itkImgProcess); 452 | QImage image = itk2qImg(this->itkImg); 453 | this->refreshImg(&image); 454 | break; 455 | } 456 | default: 457 | { 458 | break; 459 | } 460 | } 461 | } 462 | 463 | void viewer::erode() 464 | { 465 | if (this->isThreshold(this->itkImg)) 466 | { 467 | int radium = 1; 468 | typedef itk::FlatStructuringElement<2> StructuringElementType; 469 | StructuringElementType::RadiusType elementRadius; 470 | elementRadius.Fill(radium); 471 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 472 | 473 | typedef itk::BinaryErodeImageFilter BinaryErodeImageFilterType; 474 | BinaryErodeImageFilterType::Pointer binaryErodeFilter = BinaryErodeImageFilterType::New(); 475 | binaryErodeFilter->SetInput(this->itkImg); 476 | binaryErodeFilter->SetKernel(structuringElement); 477 | binaryErodeFilter->Update(); 478 | 479 | this->itkImg = binaryErodeFilter->GetOutput(); 480 | this->itkImgProcess = itkShow2process(this->itkImg); 481 | QImage image = itk2qImg(this->itkImg); 482 | this->refreshImg(&image); 483 | } 484 | else 485 | { 486 | float kernelValue = 2; 487 | 488 | typedef itk::Neighborhood KernelType; 489 | KernelType neighborhood; 490 | neighborhood.SetRadius(kernelValue); 491 | for (unsigned int i = 0; i < neighborhood.GetSize()[0] * neighborhood.GetSize()[1]; ++i) 492 | { 493 | neighborhood[i] = 1; 494 | } 495 | 496 | typedef itk::GrayscaleFunctionErodeImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleErodeImageFilterType; 497 | GrayscaleErodeImageFilterType::Pointer erodeFilter = GrayscaleErodeImageFilterType::New(); 498 | erodeFilter->SetInput(this->itkImgProcess); 499 | erodeFilter->SetKernel(neighborhood); 500 | erodeFilter->Update(); 501 | this->itkImgProcess = erodeFilter->GetOutput(); 502 | 503 | this->itkImg = itkProcess2show(this->itkImgProcess); 504 | QImage image = itk2qImg(this->itkImg); 505 | this->refreshImg(&image); 506 | } 507 | } 508 | 509 | void viewer::dilate() 510 | { 511 | if (this->isThreshold(this->itkImg)) 512 | { 513 | int radium = 1; 514 | typedef itk::FlatStructuringElement<2> StructuringElementType; 515 | StructuringElementType::RadiusType elementRadius; 516 | elementRadius.Fill(radium); 517 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 518 | 519 | typedef itk::BinaryDilateImageFilter BinaryDilateImageFilterType; 520 | BinaryDilateImageFilterType::Pointer binaryDilateFilter = BinaryDilateImageFilterType::New(); 521 | binaryDilateFilter->SetInput(this->itkImg); 522 | binaryDilateFilter->SetKernel(structuringElement); 523 | binaryDilateFilter->Update(); 524 | this->itkImg = binaryDilateFilter->GetOutput(); 525 | this->itkImgProcess = itkShow2process(this->itkImg); 526 | QImage image = itk2qImg(this->itkImg); 527 | this->refreshImg(&image); 528 | } 529 | else 530 | { 531 | float kernelValue = 3; 532 | 533 | typedef itk::Neighborhood KernelType; 534 | KernelType neighborhood; 535 | neighborhood.SetRadius(kernelValue); 536 | for (unsigned int i = 0; i < neighborhood.GetSize()[0] * neighborhood.GetSize()[1]; ++i) 537 | { 538 | neighborhood[i] = 1; 539 | } 540 | 541 | typedef itk::GrayscaleDilateImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleDilateImageFilterType; 542 | GrayscaleDilateImageFilterType::Pointer dilateFilter = GrayscaleDilateImageFilterType::New(); 543 | dilateFilter->SetInput(this->itkImgProcess); 544 | dilateFilter->SetKernel(neighborhood); 545 | dilateFilter->Update(); 546 | this->itkImgProcess = dilateFilter->GetOutput(); 547 | 548 | this->itkImg = itkProcess2show(this->itkImgProcess); 549 | QImage image = itk2qImg(this->itkImg); 550 | this->refreshImg(&image); 551 | } 552 | } 553 | 554 | void viewer::openOpr() 555 | { 556 | if (this->isThreshold(this->itkImg)) 557 | { 558 | int radium = 1; 559 | typedef itk::FlatStructuringElement<2> StructuringElementType; 560 | StructuringElementType::RadiusType elementRadius; 561 | elementRadius.Fill(radium); 562 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 563 | typedef itk::BinaryMorphologicalOpeningImageFilter 564 | BinaryMorphologicalOpeningImageFilterType; 565 | BinaryMorphologicalOpeningImageFilterType::Pointer openingFilter 566 | = BinaryMorphologicalOpeningImageFilterType::New(); 567 | openingFilter->SetInput(this->itkImg); 568 | openingFilter->SetKernel(structuringElement); 569 | openingFilter->Update(); 570 | this->itkImg = openingFilter->GetOutput(); 571 | this->itkImgProcess = itkShow2process(this->itkImg); 572 | QImage image = itk2qImg(this->itkImg); 573 | this->refreshImg(&image); 574 | } 575 | else 576 | { 577 | float kernelValue = 1; 578 | 579 | typedef itk::Neighborhood KernelType; 580 | KernelType neighborhood; 581 | neighborhood.SetRadius(kernelValue); 582 | for (unsigned int i = 0; i < neighborhood.GetSize()[0] * neighborhood.GetSize()[1]; ++i) 583 | { 584 | neighborhood[i] = 1; 585 | } 586 | 587 | typedef itk::GrayscaleFunctionErodeImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleErodeImageFilterType; 588 | GrayscaleErodeImageFilterType::Pointer erodeFilter = GrayscaleErodeImageFilterType::New(); 589 | erodeFilter->SetInput(this->itkImgProcess); 590 | erodeFilter->SetKernel(neighborhood); 591 | erodeFilter->Update(); 592 | this->itkImgProcess = erodeFilter->GetOutput(); 593 | 594 | typedef itk::GrayscaleDilateImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleDilateImageFilterType; 595 | GrayscaleDilateImageFilterType::Pointer dilateFilter = GrayscaleDilateImageFilterType::New(); 596 | dilateFilter->SetInput(this->itkImgProcess); 597 | dilateFilter->SetKernel(neighborhood); 598 | dilateFilter->Update(); 599 | this->itkImgProcess = dilateFilter->GetOutput(); 600 | 601 | this->itkImg = itkProcess2show(this->itkImgProcess); 602 | QImage image = itk2qImg(this->itkImg); 603 | this->refreshImg(&image); 604 | } 605 | } 606 | 607 | void viewer::closeOpr() 608 | { 609 | if (this->isThreshold(this->itkImg)) 610 | { 611 | int radium = 1; 612 | typedef itk::FlatStructuringElement<2> StructuringElementType; 613 | StructuringElementType::RadiusType elementRadius; 614 | elementRadius.Fill(radium); 615 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 616 | typedef itk::BinaryMorphologicalClosingImageFilter 617 | BinaryMorphologicalClosingImageFilterType; 618 | BinaryMorphologicalClosingImageFilterType::Pointer closingFilter 619 | = BinaryMorphologicalClosingImageFilterType::New(); 620 | closingFilter->SetInput(this->itkImg); 621 | closingFilter->SetKernel(structuringElement); 622 | closingFilter->Update(); 623 | this->itkImg = closingFilter->GetOutput(); 624 | this->itkImgProcess = itkShow2process(this->itkImg); 625 | QImage image = itk2qImg(this->itkImg); 626 | this->refreshImg(&image); 627 | } 628 | else 629 | { 630 | float kernelValue = 1; 631 | 632 | typedef itk::Neighborhood KernelType; 633 | KernelType neighborhood; 634 | neighborhood.SetRadius(kernelValue); 635 | for (unsigned int i = 0; i < neighborhood.GetSize()[0] * neighborhood.GetSize()[1]; ++i) 636 | { 637 | neighborhood[i] = 1; 638 | } 639 | 640 | typedef itk::GrayscaleDilateImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleDilateImageFilterType; 641 | GrayscaleDilateImageFilterType::Pointer dilateFilter = GrayscaleDilateImageFilterType::New(); 642 | dilateFilter->SetInput(this->itkImgProcess); 643 | dilateFilter->SetKernel(neighborhood); 644 | dilateFilter->Update(); 645 | this->itkImgProcess = dilateFilter->GetOutput(); 646 | 647 | typedef itk::GrayscaleFunctionErodeImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleErodeImageFilterType; 648 | GrayscaleErodeImageFilterType::Pointer erodeFilter = GrayscaleErodeImageFilterType::New(); 649 | erodeFilter->SetInput(this->itkImgProcess); 650 | erodeFilter->SetKernel(neighborhood); 651 | erodeFilter->Update(); 652 | this->itkImgProcess = erodeFilter->GetOutput(); 653 | this->itkImg = itkProcess2show(this->itkImgProcess); 654 | QImage image = itk2qImg(this->itkImg); 655 | this->refreshImg(&image); 656 | } 657 | } 658 | 659 | bool viewer::isImgEmpty(ImageType::Pointer itkImg) 660 | { 661 | ImageType::RegionType region = itkImg->GetLargestPossibleRegion(); 662 | ImageType::SizeType size = region.GetSize(); 663 | ImageType::PixelType pixelValue; 664 | ImageType::IndexType index; 665 | 666 | int width = size[0]; 667 | int height = size[1]; 668 | 669 | for (int i = 0; iGetPixel(index); 676 | if (pixelValue != 0) 677 | { 678 | return false; 679 | } 680 | } 681 | } 682 | 683 | return true; 684 | } 685 | 686 | void viewer::binaryDistanceTrans() 687 | { 688 | /*if (this->isThreshold(this->itkImg)) 689 | { 690 | typedef itk::SignedMaurerDistanceMapImageFilter< ImageType, ImageTypeProcess > SignedMaurerDistanceMapImageFilterType; 691 | SignedMaurerDistanceMapImageFilterType::Pointer distanceMapImageFilter = SignedMaurerDistanceMapImageFilterType::New(); 692 | distanceMapImageFilter->SetInput(this->itkImg); 693 | distanceMapImageFilter->Update(); 694 | ImageTypeProcess::Pointer result = ImageTypeProcess::New(); 695 | result = distanceMapImageFilter->GetOutput(); 696 | ImageTypeProcess::RegionType region = result->GetLargestPossibleRegion(); 697 | ImageTypeProcess::SizeType size = region.GetSize(); 698 | ImageTypeProcess::IndexType index; 699 | ImageTypeProcess::PixelType pixelValue; 700 | int width = size[0]; 701 | int height = size[1]; 702 | for (int i = 0; iGetPixel(index); 709 | if (pixelValue > 0) 710 | { 711 | result->SetPixel(index, 0); 712 | } 713 | else 714 | { 715 | result->SetPixel(index, -pixelValue); 716 | } 717 | } 718 | } 719 | this->itkImg = itkProcess2show(result); 720 | QImage image = itk2qImg(this->itkImg); 721 | this->refreshImg(&image); 722 | }*/ 723 | 724 | if (this->isThreshold(this->itkImg)) 725 | { 726 | int radium = 1; 727 | typedef itk::FlatStructuringElement<2> StructuringElementType; 728 | StructuringElementType::RadiusType elementRadius; 729 | elementRadius.Fill(radium); 730 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 731 | typedef itk::BinaryErodeImageFilter BinaryErodeImageFilterType; 732 | BinaryErodeImageFilterType::Pointer binaryErodeFilter = BinaryErodeImageFilterType::New(); 733 | 734 | ImageType::Pointer erodedImg = ImageType::New(); 735 | 736 | binaryErodeFilter->SetInput(this->itkImg); 737 | binaryErodeFilter->SetKernel(structuringElement); 738 | binaryErodeFilter->Update(); 739 | erodedImg = binaryErodeFilter->GetOutput(); 740 | erodedImg->DisconnectPipeline(); 741 | 742 | typedef itk::ImageDuplicator< ImageType > DuplicatorType; 743 | DuplicatorType::Pointer duplicator = DuplicatorType::New(); 744 | duplicator->SetInputImage(this->itkImg); 745 | duplicator->Update(); 746 | 747 | ImageType::Pointer DTM = ImageType::New(); 748 | DTM = duplicator->GetOutput(); 749 | DTM->DisconnectPipeline(); 750 | 751 | ImageType::RegionType region = DTM->GetLargestPossibleRegion(); 752 | ImageType::SizeType size = region.GetSize(); 753 | ImageType::PixelType pixelValue; 754 | ImageType::IndexType index; 755 | ImageType::PixelType pixelValuePre; 756 | 757 | for (int i = 0; iitkImg->GetPixel(index); 764 | if (pixelValue != 0) 765 | { 766 | DTM->SetPixel(index, 1); 767 | } 768 | } 769 | } 770 | 771 | while (!this->isImgEmpty(erodedImg)) 772 | { 773 | for (int i = 0; iGetPixel(index); 780 | if (pixelValue != 0) 781 | { 782 | pixelValuePre = DTM->GetPixel(index); 783 | pixelValuePre++; 784 | DTM->SetPixel(index, pixelValuePre); 785 | } 786 | } 787 | } 788 | 789 | binaryErodeFilter->SetInput(erodedImg); 790 | binaryErodeFilter->SetKernel(structuringElement); 791 | binaryErodeFilter->Update(); 792 | erodedImg = binaryErodeFilter->GetOutput(); 793 | erodedImg->DisconnectPipeline(); 794 | } 795 | 796 | this->itkDTM = DTM; 797 | this->haveDTM = true; 798 | typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleType; 799 | RescaleType::Pointer rescaler = RescaleType::New(); 800 | rescaler->SetInput(DTM); 801 | rescaler->SetOutputMinimum(0); 802 | rescaler->SetOutputMaximum(255); 803 | rescaler->Update(); 804 | this->itkImg = rescaler->GetOutput(); 805 | this->itkImgProcess = itkShow2process(this->itkImg); 806 | QImage image = itk2qImg(this->itkImg); 807 | this->refreshImg(&image); 808 | } 809 | } 810 | 811 | void viewer::skeletonize() 812 | { 813 | if (this->isThreshold(this->itkImg)) 814 | { 815 | int radium = 1; 816 | typedef itk::FlatStructuringElement<2> StructuringElementType; 817 | StructuringElementType::RadiusType elementRadius; 818 | elementRadius.Fill(radium); 819 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 820 | typedef itk::BinaryErodeImageFilter BinaryErodeImageFilterType; 821 | BinaryErodeImageFilterType::Pointer binaryErodeFilter = BinaryErodeImageFilterType::New(); 822 | 823 | ImageType::Pointer erodedImg = ImageType::New(); 824 | 825 | binaryErodeFilter->SetInput(this->itkImg); 826 | binaryErodeFilter->SetKernel(structuringElement); 827 | binaryErodeFilter->Update(); 828 | erodedImg = binaryErodeFilter->GetOutput(); 829 | erodedImg->DisconnectPipeline(); 830 | 831 | typedef itk::ImageDuplicator< ImageType > DuplicatorType; 832 | DuplicatorType::Pointer duplicator = DuplicatorType::New(); 833 | duplicator->SetInputImage(this->itkImg); 834 | duplicator->Update(); 835 | 836 | ImageType::Pointer DTM = ImageType::New(); 837 | DTM = duplicator->GetOutput(); 838 | DTM->DisconnectPipeline(); 839 | 840 | ImageType::RegionType region = DTM->GetLargestPossibleRegion(); 841 | ImageType::SizeType size = region.GetSize(); 842 | ImageType::PixelType pixelValue; 843 | ImageType::IndexType index; 844 | ImageType::PixelType pixelValuePre; 845 | 846 | for (int i = 0; iitkImg->GetPixel(index); 853 | if (pixelValue != 0) 854 | { 855 | DTM->SetPixel(index, 1); 856 | } 857 | } 858 | } 859 | 860 | while (!this->isImgEmpty(erodedImg)) 861 | { 862 | for (int i = 0; iGetPixel(index); 869 | if (pixelValue != 0) 870 | { 871 | pixelValuePre = DTM->GetPixel(index); 872 | pixelValuePre++; 873 | DTM->SetPixel(index, pixelValuePre); 874 | } 875 | } 876 | } 877 | 878 | binaryErodeFilter->SetInput(erodedImg); 879 | binaryErodeFilter->SetKernel(structuringElement); 880 | binaryErodeFilter->Update(); 881 | erodedImg = binaryErodeFilter->GetOutput(); 882 | erodedImg->DisconnectPipeline(); 883 | } 884 | 885 | //skeletonize 886 | typedef itk::ImageDuplicator< ImageType > DuplicatorType; 887 | DuplicatorType::Pointer duplicator2 = DuplicatorType::New(); 888 | duplicator2->SetInputImage(DTM); 889 | duplicator2->Update(); 890 | 891 | this->itkImg = duplicator2->GetOutput(); 892 | this->itkImg->DisconnectPipeline(); 893 | 894 | ImageType::IndexType neighborIndex; 895 | ImageType::PixelType neighborPixelValue; 896 | int innerX; 897 | int innerY; 898 | for (int i = 0; iGetPixel(index); 905 | if (pixelValue != 0) 906 | { 907 | for (int innerI = 0; innerI < 3; innerI++) 908 | { 909 | for (int innerJ = 0; innerJ < 3; innerJ++) 910 | { 911 | innerX = i + innerI - 1; 912 | innerY = j + innerJ - 1; 913 | if (innerX >= 0 && innerX < size[0] && innerY >= 0 && innerY < size[1]) 914 | { 915 | neighborIndex[0] = innerX; 916 | neighborIndex[1] = innerY; 917 | neighborPixelValue = DTM->GetPixel(neighborIndex); 918 | if (neighborPixelValue > pixelValue) 919 | { 920 | this->itkImg->SetPixel(index, 0); 921 | } 922 | } 923 | } 924 | } 925 | } 926 | } 927 | } 928 | 929 | this->itkDTM = this->itkImg; 930 | this->haveDTM = true; 931 | typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleType; 932 | RescaleType::Pointer rescaler = RescaleType::New(); 933 | rescaler->SetInput(this->itkImg); 934 | rescaler->SetOutputMinimum(0); 935 | rescaler->SetOutputMaximum(255); 936 | rescaler->Update(); 937 | this->itkImg = rescaler->GetOutput(); 938 | this->itkImgProcess = itkShow2process(this->itkImg); 939 | QImage image = itk2qImg(this->itkImg); 940 | this->refreshImg(&image); 941 | } 942 | } 943 | 944 | void viewer::skRestorate() 945 | { 946 | if (this->haveDTM) 947 | { 948 | ImageType::Pointer resMap = ImageType::New(); 949 | typedef itk::ImageDuplicator< ImageType > DuplicatorType; 950 | DuplicatorType::Pointer duplicator = DuplicatorType::New(); 951 | duplicator->SetInputImage(this->itkDTM); 952 | duplicator->Update(); 953 | resMap = duplicator->GetOutput(); 954 | resMap->DisconnectPipeline(); 955 | 956 | ImageType::RegionType region = this->itkDTM->GetLargestPossibleRegion(); 957 | ImageType::SizeType size = region.GetSize(); 958 | ImageType::PixelType pixelValue; 959 | ImageType::IndexType index; 960 | ImageType::PixelType pixelValuePre; 961 | 962 | ImageType::IndexType resIndex; 963 | int innerX; 964 | int innerY; 965 | for (int i = 0; iitkDTM->GetPixel(index); 972 | if (pixelValue > 1) 973 | { 974 | int areaLength = (pixelValue - 1) * 2 + 1; 975 | if (pixelValue != 0) 976 | { 977 | for (int innerI = 0; innerI < areaLength; innerI++) 978 | { 979 | for (int innerJ = 0; innerJ < areaLength; innerJ++) 980 | { 981 | innerX = i + innerI - pixelValue; 982 | innerY = j + innerJ - pixelValue; 983 | if (innerX >= 0 && innerX < size[0] && innerY >= 0 && innerY < size[1]) 984 | { 985 | resIndex[0] = innerX; 986 | resIndex[1] = innerY; 987 | resMap->SetPixel(resIndex, 1); 988 | 989 | } 990 | } 991 | } 992 | } 993 | } 994 | } 995 | } 996 | 997 | typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleType; 998 | RescaleType::Pointer rescaler = RescaleType::New(); 999 | rescaler->SetInput(resMap); 1000 | rescaler->SetOutputMinimum(0); 1001 | rescaler->SetOutputMaximum(255); 1002 | rescaler->Update(); 1003 | this->itkImg = rescaler->GetOutput(); 1004 | QImage image = itk2qImg(this->itkImg); 1005 | this->itkImgProcess = itkShow2process(this->itkImg); 1006 | this->refreshImg(&image); 1007 | } 1008 | } 1009 | 1010 | void viewer::morphEdge() 1011 | { 1012 | if (this->isThreshold(this->itkImg)) 1013 | { 1014 | int radium = 1; 1015 | typedef itk::FlatStructuringElement<2> StructuringElementType; 1016 | StructuringElementType::RadiusType elementRadius; 1017 | elementRadius.Fill(radium); 1018 | StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); 1019 | 1020 | typedef itk::BinaryErodeImageFilter BinaryErodeImageFilterType; 1021 | BinaryErodeImageFilterType::Pointer binaryErodeFilter = BinaryErodeImageFilterType::New(); 1022 | binaryErodeFilter->SetInput(this->itkImg); 1023 | binaryErodeFilter->SetKernel(structuringElement); 1024 | binaryErodeFilter->Update(); 1025 | 1026 | typedef itk::BinaryDilateImageFilter BinaryDilateImageFilterType; 1027 | BinaryDilateImageFilterType::Pointer binaryDilateFilter = BinaryDilateImageFilterType::New(); 1028 | binaryDilateFilter->SetInput(this->itkImg); 1029 | binaryDilateFilter->SetKernel(structuringElement); 1030 | binaryDilateFilter->Update(); 1031 | 1032 | typedef itk::SubtractImageFilter SubtractType; 1033 | SubtractType::Pointer diff = SubtractType::New(); 1034 | 1035 | switch (this->processType) 1036 | { 1037 | case 0: 1038 | { 1039 | diff->SetInput1(binaryDilateFilter->GetOutput()); 1040 | diff->SetInput2(binaryErodeFilter->GetOutput()); 1041 | diff->Update(); 1042 | break; 1043 | } 1044 | case 1: 1045 | { 1046 | diff->SetInput1(binaryDilateFilter->GetOutput()); 1047 | diff->SetInput2(this->itkImg); 1048 | diff->Update(); 1049 | break; 1050 | } 1051 | case 2: 1052 | { 1053 | diff->SetInput1(this->itkImg); 1054 | diff->SetInput2(binaryErodeFilter->GetOutput()); 1055 | diff->Update(); 1056 | break; 1057 | } 1058 | default: 1059 | break; 1060 | } 1061 | 1062 | this->itkImg = diff->GetOutput(); 1063 | this->itkImgProcess = itkShow2process(this->itkImg); 1064 | QImage image = itk2qImg(this->itkImg); 1065 | this->refreshImg(&image); 1066 | } 1067 | else 1068 | { 1069 | float kernelValue = 1; 1070 | 1071 | typedef itk::Neighborhood KernelType; 1072 | KernelType neighborhood; 1073 | neighborhood.SetRadius(kernelValue); 1074 | for (unsigned int i = 0; i < neighborhood.GetSize()[0] * neighborhood.GetSize()[1]; ++i) 1075 | { 1076 | neighborhood[i] = 1; 1077 | } 1078 | 1079 | typedef itk::GrayscaleFunctionErodeImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleErodeImageFilterType; 1080 | GrayscaleErodeImageFilterType::Pointer erodeFilter = GrayscaleErodeImageFilterType::New(); 1081 | erodeFilter->SetInput(this->itkImgProcess); 1082 | erodeFilter->SetKernel(neighborhood); 1083 | erodeFilter->Update(); 1084 | 1085 | typedef itk::GrayscaleDilateImageFilter< ImageTypeProcess, ImageTypeProcess, KernelType > GrayscaleDilateImageFilterType; 1086 | GrayscaleDilateImageFilterType::Pointer dilateFilter = GrayscaleDilateImageFilterType::New(); 1087 | dilateFilter->SetInput(this->itkImgProcess); 1088 | dilateFilter->SetKernel(neighborhood); 1089 | dilateFilter->Update(); 1090 | 1091 | typedef itk::SubtractImageFilter SubtractType; 1092 | SubtractType::Pointer diff = SubtractType::New(); 1093 | 1094 | switch (this->processType) 1095 | { 1096 | case 0: 1097 | { 1098 | diff->SetInput1(dilateFilter->GetOutput()); 1099 | diff->SetInput2(erodeFilter->GetOutput()); 1100 | diff->Update(); 1101 | break; 1102 | } 1103 | case 1: 1104 | { 1105 | diff->SetInput1(dilateFilter->GetOutput()); 1106 | diff->SetInput2(this->itkImgProcess); 1107 | diff->Update(); 1108 | break; 1109 | } 1110 | case 2: 1111 | { 1112 | diff->SetInput1(this->itkImgProcess); 1113 | diff->SetInput2(erodeFilter->GetOutput()); 1114 | diff->Update(); 1115 | break; 1116 | } 1117 | default: 1118 | break; 1119 | } 1120 | 1121 | this->itkImg = itkProcess2show(diff->GetOutput()); 1122 | this->itkImgProcess = itkShow2process(this->itkImg); 1123 | QImage image = itk2qImg(this->itkImg); 1124 | this->refreshImg(&image); 1125 | } 1126 | } 1127 | 1128 | void viewer::sendMask() 1129 | { 1130 | emit maskInfo(this->itkImg, this->itkImgProcess); 1131 | } 1132 | 1133 | void viewer::sendItk() 1134 | { 1135 | emit itkInfo(this->itkImg); 1136 | } 1137 | 1138 | void viewer::maskDilate(ImageType::Pointer itkMaskImg, ImageTypeProcess::Pointer itkMaskImgProcess) 1139 | { 1140 | if (this->isThreshold(this->itkImg)) 1141 | { 1142 | if (this->isThreshold(itkMaskImg)) 1143 | { 1144 | typedef itk::BinaryReconstructionByDilationImageFilter BinaryReconstructionImageFilterType; 1145 | BinaryReconstructionImageFilterType::Pointer binaryReconstructionFilter = BinaryReconstructionImageFilterType::New(); 1146 | binaryReconstructionFilter->SetMarkerImage(this->itkImg); 1147 | binaryReconstructionFilter->SetMaskImage(itkMaskImg); 1148 | binaryReconstructionFilter->Update(); 1149 | this->itkImg = binaryReconstructionFilter->GetOutput(); 1150 | this->itkImgProcess = itkShow2process(this->itkImg); 1151 | QImage image = itk2qImg(this->itkImg); 1152 | this->refreshImg(&image); 1153 | } 1154 | } 1155 | else 1156 | { 1157 | if (!this->isThreshold(itkMaskImg)) 1158 | { 1159 | typedef itk::ReconstructionImageFilter> ReconstructionImageFilterType; 1160 | ReconstructionImageFilterType::Pointer reconstructionFilter = ReconstructionImageFilterType::New(); 1161 | reconstructionFilter->SetMarkerImage(this->itkImgProcess); 1162 | reconstructionFilter->SetMaskImage(itkMaskImgProcess); 1163 | reconstructionFilter->Update(); 1164 | this->itkImgProcess = reconstructionFilter->GetOutput(); 1165 | this->itkImg = itkProcess2show(this->itkImgProcess); 1166 | QImage image = itk2qImg(this->itkImg); 1167 | this->refreshImg(&image); 1168 | } 1169 | } 1170 | } --------------------------------------------------------------------------------