Javascript 用于渲染DICOM单色的像素映射2

Javascript 用于渲染DICOM单色的像素映射2,javascript,html,dicom,monochrome,Javascript,Html,Dicom,Monochrome,尝试在HTML5画布上渲染dicom单色2 从灰度到画布rgb的正确像素映射是什么 当前使用的映射不正确 const ctx = canvas.getContext( '2d' ) const imageData = ctx.createImageData( 512, 512 ) const pixelData = getPixelData( dataSet ) let rgbaIdx = 0 let rgbIdx = 0 let pixelCount =

尝试在HTML5画布上渲染dicom单色2

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

    • 当前使用的映射不正确

         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 )        
      
      const ctx=canvas.getContext('2d')
      const imageData=ctx.createImageData(512)
      常量pixelData=getPixelData(数据集)
      设rgbaIdx=0
      设rgbIdx=0
      设pixelCount=512*512
      for(让idx=0;idx
  • 通读开源库,不太清楚如何呈现,请您明确介绍如何呈现

  • 图1。不正确的映射


    图2。正确的映射,IrfanView中显示的dicom这里有两个问题:单色数据的分辨率(例如值范围)高于RGB中显示的分辨率,因此不能直接将像素数据映射到RGB数据中。
    值范围取决于存储的
    标记-对于12的典型值,数据范围为4096。最简单的实现就是将数字缩小,在本例中为16

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

    设rgbaIdx=0
    设rgbIdx=0
    设pixelCount=512*512
    设scaleFactor=16//必须以实代码计算
    for(让idx=0;idx
    为了获得更好的表示,您必须考虑VOI LUT,而不仅仅是缩小规模。如果定义了
    窗口中心
    /
    窗口宽度
    标记,则可以计算最小值和最大值,并从该范围获得比例因子:

    让minValue=windowCenter-windowWidth/2
    设maxValue=windowCenter+windowWidth/2
    设scaleFactor=(maxValue-minValue)/256
    ...
    设pixelValue=pixelData[rgbIdx]+pixelData[rgbIdx+1]*256
    让displayValue=max((像素值-最小值)/scaleFactor),255)
    ...
    
    编辑:正如@WilfRosenbaum所观察到的:如果您没有VOI LUT(如WindowCenter和WindowWidth的空值所示),那么最好计算您自己的VOI LUT。为此,必须计算像素数据的最小/最大值:

    让minValue=1>>16
    设maxValue=0
    for(让idx=0;idx
    然后使用与VOI LUT相同的代码

    请注意:

    • 如果你有一个模态LUT,你必须在VOI LUT之前应用它;CT图像通常有一个(RescaleSlope/RescaleSintercept),尽管这个图像只有一个标识LUT,所以您可以忽略它
    • 您可以有多个
      WindowCenter
      /
      WindowWindow
      值对,也可以有VOI LUT序列,这里也不考虑这一点
    • 代码是我脑子里想不出来的,所以可能有bug

    这里有两个问题:单色数据的分辨率(例如值范围)高于RGB显示的分辨率,因此不能直接将像素数据映射到RGB数据中。
    值范围取决于存储的
    标记-对于12的典型值,数据范围为4096。最简单的实现就是将数字缩小,在本例中为16

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

    设rgbaIdx=0
    设rgbIdx=0
    设pixelCount=512*512
    设scaleFactor=16//必须以实代码计算
    for(让idx=0;idx
    为了获得更好的表示,您必须考虑VOI LUT,而不仅仅是缩小规模。如果定义了
    窗口中心
    /
    窗口宽度
    标记,则可以计算最小值和最大值,并从该范围获得比例因子:

    让minValue=windowCenter-windowWidth/2
    设maxValue=windowCenter+windowWidth/2
    设scaleFactor=(maxValue-minValue)/256
    ...
    设pixelValue=pixelData[rgbIdx]+pixelData[rgbIdx+1]*256
    让displayValue=max((像素值-最小值)/scaleFactor),255)
    ...
    
    编辑:正如@WilfRosenbaum所观察到的:如果您没有VOI LUT(如WindowCenter和WindowWidth的空值所示),那么最好计算您自己的VOI LUT。为此,必须计算像素数据的最小/最大值:

    让minValue=1>>16
    设maxValue=0
    for(让idx=0;idxexport const LutMonochrome2 = () => {
    
        let lut = []
        for ( let idx = 0, byt = 255; idx < 256; idx++, byt-- ) {
            // r, g, b, a
            lut.push( [byt, byt, byt, 0xff] )
        }
        return lut
    }
    
     export const bytesToShortSigned = (bytes) => {
     let byteA = bytes[ 1 ]
     let byteB = bytes[ 0 ]
     let pixelVal
    
     const sign = byteA & (1 << 7);
     pixelVal = (((byteA & 0xFF) << 8) | (byteB & 0xFF));
     if (sign) {
         pixelVal = 0xFFFF0000 | pixelVal;  // fill in most significant bits with 1's
     }
     return pixelVal
    
    export const getMinMax = ( pixelData ) => {
    
        let pixelCount = pixelData.length
        let min = 0, max = 0
    
        for ( let idx = 0; idx < pixelCount; idx += 2 ) {
            let pixelVal = bytesToShortSigned( [
                pixelData[idx],
                pixelData[idx+1]
            ]  )
    
            if (pixelVal < min)
                min = pixelVal
    
            if (pixelVal > max)
                max = pixelVal
        }
        return { min, max }
    }
    
    export const draw = ( { dataSet, canvas } ) => {
    
     const monochrome2 = LutMonochrome2()
    
     const ctx = canvas.getContext( '2d' )
     const imageData = ctx.createImageData( 512, 512 )
     const pixelData = getPixelData( dataSet )
     let pixelCount = pixelData.length
    
     let { min: minPixel, max: maxPixel } = getMinMax( pixelData )
    
     let windowWidth = Math.abs( maxPixel - minPixel );
     let windowCenter = ( maxPixel + minPixel ) / 2.0;
    
     console.debug( `minPixel: ${minPixel} , maxPixel: ${maxPixel}` )
    
     let rgbaIdx = 0
     for ( let idx = 0; idx < pixelCount; idx += 2 ) {
         let pixelVal = bytesToShortSigned( [
             pixelData[idx],
             pixelData[idx+1]
         ]  )
    
    
         let binIdx = Math.floor( (pixelVal - minPixel) / windowWidth * 256 );
    
         let displayVal = monochrome2[ binIdx ]
         if ( displayVal == null )
             displayVal = [ 0, 0, 0, 255]
    
         imageData.data[ rgbaIdx ] = displayVal[0]
         imageData.data[ rgbaIdx + 1 ] = displayVal[1]
         imageData.data[ rgbaIdx + 2 ] = displayVal[2]
         imageData.data[ rgbaIdx + 3 ] = displayVal[3]
         rgbaIdx += 4
     }
     ctx.putImageData( imageData, 0, 0 )
    
    }