日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

肺部CT图像分割及重建系统

發布時間:2023/12/29 windows 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 肺部CT图像分割及重建系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、 系統概況

我們實現了一個系統,可以從CT圖像中將肺部從胸腔中分離出來,并且通過三維重建實現可視化。該系統是基于Visual Studio 2013平臺,借助VTK-7.0和Qt5.6開源庫通過C++語言實現。

二、 系統設計

肺部CT圖像分割及重建系統的實現需要幾個方面的工作,一是CT圖像的肺部分割;二是CT圖像的三維重建;三是可視化界面的設計。
根據工作內容的不同,需要用到不同的開源庫。我們通過VTK實現了CT圖像的三維重建,包含體繪制和面繪制兩種重建算法;通過Qt實現了UI的設計。因此在windows10環境下用VS2013編譯支持Qt的VTK庫,是前期的準備工作。
在肺部分割這一部分工作上,我們采用以閾值分割為主,其余簡單圖像處理操作如濾波操作等為輔,進行肺部的分割。

三、系統實現(含源代碼)

3.1 前期準備工作——Windows10環境下用VS2013編譯支持Qt的VTK庫

網上有大量的相關文章,但由于VTK,VS,Qt的版本不同,可能導致Qt與VTK的聯動失敗。在此,我們參考了兩位博主的搭建方式:
(1) http://www.cnblogs.com/tianhu9102/p/7641397.html
(2) https://blog.csdn.net/u011017966/article/details/40984473
這兩篇文章對應兩種不同的搭建方式,一種是在兩種庫編譯成功后通過直接添加庫目錄,包含目錄的方法實現VTK與Qt聯動;另一種則跳過了添加庫目錄,包含目錄等繁瑣操作,程序全部用cmake來管理,直接通過cmake進行編譯實現一個工程文件。
經過驗證,兩種方法均可實現VTK + QT的聯動。

3.2三維重建的實現

我們采用了兩種三維重建方法:體繪制和面繪制。
面繪制是將感興趣的部分以等值面的形式抽取出來便于利用真實感技術,通過任意旋轉和變換光照效果來生成高質量的三維圖像,并可以方便的對其進行觀察和分析。
面繪制的代碼如下:

void MainWindow::open(){//抽取等值面為骨頭的信息 vtkSmartPointer< vtkMarchingCubes > boneExtractor =vtkSmartPointer< vtkMarchingCubes >::New();boneExtractor->SetInputConnection(threshould->GetOutputPort());//boneExtractor->SetValue(0, 500); //設置提取的等值信息boneExtractor->SetValue(0, 1000);boneExtractor->SetNumberOfContours(1);boneExtractor->Update();//剔除舊的或廢除的數據單元,提高繪制速度(可略去這一步) vtkSmartPointer< vtkStripper > boneStripper =vtkSmartPointer< vtkStripper >::New(); //三角帶連接 boneStripper->SetInputConnection(boneExtractor->GetOutputPort());boneStripper->Update();//建立映射 vtkSmartPointer< vtkPolyDataMapper > boneMapper =vtkSmartPointer< vtkPolyDataMapper >::New();boneMapper->SetInputData(boneStripper->GetOutput());boneMapper->ScalarVisibilityOff();//建立角色 vtkSmartPointer< vtkActor > bone =vtkSmartPointer< vtkActor >::New();bone->SetMapper(boneMapper);bone->GetProperty()->SetDiffuseColor(.1, .94, .52);bone->GetProperty()->SetSpecular(.3);bone->GetProperty()->SetSpecularPower(20);bone->GetProperty()->SetOpacity(1.0);bone->GetProperty()->SetColor(1,1,1);bone->GetProperty()->SetRepresentationToSurface();//定義繪制器 vtkSmartPointer< vtkRenderer > aRenderer =vtkSmartPointer< vtkRenderer >::New();//定義繪制窗口 vtkSmartPointer< vtkRenderWindow > renWin = ui->qvtkWidget_Volume->GetRenderWindow();//vtkSmartPointer< vtkRenderWindow >::New();renWin->AddRenderer(aRenderer);//定義窗口交互器 vtkSmartPointer< vtkRenderWindowInteractor > iren =vtkSmartPointer< vtkRenderWindowInteractor >::New();iren->SetRenderWindow(renWin);//創建一個camera vtkSmartPointer< vtkCamera > aCamera =vtkSmartPointer< vtkCamera >::New();aCamera->SetViewUp(0, 0, -1);aCamera->SetPosition(0, 1, 0);aCamera->SetFocalPoint(0, 0, 0);aRenderer->AddActor(bone);aRenderer->SetActiveCamera(aCamera);aRenderer->ResetCamera();aCamera->Dolly(1.5);aRenderer->SetBackground(0, 0, 0);aRenderer->ResetCameraClippingRange();vtkInteractorStyleTrackballCamera *style = //設置交互方式vtkInteractorStyleTrackballCamera::New();iren->SetInteractorStyle(style);iren->Initialize();iren->Start(); }

體繪制的原理和面繪制完全不相同。面繪制需要生成中間圖元,而體繪制則是直接在原圖上進行繪制,內容需求較面繪制小。每切換一個視角需要重新對所有的像素點進行顏色和透明度計算,需要時間比面繪制長。VTK中基于體繪制實現三維重建,使用的是光線投射法(Ray-casting)。
體繪制的具體代碼如下:

void MainWindow::volume(){VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper =vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();volumeMapper->SetInputConnection(threshould->GetOutputPort());volumeMapper->SetBlendModeToComposite();volumeMapper->SetSampleDistance(0.3);volumeMapper->AutoAdjustSampleDistancesOff();vtkSmartPointer<vtkVolumeProperty> volumeProperty =vtkSmartPointer<vtkVolumeProperty>::New();volumeProperty->SetInterpolationTypeToLinear();volumeProperty->ShadeOn(); //打開或者關閉陰影測試 volumeProperty->SetAmbient(0.2);volumeProperty->SetDiffuse(1.2); //漫反射 volumeProperty->SetSpecular(0.1); //鏡面反射 volumeProperty->SetSpecularPower(10);//設置不透明度 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity->AddPoint(70, 0.00);compositeOpacity->AddPoint(90, 0.40);compositeOpacity->AddPoint(180, 0.60);volumeProperty->SetScalarOpacity(compositeOpacity); //設置不透明度傳輸函數 //設置梯度不透明屬性 vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity =vtkSmartPointer<vtkPiecewiseFunction>::New();volumeGradientOpacity->AddPoint(10, 0.0);volumeGradientOpacity->AddPoint(90, 0.5);volumeGradientOpacity->AddPoint(100, 1.0);volumeProperty->SetGradientOpacity(volumeGradientOpacity);//設置梯度不透明度效果對比 //設置顏色屬性 vtkSmartPointer<vtkColorTransferFunction> color =vtkSmartPointer<vtkColorTransferFunction>::New();color->AddRGBPoint(64.00, 1.00, 0.52, 0.30);volumeProperty->SetColor(color);/********************************************************************************/vtkSmartPointer<vtkVolume> volume =vtkSmartPointer<vtkVolume>::New();volume->SetMapper(volumeMapper);volume->SetProperty(volumeProperty);vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();ren->SetBackground(0, 0, 0);ren->AddVolume(volume);vtkSmartPointer<vtkRenderWindow> rw =ui->qvtkWidget_Volume_6->GetRenderWindow();rw->AddRenderer(ren);rw->Render();vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(rw);vtkInteractorStyleTrackballCamera *st = //設置交互方式vtkInteractorStyleTrackballCamera::New();rwi->SetInteractorStyle(st);/********************************************************************************/ren->ResetCamera();rw->Render(); }

3.3 UI設計

Qt的UI界面設計如下圖所示:

我們主要用到了Qt的幾個常用Widget:
PushButton:用于啟動某個功能
horizontalScrollBar: 用于手動調整上界閾值和下界閾值
textEdit:用于輸入圖像分割的矩形框大小(后面分割會提到)
textBrowser: 用于顯示程序運行狀態

3.4 分割操作的實現

為了盡可能提高分割的效果,我們采用了多管齊下的方法。
首先,我們設置了以交互的方式,讓用戶輸入上界閾值和下界閾值,則CT圖像的CT值在這個閾值內的保留原值不變,小于下界閾值的變黑,大于上界閾值的變白。

void MainWindow::segmentBetween(){int upper, lower;// 從滑條里分別獲取上界和下界閾值upper = ui->horizontalScrollBar->value();lower = ui->horizontalScrollBar_2->value();threshould->ThresholdBetween(lower, upper);// 利用ThresholdBetween進行分割threshould->SetInValue(1024);threshould->SetOutValue(-1024);threshould->Update(); //算法執行后必須添加的更新消息slice(); }

其次,因為CT原圖像中有CT機床等干擾,我們在原CT圖像上進行截取,只需輸入矩形框的兩個對角頂點的坐標,就可以輕松截取框內的圖像,框外的圖像全部置黑。
最后,我們發現通過簡單的閾值分割并不能很好地去除一些細節上的噪聲和胸腔組織,因此我們寫了一個簡單的濾波算法,進行濾波操作,根據該像素點的鄰域是否具有像素值進行判斷,從而極大程度上去除了噪聲,取得了不錯的分割效果。

void MainWindow::Filter(){int dims[3];int upperNum, upperNum2, upperNum3, upperNum4;QString upper, upper2, upper3, upper4;upper = ui->textEdit->document()->toPlainText();upperNum = upper.toInt();upper2 = ui->textEdit_2->document()->toPlainText();upperNum2 = upper2.toInt();upper3 = ui->textEdit_3->document()->toPlainText();upperNum3 = upper3.toInt();upper4 = ui->textEdit_4->document()->toPlainText();upperNum4 = upper4.toInt();reader->GetOutput()->GetDimensions(dims);for (int k = 0; k < dims[2] ; k++){for (int j = 0; j < dims[1] ; j++){for (int i = 0; i < dims[0] ; i++){short *pixel = (short *)(threshould->GetOutput()->GetScalarPointer(i, j, k));if (j < upperNum2 || j > upperNum4)*pixel = -1024;if (i < upperNum || i > upperNum3)*pixel = -1024;if ((j > 5) && (j < dims[1] - 6)){short *pixel2 = (short *)(threshould->GetOutput()->GetScalarPointer(i, j + 5, k));short *pixel3 = (short *)(threshould->GetOutput()->GetScalarPointer(i, j - 5, k));if ((*pixel2 < -500) && (*pixel3 <-500))*pixel = -1024;}}}}threshould->Update();slice(); }

四、結果展示






分割:手動設置上界閾值和下界閾值,并在去噪輸入框內輸入矩形框的對角頂點坐標,則可達到分割的效果。
顯示:左上為三維重建的體繪制(左)和面繪制(右),可以通過鼠標拖動,從不同視角觀看肺部結構。右邊為水平面,矢狀面,冠狀面的顯示,通過拖動進度條可以看不同層的截面顯示。

資源已經上傳:
https://download.csdn.net/download/h_swhite/10901427

總結

以上是生活随笔為你收集整理的肺部CT图像分割及重建系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。