多帧渲染更改

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

View File

@ -65,8 +65,34 @@
/> />
</div> </div>
<div class="series-text"> <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"> <div v-if="!study.IsCriticalSequence" class="text-desc" :title="series.SeriesNumber">
#{{ series.SeriesNumber }} #{{ series.SeriesNumber }}
</div> </div>
<div v-if="series.Description" class="text-desc" :title="series.Description"> <div v-if="series.Description" class="text-desc" :title="series.Description">
{{ series.Description }} {{ series.Description }}
@ -154,6 +180,31 @@ export default {
if (!studyId) return if (!studyId) return
this.activeStudy(studyId) 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) { getPreviousOrNextSeries(type, series) {
const seriseList = this.studyList.map(s => s.SeriesList).flat() const seriseList = this.studyList.map(s => s.SeriesList).flat()
const i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId) const i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId)
@ -242,6 +293,7 @@ export default {
flex: 1; flex: 1;
padding-left: 5px; padding-left: 5px;
color: #ddd; color: #ddd;
position: relative;
.text-desc { .text-desc {
width: 100px; width: 100px;
white-space: nowrap; white-space: nowrap;

View File

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