Javascript 用于渲染DICOM单色的像素映射2
尝试在HTML5画布上渲染dicom单色2Javascript 用于渲染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 =
- 当前使用的映射不正确
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
图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
值对,也可以有VOI LUT序列,这里也不考虑这一点WindowWindow
- 代码是我脑子里想不出来的,所以可能有bug
值范围取决于存储的
位
标记-对于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 )
}