Algoritma untuk memodifikasi warna agar kurang mirip dengan latar belakang

23

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, pygamemenerima 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)

MestreLion
sumber
1
Mengapa tidak menaruh garis besar di sekitar setiap bola?
ashes999
1
Maka mungkin ada masalah dengan membuat warna garis yang berbeda dari latar belakang DAN warna bola;)
Kromster mengatakan mendukung Monica
1
@AlexM .: sulit dipercaya tidak ada solusi mudah untuk "menghasilkan warna acak dan menghindari yang sembarang"
MestreLion
1
@MestreLion hanya menggunakan warna hitam untuk garis besar dan menghasilkan warna dengan nilai RGB minimum 128. Sangat Mudah.
ashes999

Jawaban:

33

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.

René
sumber
Itu pendekatan yang sangat bagus, saya bisa melakukan itu :) Terima kasih! Juga, sedikit peduli untuk menguraikan cara menemukan ambang "jarak minumum" yang memadai? Jika RGB tidak memadai, bagaimana cara mengkonversi ke L a b? Saya tidak berusaha untuk metrik persepsi yang akurat, sehingga standar "cukup baik" akan dilakukan.
MestreLion
1
Sukai jawaban ini, dipikirkan dengan matang, penjelasan yang baik tentang bagaimana melakukan tugas sambil memberikan persamaan dan referensi yang dibutuhkan. Jawaban pertama yang bagus
Tom 'Blue' Piddock
1
Jika Anda mencari perkiraan persepsi manusia yang "cukup baik", Anda mungkin ingin melihat ruang warna YUV , yang memiliki konversi langsung dari RGB.
trm
5
Hemat sedikit waktu, dan jangan mengambil akar kuadrat (mahal). Buat saja nilai jarak warna minimum yang Anda bandingkan dengan kuadrat.
Chris Cudmore
1
@MestreLion Ruang warna L a b * diciptakan untuk seragam secara perseptual, yang berarti bahwa jarak yang dirasakan antara dua warna sama dengan jarak aktual dalam ruang warna. Karena warna RGB tergantung pada perangkat, Anda tidak dapat langsung mengkonversi antara Lab dan RGB. Namun, jika Anda menggunakan ruang warna RGB absolut tertentu, Anda dapat mengubahnya. Lihat artikel ini: en.wikipedia.org/wiki/SRGB_color_space dan artikel ini: en.wikipedia.org/wiki/Lab_color_space
jwir3
8

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:

  • Teks Besar: Teks skala besar dan gambar teks skala besar memiliki rasio kontras minimal 3: 1

Sekarang apa rasio kontras? Mengikuti hyperlink lebih lanjut (ini menyenangkan!) Kita sampai ke halaman W3 yang mendefinisikan rasio kontras sebagai:

Contrast Ratio = (L1 + 0.05)/(L2 + 0.05)

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:

L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:

if RsRGB <= 0.03928 then R = RsRGB/12.92 else R = ((RsRGB+0.055)/1.055) ^ 2.4
if GsRGB <= 0.03928 then G = GsRGB/12.92 else G = ((GsRGB+0.055)/1.055) ^ 2.4
if BsRGB <= 0.03928 then B = BsRGB/12.92 else B = ((BsRGB+0.055)/1.055) ^ 2.4
and RsRGB, GsRGB, and BsRGB are defined as:

RsRGB = R8bit/255
GsRGB = G8bit/255
BsRGB = B8bit/255

CATATAN : Simbol caret ^ di atas mengacu pada eksponensial (x²)

Kami memiliki kerangka kerja yang cukup bagus untuk algoritma kontras (ramah warna!)

  • Tentukan nilai R, G, B untuk setiap warna
  • Tentukan Luminance untuk setiap warna
  • Jika Rasio Kontras dari warna yang lebih terang ke warna paling sedikit kurang dari 3, reroll!
John
sumber
2
Mungkin ingin dicatat bahwa ^ seharusnya eksponensial. Bagi kami pengguna mirip C yang gila itu berarti xor (saya benar-benar berpikir Anda mencoba melakukan operasi bitwise pada nilai floating point selama satu menit).
Pharap
Itu pendekatan yang luar biasa , saya menyukainya! :)
MestreLion
Dan jangan khawatir ^, 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 **)
MestreLion
1
Hanya memperbaiki kesalahan ketik. Plus, jika satu orang memiliki masalah dengan ^, kemungkinan orang lain di masa depan juga bisa. Tidak ada salahnya untuk spesifik.
John
1
@ John Jangan khawatir,. Saya tidak yakin dari mana asal mula kebingungan (yaitu, bahasa mana yang digunakan ^ untuk tujuan apa pertama kali). Saya hanya tahu ^ kadang-kadang digunakan untuk eksponensial karena pengalaman saya dengan VB (saya tidak tahu bahasa lain yang menggunakannya sebagai eksponensial, tetapi mungkin ada beberapa). Sama seperti kepala-up, itu adalah simbol caret , bukan simbol wortel . Mungkin ingin mengubahnya sebelum seseorang membuat lelucon mengerikan tentang pemrograman dengan sayuran (terutama yang melibatkan akar kuadrat).
Pharap
2

Menggunakan nilai RGB dengan menghasilkan 0-255nilai 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:

numColors = 20;
stepSize = 360 / (numColors / 2 + 1); // hue step size
for(i = 0; i < numColors; i++){
    color = HSV(i / 2 * stepSize, 0.5 + (i % 2) * 0.5, 1.0) 
}

yang akan membuat 20 warna, didistribusikan dengan baik. Ini mengasumsikan Anda menggunakan bilangan bulat matematika, jadi i = 0dan i = 1akan 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):

// background color, currently equals RGB(0, 0, 255)
bg = HSV(240, 1.0, 1.0)

// number of colors to create is equal to the amount of balls
numColors = balls.length

// set threshold to compare colors. you can tweak this to your liking
threshold = 0.15

for(i = 0; i < numColors; i++){
    do {
        // assuming rnd returns a random float 0-1 inclusive
        color = HSV(rnd() * 360, rnd(), rnd())
        // calculate delta values, normalize hue to 0-1
        dH = (180 - abs(abs(bg.h - color.h) - 180)) / 360
        dS = bg.s - color.s
        dV = bg.v - color.v
        // "distance" between bg and color
        difference = sqrt(dH * dH + dS * dS + dV * dV)
    } while(difference < threshold)

    ball[i].color = color
}
bummzack
sumber
Tentang algoritme Anda, bagaimana cara memperhitungkan warna latar belakang?
MestreLion
Saat ini tidak memperhitungkan warna latar belakang ... Anda bisa mengubahnya dengan membandingkan warna yang dihasilkan (seperti yang dijelaskan pada paragraf terakhir) dan kemudian membuat warna dengan yang berbeda V(karena algoritma saat ini tidak mengubah itu).
bummzack
@MestreLion Menambahkan pembaruan dengan algoritma alternatif
bummzack
Bagus, itu sepertinya strategi yang bagus. Brute force OK, warna hanya menghasilkan satu kali pada inisialisasi, tidak dalam loop game. Sepertinya Anda menggunakan pendekatan yang sama dengan René, dengan jarak euclidean polos di HSV, benar? Adakah referensi ambang yang sesuai untuk HSV? Apakah H, S dan V berbobot dalam jarak yang sama seperti di RGB?
MestreLion
@MestreLion Ya, algoritma kedua saya cukup banyak seperti yang dijelaskan René dalam jawabannya. Sayangnya tidak ada nilai pasti untuk ambang batas yang baik karena perubahan warna tidak dirasakan seragam. Kami mengenali perubahan dalam warna hijau lebih cepat daripada warna biru ... jadi untuk nada hijau, ambang yang lebih kecil mungkin berfungsi tetapi tidak akan cukup untuk warna lain, dll. Sejauh yang saya tahu, ruang warna Lab dekat dengan persepsi warna manusia dan mungkin paling cocok jika Anda tidak mendapatkan hasil yang diinginkan dengan ruang warna HSV.
bummzack
1

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:

Black   #000000 rgb(0,0,0)
Red     #FF0000 rgb(255,0,0)
Green   #00FF00 rgb(0,255,0)
Blue    #0000FF rgb(0,0,255)
Yellow  #FFFF00 rgb(255,255,0)
Cyan    #00FFFF rgb(0,255,255)
Pink    #FF00FF rgb(255,0,255)
Gray    #C0C0C0 rgb(192,192,192)
White   #FFFFFF rgb(255,255,255)

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.

Red     #FF0000 rgb(255,0,0) ->     Cyan    #00FFFF rgb(0,255,255)
Green   #00FF00 rgb(0,255,0) ->     Purple   #FF00FF    rgb(255,0,255)
Blue    #0000FF rgb(0,0,255) ->     Yellow  #FFFF00 rgb(255,255,0)

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:

  1. Ubah warna Anda menjadi HSL.

  2. 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).

  3. Biarkan nilai Saturation and Lightness seperti semula.

  4. 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

$redhex  = substr($hexcode,0,2);
$greenhex = substr($hexcode,2,2);
$bluehex = substr($hexcode,4,2);

Itu juga dapat disajikan sebagai Desimal Merah 0 + Desimal Hijau 0 + Desimal Biru 255

$var_r = (hexdec($redhex)) / 255;
$var_g = (hexdec($greenhex)) / 255;
$var_b = (hexdec($bluehex)) / 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

$var_min = min($var_r,$var_g,$var_b);ttt
$var_max = max($var_r,$var_g,$var_b);
$del_max = $var_max - $var_min;

$l = ($var_max + $var_min) / 2;

if ($del_max == 0)
{
        $h = 0;
        $s = 0;
}
else
{
        if ($l < 0.5)
        {
                $s = $del_max / ($var_max + $var_min);
        }
        else
        {
                $s = $del_max / (2 - $var_max - $var_min);
        };

        $del_r = ((($var_max - $var_r) / 6) + ($del_max / 2)) / $del_max;
        $del_g = ((($var_max - $var_g) / 6) + ($del_max / 2)) / $del_max;
        $del_b = ((($var_max - $var_b) / 6) + ($del_max / 2)) / $del_max;

        if ($var_r == $var_max)
        {
                $h = $del_b - $del_g;
        }
        elseif ($var_g == $var_max)
        {
                $h = (1 / 3) + $del_r - $del_b;
        }
        elseif ($var_b == $var_max)
        {
                $h = (2 / 3) + $del_g - $del_r;
        };

        if ($h < 0)
        {
                $h += 1;
        };

        if ($h > 1)
        {
                $h -= 1;
        };
};

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

            $h2 = $h + 0.5;

            if ($h2 > 1)
                    {
                            $h2 -= 1;
                    };

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

    if ($s == 0)
    {
            $r = $l * 255;
            $g = $l * 255;
            $b = $l * 255;
    }
    else
    {
            if ($l < 0.5)
            {
                    $var_2 = $l * (1 + $s);
            }
            elset
            {
                    $var_2 = ($l + $s) - ($s * $l);
            };

            $var_1 = 2 * $l - $var_2;
            $r = 255 * hue_2_rgb($var_1,$var_2,$h2 + (1 / 3));
            $g = 255 * hue_2_rgb($var_1,$var_2,$h2);
            $b = 255 * hue_2_rgb($var_1,$var_2,$h2 - (1 / 3));
    };

   // Function to convert hue to RGB, called from above

    function hue_2_rgb($v1,$v2,$vh)
    {
            if ($vh < 0)
            {
                    $vh += 1;
            };

            if ($vh > 1)
            {
                    $vh -= 1;
            };

            if ((6 * $vh) < 1)
            {
                    return ($v1 + ($v2 - $v1) * 6 * $vh);
            };

            if ((2 * $vh) < 1)
            {
                    return ($v2);
            };

            if ((3 * $vh) < 2)
            {
                    return ($v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6));
            };

            return ($v1);
    };

Dan setelah rutin itu, kami akhirnya memiliki $ r, $ g dan $ b dalam format 255 255 255 (RGB), yang dapat dikonversi menjadi enam digit hex:

    $rhex = sprintf("%02X",round($r));
    $ghex = sprintf("%02X",round($g));
    $bhex = sprintf("%02X",round($b));

    $rgbhex = $rhex.$ghex.$bhex;

$ 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

Ace Caserya
sumber
Terima kasih! Tetapi tautan itu berbicara tentang menghasilkan "warna komplementer" (apa pun itu) dari dirinya sendiri . Saya masih tidak mengerti bagaimana cara menggunakannya untuk menyelesaikan masalah saya: pastikan bahwa setiap warna acak tidak sama dengan warna latar belakang. Warna latar adalah konstan, satu warna, dan ada banyak bola.
MestreLion
Terima kasih Krom melakukan itu sekarang. @MestreLion, karena latar belakangnya konstan, Anda dapat menentukan rentang bola yang masih melengkapi latar belakangnya.
Ace Caserya
Saat ini Menjelaskan jawaban saya.
Ace Caserya
Selesai Saya tidak perlu mengubah banyak penjelasan situs karena dijelaskan dengan cukup baik. Penghargaan kepada orang-orang di EasyRGB.com
Ace Caserya
Mari kita lanjutkan diskusi ini dalam obrolan .
Ace Caserya
1

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).

def lerp(a,b,value): # assuming your library was not kind enough to give you this for free
    return a + ((b - a) * value);

def drawRandomBall(bgColour,radius,point):
    var ballColour = Colour(random(0,255),random(0,255),random(0,255);
    var outlineColour = Colour(lerp(bgColour.R,255 - ballColour.R,0.5),lerp(bgColour.G,255 - ballColour.G,0.5),lerp(bgColour.B,255 - ballColour.B,0.5));
    fillCircle(point,radius+1,outlineColour);
    fillCircle(point,radius,ballColour);

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:

# Colour generator
def generateColourNonBG(leeway):
    color = (randint(0,255), randint(0,255), randint(0,255))
    while color[0] >= BG_COLOR[0]-leeway and color[0] =< BG_COLOR[0] + leeway and
    color[1] >= BG_COLOR[1]-leeway and color[1] =< BG_COLOR[1] + leeway and
    color[2] >= BG_COLOR[2]-leeway and color[2] =< BG_COLOR[2] + leeway:
        color = (randint(0,255), randint(0,255), randint(0,255))

# Ball generator
def generateBall():
    Ball(generateColourNonBG(5),
                   radius=randint(10, radius),
                   position=[randint(100, screen.get_size()[0]-radius),
                             randint(100, screen.get_size()[0]-radius)],
                   velocity=[randint(50, 50+vel[0]), randint(50, 50+vel[1])],
                   )                       

# Create the balls
balls = pygame.sprite.Group()
for _ in xrange(BALLS):
    balls.add(generateBall())

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 leewaykedua 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.

Pharap
sumber
Saya terbuka untuk strategi apa pun :) sebagai program untuk memutilasi, saya dapat memberikan Anda bahwa: github.com/MestreLion/rainballs baris yang relevan adalah 279-284
MestreLion
Saya menggunakan pygamesebagai perpustakaan. Tanpa Lerp, hanya konversi RGB-HSV-CYMK dasar: pygame.org/docs/ref/color.html
MestreLion
@MestreLion Oh Tuhan, sekarang saya harus menginstal pygame dan python untuk mengujinya. Saya sudah menembak kaki saya dengan XP yang satu ini. Mudah Lerping, lerpfungsi dalam jawaban saya adalah semua yang ada untuk itu. (Lerp berarti 'Interpolasi linier').
Pharap
@MestreLion Mengotak-atik sedikit, ternyata versi python saya tidak suka cetak dipanggil tanpa tanda kurung. Memperbaiki itu, tapi sekarang saya punya kesalahan dari pygame karena tidak dapat menemukan perpustakaan yang tepat. Saya akan menulis ulang kode saya agar sesuai dengan apa yang Anda miliki, tetapi saya tidak dapat mengujinya sampai saya memperbaiki pygame. Saya akan merekomendasikan menambahkan file itu ke pertanyaan jika Anda belum melakukannya (kalau-kalau ada orang yang merasa cukup baik untuk menulis beberapa python untuk Anda).
Pharap
Anda printberbeda karena Anda menggunakan Python 3, dan saya masih menggunakan Python 2. Dan saya tidak yakin apakah pygameporting ke Py3. Intinya: jangan repot-repot :) Pertanyaannya adalah tentang warna, Anda tidak perlu bola yang sebenarnya memantul :)
MestreLion
1

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.

AB
sumber