cv2.imwrite не записывает правильные значения пикселей - PullRequest
2 голосов
/ 18 марта 2020

Я изучаю базу данных INbreast и пытаюсь конвертировать изображения DICOM в формат JPEG. Вот как должны выглядеть изображения DICOM при чтении их в виде массива numpy со следующим кодом:

ds = dicom.dcmread(img_path)
plt.imshow(ds.pixel_array)
plt.show()

enter image description here

Но когда я пытаюсь написать Изображение в формате JPEG выглядит следующим образом, я получаю неправильные значения пикселей:

cv2.imwrite("{new_img_path}.jpeg", ds.pixel_array)
img = cv2.imread("{new_img_path}.jpeg")
plt.imshow(img)
plt.show()

enter image description here

Кто-нибудь знает, как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Ответ в основном это комбинации предложений от Густаво Кането и unlut .

Сначала мне нужно преобразовать из DICOM в PNG как Густаво Кането предложил. После этого мне нужно прочитать его в градациях серого, используя флаг cv2.IMREAD_GRAYSCALE, как предложено до . В результате я получаю действительные значения пикселей:

enter image description here

0 голосов
/ 18 марта 2020

После некоторых комментариев @unlut мы знаем, что ваши данные - это uint16 и один канал.

Итак, я проверил здесь несколько тестовых кодов ...

При сохранении в .jpeg , cv.imwrite() обрезать значения до диапазона uint8 (0-255).

Простое решение - сохранить файл в .png, который принимает значения uint16.

Если вам нужен формат jpeg, вам придется конвертировать ваш uint16 в uint8 до cv.imwrite(). (Обратите внимание, что в любом случае cv.imshow() покажет ваши данные (ds.pixelarray) правильно до сохранения файла в jpeg.)

Код для проверки cv.imwrite()

import cv2 as cv
import numpy as np
import random as rng

# create an uint16 one-channel image with random pixel values in the range 0-65535
image16 = np.ones((200,200), dtype=np.uint16)
x, y = image16.shape
for i in range(x):
    for j in range(y):
        image16[i][j] *= rng.randint(0,65535)

# use cv to write it in JPEG and PNG formats
cv.imwrite('img16.jpeg',image16)
cv.imwrite('img16.png',image16)

# convert to uint8 then save again
image8 = image16.astype('uint8')
cv.imwrite('img8.jpeg',image8)
cv.imwrite('img8.png',image8)

cv.waitKey()

Результаты от imwrite():

enter image description here

Обратите внимание, что данные uint16, сохраненные в формате jpeg, приводят к отсечке более высоких значений ( т.е. все значения больше 255 будут 255 и будут отображаться белым цветом).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...