Simpan array numpy 16-bit sebagai gambar PNG 16-bit

Sep 24 2020

Saya mencoba menyimpan array numpy 16-bit sebagai PNG 16-bit tetapi yang saya dapatkan hanyalah gambar hitam. Saya taruh di sini contoh minimum dari apa yang saya bicarakan.

im = np.random.randint(low=1, high=6536, size=65536).reshape(256,256) #sample numpy array to save as image
plt.imshow(im, cmap=plt.cm.gray)

Diberikan array numpy di atas ini adalah gambar yang saya lihat dengan matplotlib, tetapi ketika saya menyimpan gambar sebagai png 16-bit saya mendapatkan gambar di bawah ini:

import imageio

imageio.imwrite('result.png', im)

Gambar disimpan:

di mana beberapa titik abu-abu terang terlihat tetapi gambarnya sangat hitam. Bagaimanapun, ketika saya membaca kembali gambar dan memvisualisasikannya lagi dengan matplotlib, saya melihat gambar awal yang sama. Saya juga mencoba perpustakaan lain daripada imageio(suka PILatau PyPNG) tetapi dengan hasil yang sama.

Saya tahu bahwa nilai gambar 16-bit berkisar dari 0 hingga 65535 dan dalam array numpy array di sini hanya ada nilai dari 1 hingga 6536, tetapi saya perlu menyimpan gambar array numpy yang mirip dengan ini, yaitu di mana nilai maksimum yang diwakili dalam gambar isn t nilai maksimal yang dapat diwakili. Saya pikir ada semacam nornalisasi yang terlibat dalam proses penyimpanan. Saya perlu menyimpan array persis seperti yang saya lihat di matplotlib pada resolusi maksimumnya dan tanpa kompresi atau penyusutan nilainya (jadi pembagian dengan 255 atau konversi ke array 8-bit tidak cocok).

Jawaban

2 WarrenWeckesser Sep 24 2020 at 14:38

Sepertinya imageio.imwriteakan melakukan hal yang benar jika Anda mengonversi tipe data array menjadi numpy.uint16sebelum menulis file PNG:

imageio.imwrite('result.png', im.astype(np.uint16))

Ketika saya melakukan itu, result.pngadalah file PNG skala abu-abu 16 bit.

Jika Anda ingin gambar memiliki kisaran skala abu-abu penuh dari hitam ke putih, Anda harus menskalakan nilai ke kisaran [0, 65535]. Misalnya sesuatu seperti:

im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)

Kemudian Anda dapat menyimpan array itu dengan

imageio.imwrite('result2.png', im2)

Untuk menulis array NumPy ke file PNG, alternatifnya adalah numpngw(paket yang saya buat). Sebagai contoh,

from numpngw import write_png

im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)
write_png('result2.png', im2)

Jika Anda sudah menggunakan imageio, mungkin tidak ada keuntungan yang signifikan untuk menggunakan numpngw. Bagaimanapun, ini adalah ketergantungan yang jauh lebih ringan daripada imageio--itu hanya bergantung pada NumPy (tidak ada ketergantungan pada PIL / Pillow dan tidak ada ketergantungan pada libpng).