首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于DICOM Monochrome2绘制的像素映射

用于DICOM Monochrome2绘制的像素映射
EN

Stack Overflow用户
提问于 2020-07-19 07:05:06
回答 2查看 504关注 0票数 1

试图将dicom monochrome2呈现到HTML5画布上

  1. 从灰度到画布rgb的正确像素映射是什么?

代码语言:javascript
复制
- Currently using **incorrect** mapping of
const ctx = canvas.getContext( '2d' )    const imageData = ctx.createImageData( 512, 512 )    const pixelData = getPixelData( dataSet )     let rgbaIdx = 0    let rgbIdx = 0    let pixelCount = 512 \* 512    for ( let idx = 0; idx < pixelCount; idx++ ) {        imageData.data[ rgbaIdx ] = pixelData[ rgbIdx ]        imageData.data[ rgbaIdx + 1 ] = pixelData[ rgbIdx + 1 ]        imageData.data[ rgbaIdx + 2 ] = 0        imageData.data[ rgbaIdx + 3 ] = 255        rgbaIdx += 4        rgbIdx += 2    }    ctx.putImageData( imageData, 0, 0 )        

  1. 通过开放源码库阅读,不太清楚怎么做,请您建议清楚地介绍如何呈现?

图1.不正确的映射

图2.正确的映射,dicom显示在IrfanView中

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-02 05:24:19

结果证明了需要做的四件主要事情(阅读fo-dicom源代码来找出这些事情)

  1. 制备Monochrome2 LUT

导出const LutMonochrome2 = () => { let lut = [] for (设idx = 0,byt = 255;idx++,byt-){ // r,g,b,a lut.push( byt,0xff )}返回lut }

  1. 将像素数据解释为无符号短

导出const bytesToShortSigned =(字节) => { let byteA =1 let byteB =byteB 0 let pixelVal const符号= byteA & (1 << 7);pixelVal =(byteA& 0xFF) << 8) << (byteB & 0xFF));if (符号){ pixelVal =0xFFF0000 pixelVal;//使用1's }返回pixelVal返回的最重要位

}

  1. 得到最小和最大像素值,然后计算WindowWidth,最终将每个像素映射到Monochrome2颜色映射。

导出const getMinMax =( pixelData ) => { let pixelCount = pixelData.length let min = 0,max =0 for (设idx = 0;+= 2){ let pixelVal = bytesToShortSigned( [ pixelDataidx,pixelDataidx+1 ]) if (pixelVal < min) min = pixelVal if (pixelVal > max) max = pixelVal }返回{ min,max }

  1. 最终抽签

({ dataSet,画布}) => { const monochrome2 = LutMonochrome2() const ctx = canvas.getContext( '2d‘) const imageData = ctx.createImageData( 512,512 ) const pixelData = getPixelData( dataSet )让pixelCount = pixelData.length使{ min: minPixel,max: maxPixel }= getMinMax( pixelData - );让=(+)/ 2.0;()让=0( let idx = 0;idx <;+= 2){ let pixelVal = bytesToShortSigned( [ pixelDataidx,pixelDataidx+1 ])设binIdx = Math.floor( (pixelVal - minPixel) / windowWidth * 256 );设displayVal = monochrome2 binIdx if ( displayVal == null ) displayVal = 0,0,0,255 imageData.data rgbaIdx = displayVal imageData.data rgbaIdx +1= displayVal1 imageData.data rgbaIdx +2= displayVal2 imageData.data rgbaIdx +3= rgbaIdx 4}(,0,0)}en23#

票数 1
EN

Stack Overflow用户

发布于 2020-07-19 09:36:32

这里有两个问题:您的单色数据的分辨率(例如值范围)比在RGB中显示的要高,所以您不能直接将像素数据映射到RGB数据中。

值范围取决于Bits Stored标记-对于典型的值12,数据范围将为4096。最简单的实现可以将这个数字缩小,在本例中是16。

代码的第二个问题:要在RGB中表示单色值,必须添加3个具有相同值的颜色组件:

代码语言:javascript
复制
let rgbaIdx = 0
let rgbIdx = 0
let pixelCount = 512 * 512
let scaleFactor = 16 // has to be calculated in real code
for ( let idx = 0; idx < pixelCount; idx++ ) {
    # assume Little Endian
    let pixelValue = pixelData[ rgbIdx ] + pixelData[ rgbIdx + 1 ] * 256
    let displayValue = Math.round(pixelValue / scaleFactor)
    imageData.data[ rgbaIdx ] = displayValue
    imageData.data[ rgbaIdx + 1 ] = displayValue
    imageData.data[ rgbaIdx + 2 ] = displayValue
    imageData.data[ rgbaIdx + 3 ] = 255
    rgbaIdx += 4
    rgbIdx += 2
}

为了得到更好的表示,你必须考虑到VOI LUT,而不仅仅是缩小比例。如果定义了Window Center / Window Width标记,则可以计算最小值和最大值,并从该范围获得比例因子:

代码语言:javascript
复制
let minValue = windowCenter - windowWidth / 2
let maxValue = windowCenter + windowWidth / 2
let scaleFactor = (maxValue - minValue) / 256
...
   let pixelValue = pixelData[ rgbIdx ] + pixelData[ rgbIdx + 1 ] * 256
   let displayValue = max((pixelValue - minValue) / scaleFactor), 255)
   ...

编辑:正如@WilfRosenbaum所观察到的:如果您没有VOI (如WindowCenter和WindowWidth的空值所建议的那样),那么最好自己计算一个。为此,必须计算像素数据的最小/最大值:

代码语言:javascript
复制
let minValue = 1 >> 16
let maxValue = 0
for ( let idx = 0; idx < pixelCount; idx++ ) {
    let pixelValue = pixelData[ rgbIdx ] + pixelData[ rgbIdx + 1 ] * 256
    minValue = min(minValue, pixelValue)
    maxValue = max(maxValue, pixelValue)
}
let scaleFactor = (maxValue - minValue) / 256

然后使用与VOI LUT相同的代码。

几个注意事项:

  • 如果您有一个模式LUT,您必须在value之前应用它;CT图像通常有一个(Rescale斜率/RescaleIntercept),尽管这个只有一个标识LUT,所以您可以忽略它
  • 您可以有多个WindowCenter / WindowWindow值对,或者可能有一个value序列,这在这里也没有考虑--
  • --代码超出了我的大脑,所以它可能有bug

< code >F 215

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62977280

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档