Materi
Histogram citra menghitung berapa piksel yang memiliki setiap nilai. np.bincount(citra.ravel(), minlength=256) memberi 256 hitungan, satu per nilai 0–255; np.histogram mengelompokkan nilai ke beberapa bin; Image.histogram di Pillow mengembalikan daftar hitungan yang sama. Foto redup menumpuk di kiri histogram, foto silau di kanan, dan foto berkontras rendah menumpuk di rentang sempit.
Mencerahkan berarti menambah konstanta ke setiap piksel; menaikkan kontras berarti meregangkan rentangnya. Regangan paling sederhana adalah normalisasi min-max: (x − min) / (max − min) memetakan nilai terkecil ke 0 dan terbesar ke 1, lalu dikali 255 untuk kembali ke skala uint8.
Di sinilah uint8 menjebak. Dokumentasi tipe data numpy menyebut numpy mengikuti aturan casting C, sehingga nilai yang melewati batas tipe meluap: 300 dalam int8 menjadi 44. Hal yang sama terjadi pada uint8: 250 + 20 menjadi 14, piksel putih mendadak hitam. Menambah bilangan Python negatif ke larik uint8 malah memunculkan OverflowError: Python integer -20 out of bounds for uint8. Cara aman: ubah ke tipe yang lebih lebar (int16 atau float), hitung, potong ke 0–255 dengan np.clip, lalu astype(np.uint8).
import numpy as np
langit = np.array([240, 245, 250], dtype=np.uint8)
print(langit + 10) # [250 255 4] <- 250 + 10 meluap
aman = np.clip(langit.astype(np.int16) + 10, 0, 255).astype(np.uint8)
print(aman) # [250 255 255]