Diagram warna 24-bit dan diagram skala abu-abu 8-bit
Pertama, mari kita perkenalkan gambar warna 24-bit. Dalam gambar warna 24-bit, setiap piksel diwakili oleh tiga byte, biasanya dinyatakan sebagai RGB. Secara umum, banyak gambar warna 24-bit disimpan sebagai gambar 32-bit, dan kelebihan byte per piksel disimpan sebagai nilai alpha , menunjukkan informasi pengaruh khusus [1].
Dalam model RGB, jika r = g = b, warnanya mewakili warna abu -abu, di mana nilai r = g = b disebut nilai skala abu -abu. Oleh karena itu, setiap piksel gambar skala abu-abu hanya membutuhkan satu byte untuk menyimpan nilai skala abu-abu (juga dikenal sebagai nilai intensitas dan nilai kecerahan), dan rentang skala abu-abu adalah 0-255 [2]. Ini memberi Anda gambar skala abu -abu dari gambar.
Beberapa metode skala abu -abu
1. Metode Komponen: Gunakan salah satu dari tiga komponen RGB sebagai nilai skala abu -abu dari peta skala abu -abu.
2. Metode Nilai Sebagian besar: Gunakan nilai maksimum atau minimum dari tiga komponen RGB sebagai nilai skala abu -abu dari peta skala abu -abu.
3. Metode rata -rata: Gunakan nilai rata -rata dari tiga komponen RGB sebagai nilai skala abu -abu dari grafik skala abu -abu.
4. Metode pembobotan: Karena sensitivitas warna mata manusia yang berbeda, rata-rata tertimbang RGB tiga komponen dapat memperoleh gambar abu-abu yang lebih masuk akal. Situasi umum adalah sebagai berikut: y = 0,30r + 0,59g + 0,11b.
[Catatan] Metode pembobotan sebenarnya mengambil nilai kecerahan gambar sebagai nilai skala abu -abu untuk menghitung, dan menggunakan model YUV. Dalam [3], Anda akan menemukan bahwa penulis menggunakan y = 0,21 * R + 0,71 * G + 0,07 * B untuk menghitung nilai skala abu -abu (jelas jumlah dari tiga bobot tidak sama 1, yang mungkin merupakan kesalahan penulis?). Bahkan, perbedaan ini harus terkait dengan apakah koreksi gamma digunakan [1].
Metode untuk mengimplementasikan grayscale di java
Jika Anda mencari "Java mengimplementasikan grayscale", kebanyakan dari mereka adalah satu metode (kode):
public void GrayImage () melempar ioException {file file = file baru (System.getProperty ("user.dir")+"/test.jpg"); BufferedImage Image = ImageIo.read (file); int width = image.getWidth (); int height = image.getHeight (); BufferedImage GrayImage = BufferedImage baru (lebar, tinggi, bufferedImage.type_byte_gray); untuk (int i = 0; i <width; i ++) {for (int j = 0; j <height; j ++) {int rgb = image.getrgb (i, j); Grayimage.setrgb (I, J, RGB); }} File newfile = file baru (system.getProperty ("user.dir")+"/method1.jpg"); Imageo.write (Grayimage, "JPG", Newfile); }Gambar asli test.jpg adalah:
Diagram skala abu -abu yang diperoleh dengan menggunakan metode di atas:
Melihat gambar skala abu -abu ini tampaknya layak, tetapi jika kita menggunakan opencv untuk mencapai skala abu -abu atau menggunakan PIL (Python), Anda akan menemukan bahwa efeknya sangat bervariasi:
img = cv2.imread ('test.jpg', cv2.imread_color) abu -abu = cv2.cvtcolor (img, cv2.color_bgr2gray) cv2.imwrite ('pythonmethod.jpg', abu -abu) Dapat dengan jelas terlihat bahwa grafik skala abu -abu yang diperoleh dengan menggunakan opencv (hal yang sama berlaku untuk PIL) jauh lebih baik daripada metode yang diperoleh dengan metode Java di atas, dan banyak detail dapat dilihat. Ini menunjukkan bahwa metode populer di internet ini selalu memiliki beberapa masalah, tetapi telah diabaikan.
Cara mencapai skala abu -abu di opencv
Jika Anda telah membaca buku atau kode yang terkait dengan opencv , Anda mungkin dapat mengetahui bahwa opencv Grayscale menggunakan metode pembobotan. Alasannya adalah bahwa itu kira -kira karena kita tidak tahu mengapa gambar grayscale opencv sangat bagus. Apakah ada detail pemrosesan lain yang kami abaikan?
Memverifikasi tebakan kami sangat sederhana. Cukup periksa perubahan sebelum dan sesudah nilai piksel berwarna abu -abu. Anda dapat mengujinya sebagai berikut:
img = cv2.imread ('test.jpg', cv2.imread_color) h, w = img.shape [: 2] abu -abu = cv2.cvtcolor (img, cv2.color_bgr2gray) untuk j dalam kisaran (w): untuk i dalam rentang (h): cetak str (i)) untuk j dalam kisaran (w): untuk i dalam jangkauan (h): cetak str (i) ":": " +": "): untuk J) (w): for i in range (h): print str (i)": ":": "): f untuk i dalam kisaran (h): cetak str (i) +": ":": " IMG [H-1] [W-1] [0: 3]Sulit bagi kita untuk menilai begitu banyak piksel di bawah ini, tetapi kita hanya perlu memperhatikan titik piksel terakhir dan kita dapat menemukan petunjuk: nilai RGB dari titik piksel terakhir dalam gambar asli adalah 44, 67, 89, dan nilainya setelah beruban adalah 71. Hanya sesuai dengan nilai abu -abu yang dihitung dengan metode pembobotan. Jika Anda memeriksa nilai piksel gambar yang berwarna abu -abu di Java sebelumnya, Anda akan menemukan bahwa tidak hanya nilai piksel tidak memenuhi formula ini, tetapi bahkan jauh dari satu sama lain.
Pada titik ini, kami menduga bahwa OpenCV (termasuk PIL) adalah implementasi skala abu -abu menggunakan metode pembobotan.
Java mengimplementasikan metode abu -abu tertimbang
Jika metode populer di internet tidak berfungsi, bagaimana kita harus menggunakan Java untuk mencapai grayscale? Faktanya, [3] telah berhasil mencapai (beberapa metode) Grayscale (teman asing masih sangat kuat dalam teknologi), dan hanya kode yang diperlukan yang diekstraksi di sini:
private static int colortorgb (int alpha, int red, int green, int blue) {int newpixel = 0; newpixel += alpha; newpixel = newpixel << 8; newpixel += merah; newpixel = newpixel << 8; newpixel += green; newpixel = newpixel << 8; newpixel += biru; mengembalikan newpixel; } public static void main (string [] args) melempar ioException {bufferedImage bufferedImage = imageIO.read (file baru (System.getProperty ("user.dir" + "/test.jpg")); bufferedImage garreimage = BufferedImage baru (bufferedimage.getwidth ()); bufferedImage garreimage = buffered new BufferedImage (bufferedimage.getwidth ()); bufferedImage garreImage = Bufferedimage (bufferedimage.getwidth ()); bufferedImage garreimage = buffered new BufferedImage (bufferedimage.getwidth () BufferedImage.getType ()); untuk (int i = 0; i <BufferedImage.getWidth (); i ++) {for (int j = 0; j <bufferedImage.getheight (); = Warna & 0xff; File (System.getProperty ("user.dir") + "/ok.jpg"); Kode di atas akan mencetak nilai piksel skala abu-abu. Jika Anda membandingkannya dengan kode Python di atas, Anda akan menemukan bahwa nilai piksel sepenuhnya sesuai. Metode colorToRGB menangani diagram warna persis 4 byte, salah satunya adalah parameter alpha (seperti yang disebutkan sebelumnya). Gambar berikut adalah gambar skala abu -abu dari kode ini:
Untuk metode lain, hal yang sama dapat diperoleh secara bergantian.
Meringkaskan
Alasan artikel ini adalah menggunakan Java untuk mengimplementasikan beberapa operasi skala abu -abu dan menggunakan OpenCV untuk memverifikasi benar atau salah dari konversi. Namun, beberapa masalah ditemukan dalam tes aktual (ada perbedaan dalam gambar yang dikonversi, dan bagaimana menghasilkan gambar skala abu -abu berdasarkan nilai -nilai abu -abu setelah konversi), dan beberapa pemikiran dan verifikasi dilakukan pada ini. Perlu dicatat di sini bahwa beberapa artikel di internet memiliki lebih atau kurang dari pemikiran lebih lanjut (dan banyak dari mereka bahkan disalin, terutama artikel domestik), dan untuk masalah-masalah praktis ini, implementasi dan verifikasi langsung adalah metode yang sangat penting. Saya berharap konten artikel ini akan membantu semua orang. Jika Anda memiliki pertanyaan, silakan tinggalkan pesan untuk didiskusikan.