Здесь есть две проблемы: ваши монохромные данные имеют более высокое разрешение (например, диапазон значений), чем могут отображаться в RGB, поэтому вы не можете просто напрямую преобразовать данные пикселей в данные RGB.
Диапазон значений зависит от Bits Stored
тег — для типичного значения 12 диапазон данных будет 4096. Простейшая реализация может просто уменьшить число, в данном случае на 16.
Вторая проблема с вашим кодом: для представления монохромного значения в RGB вам нужно добавить 3 компонента цвета с одинаковым значением:
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
, вы можете вычислить минимальное и максимальное значения и получить коэффициент масштабирования из этого диапазона:
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 LUT (как предполагают пустые значения WindowCenter и WindowWidth), вам лучше всего рассчитать свой собственный. Для этого вам нужно рассчитать минимальные/максимальные значения ваших пиксельных данных:
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 модальности, вы должны применить ее до VOI LUT; Изображения CT обычно имеют один (RescaleSlope/RescaleIntercept), хотя у этого есть только LUT идентификации, поэтому вы можете его игнорировать.
- у вас может быть более одной пары значений
WindowCenter
/WindowWindow
или может быть последовательность VOI LUT, которая здесь также не рассматривается
- код вылетел из моей головы, поэтому в нем могут быть ошибки
person
MrBean Bremen
schedule
19.07.2020