多帧渲染更改

main
caiyiling 2025-04-22 13:42:58 +08:00
parent aea6a3f8c8
commit 4ff9a7c482
3 changed files with 119 additions and 34 deletions

View File

@ -27,6 +27,7 @@
:visit-task-info="s"
:markedSeriesIds="markedSeriesIds"
@activeSeries="activeSeries"
@showMultiFrame="showMultiFrame"
/>
</div>
@ -436,7 +437,8 @@ import {
// metaData,
getRenderingEngine,
eventTarget,
utilities as csUtils
utilities as csUtils,
cache
} from '@cornerstonejs/core'
import {
annotation
@ -754,11 +756,12 @@ export default {
const res1 = await getReadingVisitStudyList(this.trialId, sujectVisitId, taskId)
let keyStudyIndex = -1
let keySeriesIndex = -1
// const arr = res1.Result.filter(i => !i.IsCriticalSequence)
// const arr = [res1.Result[0]]
const arr = res1.Result
arr.forEach((study, studyIndex) => {
arr.forEach((study, studyIndex) => {
study.SeriesList.forEach((series, seriesIndex) => {
const imageIds = []
const stack = []
series.InstanceInfoList.forEach((instance, instanceIndex) => {
if (study.IsCriticalSequence) {
keyStudyIndex = studyIndex
@ -773,18 +776,19 @@ export default {
const nFrames = instance.NumberOfFrames || 0
if (nFrames === 0) {
//
imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`)
stack.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`)
} else {
//
for (let i = 0; i < nFrames; i++) {
const newImageId = `wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}&frame=${i + 1}`
imageIds.push(newImageId)
stack.push(newImageId)
}
}
imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`)
this.instanceInfo[instance.Id] = { taskIndex, studyIndex, seriesIndex }
}
})
series.Stack = stack
series.ImageIds = imageIds
series.SliceIndex = 0
series.LoadedImageCount = 0
@ -879,7 +883,7 @@ export default {
//
async initLoader() {
await initLibraries()
cache.setMaxCacheSize(6 * 1024 * 1024 * 1024);
let renderingEngine = getRenderingEngine(renderingEngineId)
if (!renderingEngine) {
renderingEngine = new RenderingEngine(renderingEngineId)
@ -1610,6 +1614,7 @@ export default {
},
//
scrollPage(type) {
this.clipPlaying = false
this.$refs[`viewport-${this.activeViewportIndex}`][0].scrollPage(type)
},
//
@ -1822,6 +1827,16 @@ export default {
}
this.setToolsPassive()
},
async showMultiFrame(obj) {
this.$refs[`viewport-${this.activeViewportIndex}`][0].setSeriesInfo(obj, true)
this.clipPlaying = false
this.fps = 15
if (this.activeViewportIndex === this.cells.length - 1) {
this.lastViewportTaskId = obj.TaskInfo.VisitTaskId
this.currentVisitInfo = obj.TaskInfo
}
this.setToolsPassive()
},
//
activeViewport(index) {
if (this.activeViewportIndex === index) return
@ -1861,8 +1876,8 @@ export default {
const idx = similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1
if (idx > -1) {
obj = Object.assign({}, seriesList[idx])
const imageIds = seriesList[idx].ImageIds
const sliceIdx = Math.floor(imageIds.length * ((baselineSeries.SliceIndex + 1) / baselineSeries.ImageIds.length))
const stack = seriesList[idx].Stack
const sliceIdx = Math.floor(stack.length * ((baselineSeries.SliceIndex + 1) / baselineSeries.Stack.length))
// let sliceIdx = Math.floor(imageIds.length / 2)
obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0
}
@ -1872,8 +1887,8 @@ export default {
const idx = seriesList.findIndex(series => series.InstanceCount === baselineSeries.InstanceCount)
if (idx > -1) {
obj = Object.assign({}, seriesList[idx])
const imageIds = seriesList[idx].ImageIds
const sliceIdx = Math.floor(imageIds.length / 2)
const stack = seriesList[idx].Stack
const sliceIdx = Math.floor(stack.length / 2)
obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0
}
}
@ -1882,8 +1897,8 @@ export default {
const idx = seriesList.findIndex(series => series.IsDicom && parseInt(series.SliceThickness) === 5)
if (idx > -1) {
obj = Object.assign({}, seriesList[idx])
const imageIds = seriesList[idx].ImageIds
const sliceIdx = Math.floor(imageIds.length / 2)
const stack = seriesList[idx].Stack
const sliceIdx = Math.floor(stack.length / 2)
obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0
}
}
@ -1897,8 +1912,8 @@ export default {
const seriesIdx = studyList[k].SeriesList.findIndex(s => s.SliceThickness && parseInt(s.SliceThickness) === 5)
if (seriesIdx > -1) {
obj = Object.assign({}, studyList[k].SeriesList[seriesIdx])
const imageIds = studyList[k].SeriesList[seriesIdx].ImageIds
const sliceIdx = Math.floor(imageIds.length / 2)
const stack = studyList[k].SeriesList[seriesIdx].Stack
const sliceIdx = Math.floor(stack.length / 2)
obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0
obj.IsMarked = false
break
@ -1910,8 +1925,8 @@ export default {
const sIdx = studyList.findIndex(s => s.IsDicom)
if (sIdx > -1) {
obj = Object.assign({}, studyList[sIdx].SeriesList[0])
const imageIds = studyList[sIdx].SeriesList[0].ImageIds
const sliceIdx = Math.floor(imageIds.length / 2)
const stack = studyList[sIdx].SeriesList[0].Stack
const sliceIdx = Math.floor(stack.length / 2)
obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0
obj.IsMarked = false
}
@ -1936,8 +1951,8 @@ export default {
} else {
filterStr = `instanceId=${annotation.InstanceId}`
}
const imageIds = seriesList[seriesIdx].ImageIds
const imageIdIdx = imageIds.findIndex(is => is.includes(filterStr))
const stack = seriesList[seriesIdx].Stack
const imageIdIdx = stack.findIndex(is => is.includes(filterStr))
if (imageIdIdx > -1) {
obj = Object.assign({}, seriesList[seriesIdx])
obj.SliceIndex = imageIdIdx

View File

@ -65,8 +65,34 @@
/>
</div>
<div class="series-text">
<div v-if="series.IsExistMutiFrames && series.InstanceCount > 1"
style="position: absolute;right: 0;top: 0;">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div class="frame_list">
<div
v-for="(instance, idx) in series.InstanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.InstanceInfoList.length-1? '5px':'0px'}"
@click.stop="showMultiFrames(index,series, i, instance)"
>
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;color: #ffeb3b;" />
</el-popover>
</div>
<div v-if="!study.IsCriticalSequence" class="text-desc" :title="series.SeriesNumber">
#{{ series.SeriesNumber }}
</div>
<div v-if="series.Description" class="text-desc" :title="series.Description">
{{ series.Description }}
@ -154,6 +180,31 @@ export default {
if (!studyId) return
this.activeStudy(studyId)
},
showMultiFrames(studyIndex, series, seriesIndex, instance) {
let obj = Object.assign({}, series)
this.activeStudyIndex = studyIndex
this.activeSeriesIndex = seriesIndex
let taskId = this.visitTaskInfo.VisitTaskId
const nFrames = instance.NumberOfFrames || 0
let imageIds = []
const stack = []
if (nFrames === 0) {
//
stack.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`)
} else {
//
for (let i = 0; i < nFrames; i++) {
const newImageId = `wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}&frame=${i + 1}`
stack.push(newImageId)
}
}
imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`)
obj.Stack = stack
obj.ImageIds = imageIds
obj.SliceIndex = 0
this.$emit('showMultiFrame', obj)
},
getPreviousOrNextSeries(type, series) {
const seriseList = this.studyList.map(s => s.SeriesList).flat()
const i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId)
@ -242,6 +293,7 @@ export default {
flex: 1;
padding-left: 5px;
color: #ddd;
position: relative;
.text-desc {
width: 100px;
white-space: nowrap;

View File

@ -26,7 +26,7 @@
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
</h2>
<div>Series: #{{ series.SeriesNumber }}</div>
<div>Image: #{{ `${series.SliceIndex + 1}/${series.ImageIds.length}` }}</div>
<div v-if="series.Stack">Image: #{{ `${series.SliceIndex + 1}/${series.Stack.length}` }}</div>
<div>{{ series.Modality }}</div>
</div>
<div
@ -110,6 +110,7 @@ import {
utilities as csUtils
} from '@cornerstonejs/core'
import * as cornerstoneTools from '@cornerstonejs/tools'
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
const {
ToolGroupManager
} = cornerstoneTools
@ -194,7 +195,7 @@ export default {
stackNewImage(e) {
const { detail } = e
this.series.SliceIndex = detail.imageIdIndex
this.sliderInfo.height = detail.imageIdIndex * 100 / (this.series.ImageIds.length - 1)
this.sliderInfo.height = detail.imageIdIndex * 100 / (this.series.Stack.length - 1)
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
const zoom = viewport.getZoom()
@ -311,6 +312,7 @@ export default {
newImageIdIndex = numImages - 1
}
viewport.setImageIdIndex(newImageIdIndex)
cornerstoneTools.utilities.cine.stopClip(viewport.element)
},
setZoom(ratio) {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
@ -329,16 +331,32 @@ export default {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
renderingEngine.resize(true, forceFitToWindow)
},
async setSeriesInfo(obj, isLocate = false) {
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) {
obj.SliceIndex = this.series.SliceIndex
async prefetchMetadataInformation(imageIdsToPrefetch) {
let taskPromises = []
for (let i = 0; i < imageIdsToPrefetch.length; i++) {
taskPromises.push(cornerstoneDICOMImageLoader.wadouri.loadImage(imageIdsToPrefetch[i]).promise)
if (taskPromises.length >= 6 || i === imageIdsToPrefetch.length - 1) {
await Promise.all(taskPromises)
taskPromises = []
}
}
this.series = { ...obj }
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
await viewport.setStack(obj.ImageIds, obj.SliceIndex)
cornerstoneTools.utilities.stackPrefetch.enable(viewport.element)
viewport.render()
},
async setSeriesInfo(obj, isLocate = false) {
try {
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) {
obj.SliceIndex = this.series.SliceIndex
}
this.series = { ...obj }
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
await this.prefetchMetadataInformation(obj.ImageIds)
await viewport.setStack(this.series.Stack, obj.SliceIndex)
// cornerstoneTools.utilities.stackContextPrefetch.enable(viewport.element)
viewport.render()
} catch(e) {
console.log(e)
}
},
cornerstoneToolsMouseMove(e) {
const { currentPoints } = e.detail
@ -373,8 +391,8 @@ export default {
clickSlider(e) {
const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
this.sliderInfo.height = height
let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100)
sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
let sliceIdx = Math.trunc(this.series.Stack.length * height / 100)
sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(
this.viewportId
@ -401,8 +419,8 @@ export default {
if (delta < 0) return
if (delta > boxHeight) return
const height = delta * 100 / boxHeight
let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100)
sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
let sliceIdx = Math.trunc(this.series.Stack.length * height / 100)
sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
this.sliderInfo.height = height
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(