Saya membuat demo 20 bola yang saling memantul, dengan latar belakang yang penuh warna solid. Warna untuk setiap bola dipilih secara acak dengan randint(0, 255)
untuk setiap komponen tuple R, G, B.
Masalahnya adalah beberapa bola berakhir dengan warna yang sangat mirip dengan latar belakang, membuatnya sulit untuk dilihat. Saya ingin menghindari itu, baik dengan menggulirkan warna lain jika yang dipilih terlalu mirip (dalam batas tertentu), atau dengan memindahkannya dari warna latar belakang.
Bagaimana cara menghitung indeks kesamaan untuk digunakan sebagai ambang? Atau bagaimana mengubah warna untuk membuatnya, katakanlah, kurang biru-ish ?
Penafian yang jelas: Saya tidak tahu apa-apa tentang teori warna, jadi saya tidak tahu apakah konsep di atas bahkan ada!
Saya mengkode dengan python, tapi saya mencari konsep dan strategi, jadi pseudo-code baik-baik saja (atau hanya teorinya).
EDIT:
Untuk memperjelas beberapa poin:
Setiap bola memiliki warna acaknya sendiri. Saya ingin mereka tetap acak, dan menjelajahi sebanyak mungkin ruang warna (baik RGB atau HSV,
pygame
menerima kedua format untuk menentukan warna)Saya hanya ingin menghindari setiap warna "terlalu dekat" dengan latar belakang. Masalahnya bukan hanya tentang rona: Saya benar-benar baik-baik saja dengan bola biru muda terhadap latar belakang biru tua (atau "biru penuh" terhadap biru "putih-ish", dll.)
Untuk saat ini, saya tidak peduli apakah bola berakhir dengan warna yang sama (atau bahkan identik) dengan bola lain. Menghindari itu adalah bonus, tapi itu masalah kecil.
Warna latar adalah warna RGB tunggal yang konstan. Untuk saat ini saya menggunakan biru "dasar"
(0, 0, 255)
, tetapi saya tidak puas dengan itu. Jadi pertimbangkan latar belakang dari warna sewenang - wenang (dengan warna sewenang-wenang, kecerahan, saturasi, dll).
EDIT2:
TL, versi DR: Hanya berikan cara untuk membuat warna acak X sehingga tidak ada "memudar terlalu banyak" dengan latar belakang warna sewenang-wenang (tapi tunggal dan konstan)
Jawaban:
Anda dapat menggunakan fakta bahwa warna membentuk ruang warna (tiga dimensi) dan menghitung jarak dalam ruang warna ini. Anda kemudian perlu mendefinisikan metrik dalam ruang warna ini untuk menemukan jarak antara dua warna.
Misalnya jarak dalam ruang euclidean antara dua titik x = (x1, x2, x3) dan y = (y1, y2, y3) diberikan oleh d (x, y) = sqrt ((y1-x1) * (y1- x1) + (y2-x2) * (y2-x2) + (y3-x3) * (y3-x3)).
Sekarang Anda dapat menghitung jarak antara warna bola dan warna latar belakang Anda dan jika terlalu kecil, buat warna acak baru dan uji lagi.
Anda akan menemukan bahwa baik RGB maupun HSV bukan ruang warna yang baik untuk tugas ini. The artikel wikipedia tentang perbedaan warna mempekerjakan L a b ruang warna dan memberikan beberapa metrik mungkin.
Ada juga diskusi tentang stackoverflow pada topik.
sumber
Halaman standar aksesibilitas web PBB ( http://www.un.org/webaccessibility/1_visual/13_colourcontrast.shtml ) menunjukkan standar untuk memastikan teks yang kontras pada situs web, mengingat bahwa beberapa pengguna buta warna. Ini mungkin sangat penting bagi Anda karena beberapa pengguna Anda mungkin juga buta warna (akan sulit untuk mengatakan bola merah dari latar belakang hijau jika mereka memiliki pencahayaan yang sama).
Halaman PBB menunjuk ke Juicy Studios Luminosity Color Contrast Ratio Analyzer di ( http://juicystudio.com/services/luminositycontrastratio.php#specify ) yang menyatakan teks di latar belakang harus memiliki rasio kontras 4,5: 1, kecuali untuk apa yang saya percaya serupa dengan kasus Anda:
Sekarang apa rasio kontras? Mengikuti hyperlink lebih lanjut (ini menyenangkan!) Kita sampai ke halaman W3 yang mendefinisikan rasio kontras sebagai:
Di mana L1 dan L2 adalah luminens relatif dari warna. L1 adalah warna yang lebih terang, L2 adalah warna yang kurang terang. Sekali lagi, kami mengikuti tautan ke halaman W3 yang sama yang menentukan:
CATATAN : Simbol caret ^ di atas mengacu pada eksponensial (x²)
Kami memiliki kerangka kerja yang cukup bagus untuk algoritma kontras (ramah warna!)
sumber
^
, saya tidak akan pernah berpikir tentang XOR bitwise dalam konteks ini. (Atau sebenarnya. C'mon C phreaks,^
adalah simbol de-facto untuk eksponensial dalam pseudo-codes (walaupun sangat sedikit bahasa yang menggunakannya ... dengan python**
)Menggunakan nilai RGB dengan menghasilkan
0-255
nilai acak untuk setiap komponen mungkin tidak hanya membuat warna yang mirip dengan latar belakang, Anda juga bisa berakhir dengan warna yang sangat mirip untuk bola.Saya mungkin akan memilih pendekatan yang kurang acak dan membuat warna yang dijamin berbeda. Anda dapat membuat warna untuk setiap ~ 32 derajat dalam rentang rona dan mengganti kecerahan atau saturasi (gunakan model warna HSV alih-alih RGB).
Jadi sesuatu seperti ini:
yang akan membuat 20 warna, didistribusikan dengan baik. Ini mengasumsikan Anda menggunakan bilangan bulat matematika, jadi
i = 0
dani = 1
akan membuat nilai rona yang sama.Tentu saja ini tidak berskala terlalu baik .. jika Anda memiliki nilai warna 100 untuk dibuat, jarak rona mungkin tidak cukup dan Anda akan berakhir dengan warna yang sama lagi. Dalam hal ini Anda juga bisa memvariasikan nilai
V
(kecerahan).Saya tidak tahu seperti apa warna latar belakang Anda, tetapi HSV membuatnya juga lebih mudah untuk membandingkan warna (bandingkan saja 3 komponen dan jangan lupa bahwa HUE berbentuk lingkaran (0 == 360)).
MEMPERBARUI:
Karena saya tidak benar-benar menjawab pertanyaan Anda melainkan memberikan pendekatan lain, inilah bagaimana algoritma untuk latar belakang yang sewenang-wenang dan bola berwarna benar-benar acak dapat terlihat (ini adalah pendekatan kasar tetapi harus bekerja dengan baik untuk kasus penggunaan Anda):
sumber
V
(karena algoritma saat ini tidak mengubah itu).Karena Anda menyebutkan bahwa Anda memiliki latar belakang stasioner, warna bola masih bisa acak tetapi mereka harus jatuh pada rentang tertentu yang masih memuji latar belakang.
Dasar-dasar Sebelum kita melakukan itu, Anda perlu mengetahui dasar-dasarnya. Pertimbangkan warna-warna berikut:
Campuran Warna RGB [(0..255), (0..255), (0..255)] menciptakan warna baru seperti di atas.
Komputasi untuk Warna Negatif Komputasi untuk warna negatif seperti mentransformasikan merah dalam cyan, hijau dalam ungu, biru dalam kuning.
Warna Pelengkap
Sesuai referensi tentang Komputasi warna komplementer: http://serennu.com/colour/rgbtohsl.php
Tentang HSL
HSL mengekspresikan warna dalam kaitannya dengan Hue, Saturation, dan Lightness mereka, memberikan angka untuk masing-masing dari ketiga atribut warna ini.
Hue adalah posisi warna pada roda warna, dinyatakan dalam derajat dari 0 ° hingga 359 °, mewakili 360 ° roda; 0 ° menjadi merah, 180 ° menjadi warna berlawanan cyan, dan seterusnya.
Kejenuhan adalah intensitas warna, seberapa kusam atau cerahnya warna itu. Semakin rendah saturasi, semakin kusam (abu-abu) warna terlihat. Ini dinyatakan sebagai persentase, 100% menjadi saturasi penuh, paling terang, dan 0% menjadi tidak saturasi, abu-abu.
Lightness adalah seberapa terang warnanya. Sedikit berbeda dengan saturasi. Semakin putih warna semakin tinggi nilai Terangnya, semakin banyak hitam, semakin rendah Terangnya. Jadi 100% Lightness mengubah warna menjadi putih, 0% Lightness mengubah warna menjadi hitam, dan warna "murni" akan menjadi 50% Lightness.
Lebih mudah untuk melihat perbedaan antara Saturasi dan Terang daripada menjelaskannya. Jika Anda ingin memperjelas, coba lihat variasi Lightness dan Saturation pada halaman kalkulator warna, pilih warna yang cukup cerah sebagai warna starter Anda.
Jadi notasi HSL terlihat seperti ini, memberikan nilai Hue, Saturation, dan Lightness dalam urutan itu: t
Merah: 0 ° 100% 50% Merah muda pucat: 0 ° 100% 90% Cyan: 180 ° 100% 50% Berikut adalah Langkah-langkahnya:
Ubah warna Anda menjadi HSL.
Ubah nilai Hue ke nilai Hue yang berlawanan (misalnya, jika Hue Anda adalah 50 °, yang berlawanan akan berada pada 230 ° pada roda - 180 ° lebih jauh di sekitar).
Biarkan nilai Saturation and Lightness seperti semula.
Ubah nilai HSL baru ini kembali ke notasi warna asli Anda (RGB atau apa pun).
Situs seperti EasyRGB.com dapat melakukan konversi generik untuk Anda dari RGB ke HSL atau sebaliknya.
Contoh Pemrograman dilakukan dalam PHP sesuai referensi
Konversi dari RGB ke HSL
Nilai di atas Biru # 0000FF rgb (0,0255) dapat disajikan sebagai Heksadesimal Merah 00 + Heksadesimal Hijau 00 + FF Heksadesimal Biru
Itu juga dapat disajikan sebagai Desimal Merah 0 + Desimal Hijau 0 + Desimal Biru 255
Sekarang colokkan nilai-nilai ini ke dalam rutin rgb2hsl. Di bawah ini adalah versi generik kode EasyRGB.com PHP saya untuk konversi itu:
Input adalah $ var_r, $ var_g dan $ var_b dari atas. Outputnya setara dengan $ h, $ s dan $ l - ini sekali lagi dinyatakan dalam pecahan 1, seperti nilai input
Jadi sekarang kita memiliki warna sebagai nilai HSL, dalam variabel $ h, $ s dan $ l. Ketiga variabel keluaran ini lagi-lagi dianggap sebagai pecahan 1 pada tahap ini, bukan sebagai derajat dan persentase. Jadi misalnya, cyan (180 ° 100% 50%) akan keluar sebagai $ h = 0,5, $ s = 1, dan $ l = 0,5.
Selanjutnya temukan nilai Hue yang berlawanan, yaitu yang berjarak 180 °, atau 0,5, jauh (saya yakin para ahli matematika memiliki cara yang lebih elegan untuk menyamakan ini, tetapi):
Hitung rona yang berlawanan, $ h2
Nilai HSL dari warna komplementer sekarang dalam $ h2, $ s, $ l. Jadi kami siap untuk mengonversikan ini kembali ke RGB (sekali lagi, versi PHP dari rumus EasyRGB.com). Perhatikan format input dan output berbeda kali ini, lihat komentar saya di bagian atas kode:
Input adalah nilai HSL dari warna komplementer, disimpan dalam $ h2, $ s, $ l sebagai fraksi dari 1 Output adalah RGB dalam format 255 255 255 normal, disimpan dalam $ r, $ g, $ b Hue dikonversi menggunakan fungsi hue_2_rgb, ditunjukkan di akhir kode ini
Dan setelah rutin itu, kami akhirnya memiliki $ r, $ g dan $ b dalam format 255 255 255 (RGB), yang dapat dikonversi menjadi enam digit hex:
$ rgbhex adalah jawaban kami - warna pelengkap dalam hex.
Karena latar belakang warna Anda biru atau 0,0255 HSL adalah
Hue (H): 240 derajat / Saturasi (S): 100% / Ringan (L): 4,9%
kebalikan dari 240 adalah 60 dalam lingkaran kemudian konversikan kembali ke RGB memberikan nilai # 181800
sumber
Saya ingin memperluas ide @ ashes999 tentang membuat garis besar.
Kode saya akan menjadi seperti python yang saya bisa dari atas kepala saya (saya tidak pernah menulis garis python dalam hidup saya, tetapi saya telah melirik buku sekali atau dua kali).
Ini mungkin tidak terlihat sangat cantik dan itu tidak benar-benar ideal untuk kode produksi, tetapi itu sudah cukup sebagai perbaikan cepat. Saya belum menguji kode karena saya tidak punya program "bola memantul di sekitar layar" untuk menyerahkan bahwa saya dapat memutilasi untuk mengujinya.
Edit:
Setelah melihat kode aktual yang digunakan, situasinya terbalik, jadi saya menawarkan solusi ini.
Ganti baris 276-284 dengan yang berikut:
Dalam versi baru yang disederhanakan ini, metode pabrik meludahkan bola, dan metode khusus menghasilkan warna. Generator warna menguji warna yang dihasilkan secara acak untuk melihat apakah warna tersebut berada dalam kisaran kedekatan tertentu dengan warna latar belakang. Warna dianggap terlalu dekat dengan warna BG jika ketiga saluran warnanya berada di
leeway
kedua sisi BG. Jadi jika kelonggaran adalah 0, hanya warna yang sama persis dengan BG yang ditolak. Saya telah memilih 5 sebagai default, yang menolak warna BG dan 5 warna di kedua sisi. Karena warna BG adalah putih, saya tidak yakin apakah akan menolak hitam karena angka-angka itu membungkus bulat. Itu bisa dihindari dengan menggunakan fungsi min dan max, tapi saya meninggalkannya demi singkatnya.sumber
pygame
sebagai perpustakaan. Tanpa Lerp, hanya konversi RGB-HSV-CYMK dasar: pygame.org/docs/ref/color.htmllerp
fungsi dalam jawaban saya adalah semua yang ada untuk itu. (Lerp berarti 'Interpolasi linier').print
berbeda karena Anda menggunakan Python 3, dan saya masih menggunakan Python 2. Dan saya tidak yakin apakahpygame
porting ke Py3. Intinya: jangan repot-repot :) Pertanyaannya adalah tentang warna, Anda tidak perlu bola yang sebenarnya memantul :)Untuk format RGB, ini tampaknya berfungsi cukup baik dan sepele:
diversity_score = (abs (r1 - r2) + abs (g1 - g2) + abs (b1 - b2)) / 765.0
Ini akan memberi Anda skor antara 0,0 dan 1,0. Semakin rendah, semakin sulit untuk membedakan dua warna.
Itu harus jelas, tetapi demi kelengkapan: nilai r, g, b harus dilemparkan ke angka floating point terlebih dahulu, dan diasumsikan bahwa nilai maksimumnya adalah 255.
sumber