Catatan : Anders Kaseorg telah dianugerahi terima untuk saat ini, untuk menarik perhatian pada jawaban besarnya, tetapi tantangannya sama sekali tidak berakhir! Masih ada hadiah 400 poin dalam penawaran untuk siapa saja yang mengambil skor tertinggi tanpa menggunakan kompresi bawaan.
Di bawah ini adalah 386x320
representasi png dari Starry Night karya van Gogh.
Tujuan Anda adalah untuk mereproduksi gambar ini sedekat mungkin, tidak lebih dari 1024 byte kode. Untuk keperluan tantangan ini, kedekatan gambar diukur oleh perbedaan kuadrat dalam nilai piksel RGB, seperti yang dijelaskan di bawah ini.
Ini adalah tantangan kode . Skor dihitung menggunakan skrip validasi di bawah ini. Skor terendah menang.
Kode Anda harus mematuhi batasan berikut:
- Itu harus program yang lengkap
- Itu harus menampilkan gambar dalam format yang dapat dibaca oleh skrip validasi di bawah ini, berjalan di mesin saya. Script ini menggunakan pustaka PIL Python, yang dapat memuat berbagai format file , termasuk png, jpg dan bmp.
- Itu harus sepenuhnya mandiri, tidak mengambil input dan tidak memuat file (selain mengimpor perpustakaan, yang diizinkan)
- Jika bahasa atau pustaka Anda menyertakan fungsi yang menghasilkan Starry Night, Anda tidak diizinkan menggunakan fungsi itu.
- Itu harus berjalan secara deterministik, menghasilkan output yang sama setiap waktu.
- Dimensi gambar output harus
386x320
- Untuk menghindari keraguan: jawaban yang valid harus menggunakan bahasa pemrograman sesuai aturan PPCG biasa . Itu harus berupa program yang menampilkan gambar, bukan hanya file gambar.
Kemungkinan beberapa pengiriman sendiri akan dihasilkan oleh kode. Jika demikian, harap sertakan dalam jawaban Anda kode yang digunakan untuk menghasilkan kiriman Anda , dan jelaskan cara kerjanya. Pembatasan di atas hanya berlaku untuk program penghasil gambar 1kB yang Anda kirimkan; mereka tidak berlaku untuk kode apa pun yang digunakan untuk menghasilkannya.
Mencetak gol
Untuk menghitung skor Anda, ambil gambar output Anda dan yang asli di atas dan konversikan nilai-nilai pixel RGB ke angka floating point mulai dari 0 hingga 1. Skor dari sebuah pixel adalah (orig_r-img_r)^2 +(orig_g-img_g)^2 + (orig_b-img_b)^2
, yaitu jarak kuadrat dalam ruang RGB antara dua gambar. Skor gambar adalah jumlah skor pikselnya.
Di bawah ini adalah skrip Python yang melakukan perhitungan ini - dalam hal ada ketidakkonsistenan atau ambiguitas, skor definitifnya adalah yang dihitung oleh skrip yang berjalan di mesin saya.
Perhatikan bahwa skor dihitung berdasarkan gambar output, jadi jika Anda menggunakan format lossy yang akan mempengaruhi skor.
Semakin rendah skor semakin baik. Gambar Starry Night asli akan memiliki skor 0. Dalam acara dasi yang secara astronomis tidak mungkin, jawaban dengan suara terbanyak akan menentukan pemenang.
Tujuan bonus
Karena jawaban didominasi oleh solusi menggunakan kompresi bawaan, saya menghadiahkan serangkaian hadiah untuk jawaban yang menggunakan teknik lain. Yang berikutnya akan menjadi hadiah 400 poin , yang akan diberikan jika dan ketika jawaban yang tidak menggunakan kompresi bawaan mengambil posisi teratas secara keseluruhan.
Hadiah bonus yang sebelumnya diberikan adalah sebagai berikut:
Hadiah 100 poin diberikan untuk jawaban nneonneo , karena menjadi jawaban dengan skor tertinggi yang tidak menggunakan kompresi bawaan pada saat itu. Itu memiliki 4852,87 poin pada saat itu diberikan. Sebutan terhormat masuk ke 2012 Arcampion, yang melakukan upaya berani untuk mengalahkan nneonneo menggunakan pendekatan berdasarkan Voronoi tesselation , mencetak 5076 poin, dan Sleafar, yang jawabannya memimpin hingga akhir, dengan 5052 poin, menggunakan metode yang mirip dengan nneonneo.
Hadiah 200 poin diberikan kepada entri Strawdog . Ini dianugerahi sebagai strategi berbasis optimasi yang memimpin di antara jawaban yang tidak terintegrasi dan menahannya selama seminggu. Ini mencetak 4.949,88 poin menggunakan metode cerdas mengesankan.
Skrip penilaian / validasi
Skrip Python berikut harus ditempatkan di folder yang sama dengan gambar di atas (yang harus dinamai ORIGINAL.png
) dan dijalankan menggunakan perintah dari form python validate.py myImage.png
.
from PIL import Image
import sys
orig = Image.open("ORIGINAL.png")
img = Image.open(sys.argv[1])
if img.size != orig.size:
print("NOT VALID: image dimensions do not match the original")
exit()
w, h = img.size
orig = orig.convert("RGB")
img = img.convert("RGB")
orig_pix = orig.load()
img_pix = img.load()
score = 0
for x in range(w):
for y in range(h):
orig_r, orig_g, orig_b = orig_pix[x,y]
img_r, img_g, img_b = img_pix[x,y]
score += (img_r-orig_r)**2
score += (img_g-orig_g)**2
score += (img_b-orig_b)**2
print(score/255.**2)
Catatan teknis: Ukuran obyektif dari kesamaan gambar adalah hal yang sulit. Dalam hal ini saya telah memilih yang mudah diterapkan oleh siapa pun, dengan pengetahuan penuh bahwa ada langkah-langkah yang jauh lebih baik.
Papan peringkat
sumber
pip unistall PIL
, lalupip install pillow
) dan ganti baris pertama menjadifrom PIL import Image
.Jawaban:
Pyth (tidak ada kompresi
bawaan), skor4695.074656.034444,82Satu-satunya fungsi yang berhubungan dengan gambar Pyth adalah builtin untuk menulis matriks triples RGB sebagai file gambar. Jadi ide gila di sini adalah untuk melatih jaringan saraf kecil dalam pada fungsi ( x , y ) ↦ ( r , g , b ) yang mewakili gambar, dan menjalankannya pada koordinat setiap piksel.
Rencana
Jaringan saat ini dibangun dari 45 neuron sigmoid, dengan setiap neuron terhubung ke input x , y dan ke setiap neuron sebelumnya, dan tiga neuron terakhir ditafsirkan sebagai r , g , b . Itu dilatih menggunakan algoritma Adam tanpa batching. Parameter pembobotan koneksi 1125 dikuantisasi ke kisaran 93 nilai yang mungkin (kecuali syarat konstan, yang memiliki 93 2 nilai yang mungkin) menggunakan varian kuantisasi stokastik , variasi primernya adalah kita menetapkan gradien untuk parameter terkuantisasi menjadi nol.
Hasil
Kode
1023 byte, disandikan dengan
xxd
(decode withxxd -r
). Saya menggunakan versi Pyth 2016-01-22 yang saat ini ketika tantangan ini dirilis. Anda dapat menjalankan kode secara langsung dalam Pyth, tetapi Pyth dalam PyPy3 (pypy3 pyth starry.pyth
) menjalankannya sembilan kali lebih cepat, dalam waktu sekitar 3 menit. Gambar output ditulis untuko.png
.Bagaimana itu bekerja
Latihan
Selama menjalankan pelatihan terakhir saya, saya menggunakan jadwal kuantisasi yang jauh lebih lambat dan melakukan beberapa permainan interaktif dengan itu dan tingkat belajar, tetapi kode yang saya gunakan kira-kira sebagai berikut.
Visualisasi
Gambar ini menunjukkan aktivasi semua 45 neuron sebagai fungsi dari koordinat x , y . Klik untuk memperbesar.
sumber
Mathematica, skor 14125.71333
Simpan gambar ini:
untuk
a.png
.sumber
Java, 7399.80678201
Ini mengingatkan saya pada sebuah proyek yang saya miliki di kelas perhitungan numerik saya beberapa semester yang lalu, yang menggambar siluet Gunung Everest menggunakan interpolasi polinomial. Itu dilakukan di MATLAB, tapi saya tidak terlalu menyukai MATLAB, jadi saya memutuskan untuk bekerja di Jawa. Ide dasar di baliknya adalah bahwa saya memilih poin "pintar" (baca di sini sebagai "acak") untuk interpolasi polinomial. Dengan beberapa byte yang tersisa, saya menciptakan cara bagi bintang-bintang untuk digambar, yang terjadi sebelum menggambar gunung. Dimungkinkan untuk menyingkat kode dan menambahkan polinomial lain untuk bagian bawah untuk membantu memperbaiki skor.
Sunting: Saya telah menambahkan dan mengubah beberapa polinomial dan menambahkan semua bintang. Skor saya sebelumnya adalah 9807.7168935, jadi seperti yang Anda lihat, ini adalah peningkatan yang sangat besar. Sayangnya, kode ini sangat mudah dibaca karena saya harus memeras beberapa byte terakhir untuk mendapatkan semua bintang, dan memberi mereka grup.
9807.7168935 poin: 7399.80678201 poin:
sumber
Python3.4 +, 4697.26
Saya menggunakan metode yang sama seperti pada jawaban ImageMagick saya, tetapi dengan parameter berikut:
Dengan menggunakan parameter ini, saya membuat program Python 1003 byte berikut (saya tidak menemukan perbaikan apa pun atas metode output @ kennytm):
Yang pada gilirannya menghasilkan gambar ini:
sumber
1
darilatin1
dan menyimpan spasi dariimport *
, setidaknya. Tetapi bermain golf itu bukan prioritas (karena kurang dari 1024 byte).Python 3, skor 5701.31
Cukup skala ulang dari gambar 18x13 PNG.
sumber
Java, 8748.95
Pendekatan lain:
Saya membuat kelas yang menghitung Diagram Voronoi dari serangkaian poin yang diberikan. Set poin ini digunakan sebagai set parameter yang berfungsi sebagai input untuk Apache BOBYQAOptimizer . Fungsi evaluasi pengoptimal mengambil poin dan membuat diagram voronoi darinya. Wilayah voronoi diwarnai dengan warna rata-rata dari wilayah yang sesuai dengan gambar aslinya.
Proses optimasi ditunjukkan di sini:
Gambar terakhir adalah yang ini:
yang mencapai skor 8748.95
(Ini diukur dengan fungsi saya sendiri, tetapi harus sama dengan skrip evaluasi)
Hasil dari proses ini hanya satu set 8 poin dan warna yang sesuai. (Jumlah poin yang lebih tinggi menyebabkan hasil yang lebih buruk, tetapi saya tidak mencoba ini secara ekstensif).
Kode yang dihasilkan ditampilkan di sini (maaf, saya harus memasukkan sedikit golf ke batas 1kB):
(Saya tahu, ada beberapa cara mudah yang bisa mencapai hasil yang lebih baik, tapi ... ini entah bagaimana menyenangkan ...)
Menanggapi komentar tersebut, mengenai gaya artistik dari gambar voronoi dengan jumlah poin yang lebih besar: Ini memang terlihat menarik, dan beberapa alat pencitraan sebenarnya menawarkan ini sebagai "Mosaic Filter" - misalnya, Mosaic Filter di GIMP ( meskipun ini menawarkan opsi untuk menekankan sisi dll.)
Berikut adalah contoh gambar Starry Night, dengan 256 poin. (Ini dipilih secara acak, tetapi dengan jumlah poin yang lebih besar, peningkatan yang bisa dicapai dengan optimasi akan hilang).
Ini bukan bagian dari kontes (karena tidak sesuai dengan 1kB), hanya untuk yang penasaran:
sumber
import java.util.*;
Bahkan mengubah semua kelas impor ke tanda bintang.AutoIt ,
9183.257882.53MEMPERBARUI
Jadi ternyata menggambar ulang gambar seperti balita (mabuk) lebih efektif daripada menyimpan versi gambar apa pun. (Lagi pula, lebih efektif daripada solusi lama saya ).
Setiap baris yang menarik elemen sangat penting untuk mengurangi skor. Saya menduga program ini mampu mencapai skor jauh di bawah 7000 dengan modifikasi yang sangat kecil, karena setiap perubahan memiliki efek besar (~ 20 hingga 100 poin) pada skor. Program ini menggunakan
processing
perpustakaan grafik saya yang menyediakan nama fungsi singkat untuk menggambar menggunakan GDI.Karena solusi ini melibatkan keacakan, kami menaburkan PRNG menggunakan nilai konstan
0
menggunakanSRandom(0)
. Kenapa 0? Karena itu hingga 50 poin lebih baik daripada yang lain yangn<=100
saya coba.Kanvas dimulai sebagai kosong
#587092
.Menghasilkan lantai
Bagian bawah gambar (yang ternyata dimulai dengan tepat 233px [sekali lagi, karena titik]) diisi dengan
int(1e4*2.9)
elips persis . Mengubah faktor di sini (atau tempat desimal faktor) dapat mengurangi dan meningkatkan skor dengan banyak poin. Saya puas 2,9 setelah beberapa kali mencoba. Tentu ini akan memakan waktu (beberapa detik).Palet lima warna disediakan:
Gumpalan di lantai
Empat elips digunakan untuk mengatur aksen kontras di dalam area lantai (
$4
adalah penunjuk fungsiellipse()
):Menghasilkan aksen di langit
Beberapa garis digambar menggunakan pena yang lebih tebal untuk mewakili area warna yang signifikan di dalam langit yang terlalu panjang untuk elips:
Menimbang piksel
Setelah di atas, semua bilas dan ulangi sampai kita kehabisan byte. Kemudian blur diterapkan untuk mengelabui metode validasi. Dengan kekerasan, telah ditentukan bahwa jari-jari tepat 20 memberikan hasil terbaik. Ini meningkatkan skor dengan putaran sekitar 1.5k (!).
Gambar akhir
Kode, 985 byte
JAWABAN TUA
Ini menyimpan 80 nilai warna yang membentuk gambar 10x8 px. Gambar mentah ini memiliki skor 10291. Karena 10x8 adalah faktor pikselasi 40px, Gaussian blur diterapkan menggunakan jari-jari 40px untuk menurunkan skor. Ini adalah bagaimana skrip mencapai 9183.25.
Ini adalah data yang disimpan:
File yang dihasilkan adalah True.png:
Panjang program adalah 998 byte :
sumber
1e4*2.9
sama dengan29e3
?File Windows BAT, skor 4458.854
Ukuran program adalah 1024 byte.
Mengkonversi dari gambar BPG yang disandikan base64 ke PNG.
Menggunakan certutil.exe (utilitas Windows standar) dan bpgdec.exe decoder gambar sebagai pustaka.
Kompresi:
sumber
C ++ 11,
7441.681261056997.654348335198.16107651Lebih Banyak Pembaruan
Saya sangat menyukai elips dari Perl sehingga saya harus mencobanya di C ++ 11. Saya menggunakan string mentah untuk mendorong byte ke sana, tetapi untuk sementara saya mendapatkan sedikit perbedaan dengan skor yang saya harapkan dan kode yang dihasilkan. Ternyata Anda sebenarnya tidak dapat menempatkan 0x0d (Carriage Return) mentah, karena g ++ akan mengonversinya menjadi 0x0a (Baris Baru). Jujur saya tidak yakin seberapa sah sumber yang dihasilkan ini, tetapi ia mengkompilasi dan bekerja pada beberapa mesin saya.
Saya juga mencoba algoritma lain, Pencarian Dimensi Adaptif setelah GA terlihat seperti macet, hanya untuk mencoba memoles minimum lokal dan mungkin beruntung dan jatuh ke sumur lain.
Dengan ini, C ++ 11 memberikan skor kompetitif yang mengejutkan (jauh lebih baik daripada dugaan saya semula) ... Saya cukup terkejut bahwa hal ini dapat dilakukan dengan fstream sebagai satu-satunya yang disertakan.
Teks (ya, baris baru ada di sumber sebenarnya ... Saya kira saya bisa menghapusnya):
Hexdump:
Jawaban ini menggabungkan beberapa pendekatan dari jawaban sebelumnya, yang akan saya jelaskan di bawah ini, sayangnya saya akhirnya harus mengikuti program golf agar sesuai dengan
944949 karakter (menurutwc -c
), sehingga tidak terlihat seperti C ++ lagi (permintaan maaf jika ini melanggar aturan tantangan, saya akan mencoba beberapa perbaikan segera). Saya tidak merencanakan ini pada awalnya sehingga masih tidak sepenuhnya dapat diuraikan dan masih ada banyak buah yang menggantung rendah.Hasil yang Diperbarui
Hanya menjalankan algoritma genetika lebih lama telah menghasilkan hasil yang sedikit lebih baik; Namun, mengingat konvergensi telah melambat secara signifikan saya akan mengatakan bahwa metode khusus ini mungkin mulai unggul (atau saya telah jatuh ke dalam minimum lokal yang mendalam). Saya memainkan program terakhir beberapa lagi untuk memeras beberapa persegi panjang lagi (generator tetap sama, kecuali ukuran genom maksimum ditingkatkan).
Menerapkan crossover antar individu akan membantu jika masalahnya adalah minimum lokal yang dalam, tetapi mengingat bahwa itu tetap dalam kisaran yang sama untuk sementara waktu, saya mulai berpikir ini tentang sebaik yang didapat untuk jumlah persegi panjang.
Versi Voronoi, 7331.92407536, 989 karakter
Saya menggunakan Ide Voronoi milik Marco13 dengan kode GA saya. Ini sebenarnya tidak bekerja sebaik yang saya harapkan. Saya hanya bisa menekan beberapa poin lebih banyak daripada persegi panjang. Saya pikir sifat yang berpotensi terpisah dari segi empat karena tumpang tindih membantu skor sedikit. Bagaimanapun, saya sebenarnya menyukai cara ini terlihat jauh lebih baik, meskipun skornya sama dengan entri pertama saya.
Hasil Lama, 7441.68126105, 944 karakter
Sama seperti beberapa entri lainnya, program hanya menggambar persegi panjang yang tumpang tindih. Ini menggunakan PPM biner karena formatnya sederhana (outputnya
a.ppm
, tapi saya mengunggah versi png karena SE tidak suka PPM), dan sepenuhnya deterministik.Penjelasan
Menghasilkan PPM mengambil banyak kode boilerplate, yang berarti saya tidak bisa memiliki terlalu banyak persegi panjang bahkan setelah bermain golf sedikit. Beberapa lagi mungkin dapat diperas di sini untuk meningkatkan skor lebih lanjut.
Sihir yang sebenarnya adalah daftar persegi panjang. Mirip dengan jawaban Wolfgang, saya menggunakan algoritma genetika untuk menemukannya. Sebenarnya implementasinya sebagian besar tidak lengkap, karena rekombinasi antar individu belum terjadi, tetapi mutasi masih terjadi dan peringkat turnamen-style oleh kebugaran membuat organisme terbaik di babak berikutnya. Elitisme juga digunakan, sebagai salinan individu terbaik dari babak terakhir disimpan ke babak berikutnya, sehingga organisme yang paling cocok selalu paling tidak sesuai dengan di babak sebelumnya.
Saya tidak melihat terlalu dekat pada kode Wolfgang sejak saya memulainya kemarin, tetapi tampaknya dia membiarkan warnanya juga bervariasi, yang mungkin menjelaskan perbedaan skor.
Untuk menjaga ruang pencarian lebih kecil, saya hanya melihat posisi persegi panjang; warnanya dihitung dengan rata-rata per-saluran piksel yang terlihat dari segi empat karena kita memiliki gambar sumber (saya tidak berpikir kita bisa melakukan lebih baik dari ini untuk persegi panjang tertentu karena ini meminimalkan jarak kuadrat).
Saya akan memasang repositori github dalam beberapa pengeditan berikutnya jika saya terus mengerjakannya, tetapi untuk saat ini kode (file tunggal) ada di pastebin . Kompilasi dalam mode C ++ 11, (catatan tambahan, saya cukup malu tentang betapa berantakan bahkan untuk sekali saja).
Anda juga akan membutuhkan gambar P3 PPM dari malam berbintang yang dinamai
ORIGINAL.ppm
agar ini berfungsi. Anda dapat mengunduh file dari GitHub Gist ini .sumber
i r,g,b
bukan secara terpisah, dan banyak ruang dapat dibuang). Saya tidak yakin apakah program harus menghasilkan file secara langsung atau apakah pemipaan ke stdout / stderr baik-baik saja.#include <fstream>
? Juga, lepas baris baru dan letakkan semuanya dalam satu baris karena C ++ memerlukan titik komaImageMagick, 4551.71
Menggunakan bahasa 'pemrograman' ImageMagick, menggunakan opsi berikut (Anda mungkin harus melarikan diri dari
!
):Dengan asumsi file sumber 968 byte berikut (diberikan sebagai hexdump):
Memproduksi gambar ini:
Anda mungkin bertanya-tanya bagaimana saya menghasilkan file input, dan jawabannya agak sederhana. Ubah ukuran menjadi 48x40 dengan filter Lanczos, gunakan palet yang diindeks 20 warna, dan optimalkan PNG yang dihasilkan.
Menggunakan
convert
,pngquant
,optipng
danadvdef
.sumber
=(tail +2 $0)
trik dari jawaban saya , Anda dapat membuat skrip ZSH tunggal yang berisi skrip ImageMagick dan file input PNG.Python 2, 4749.88
1018 byte
Semua orang mungkin sudah melupakan masalah ini sekarang, kecuali aku ....
Masalah ini terlalu menarik bagi saya, terutama karena dengan cepat menjadi jelas bahwa pendekatan yang menggunakan algoritma kompresi gambar jelas memimpin, tetapi entah bagaimana tidak memuaskan dari sudut pandang estetika. Pendekatan yang didasarkan pada pengoptimalan satu set gambar primitif entah bagaimana lebih menyenangkan dari sudut pandang kode estetika, tetapi tampaknya terhalang tepat di atas skor 5000.
Metode nneonneo yang tidak menggunakan kompresi gambar rak mengalahkan tanda 5000, tetapi melakukannya dengan menyandikan gambar kecil dan meningkatkannya.
Berikut adalah program yang hanya menggunakan menggambar primitif, dihasilkan secara otomatis dengan metode optimisasi, dan mengelola untuk mendapatkan skor 4749,88.
yang terlihat seperti ini:
dan hexdump dari kode:
Ini menggunakan sejumlah trik yang digunakan sebelumnya di sini:
Sebagai primitif pertama, saya menempatkan garis horizon, membelah gambar menjadi dua blok warna yang berbeda. Setelah itu, sebagai primitif dasar saya menggunakan lingkaran yang diseret antara dua titik. Ini tampak samar-samar seperti sapuan kuas kepada saya, tetapi mungkin untuk mengekspresikan dalam 7 byte. Untuk proses pencarian, saya menggunakan pencarian pola panduan. Ini hasil dengan menambahkan secara primitif, dan mengoptimalkan parameternya. Primitif ditambahkan pada titik di mana kesalahan yang ditandatangani kabur adalah yang tertinggi. Parameter dioptimalkan oleh optimasi garis lengkap melalui domain kecil, satu demi satu. Empat puluh hingga lima puluh primitif ditambahkan, dan dioptimalkan secara individual. Kemudian, daftar primitif dipangkas menjadi ukuran dengan membuang primitif yang membantu skor paling sedikit.
Ini masih belum mengalahkan skor nneonneo. Untuk mengalahkan skor itu, diperlukan pengoptimalan tahap kedua, yang berjalan lagi melalui proses penambahan primitif pada masing-masing beberapa level penyaringan, dan membuang primitif untuk memangkas program yang dihasilkan ke ukuran. Yang benar-benar menarik bagi saya adalah gagasan untuk menerapkan ini pada gambar lain. Saya menerapkannya pada beberapa gambar lain, dan memberikan rincian lebih lanjut dan animasi dari primitif yang diambil di blog saya di sini .
Dua program yang digunakan untuk menghasilkan ini tidak akan benar-benar sesuai dengan ruang yang diperbolehkan pada posting Stack Exchange, tetapi mereka ada di github: https://github.com/str4w/starrynight/tree/StackExchange
starrynight dijalankan terlebih dahulu, diikuti oleh optimalisasi stage2. Program yang dihasilkan juga ada di direktori yang sama.
sumber
Matlab, skor 5388.3
Tanpa kompresi bawaan. Kedalaman warna dikurangi sedemikian rupa sehingga setiap piksel dapat diwakili oleh satu karakter yang dapat dicetak. Dan resolusinya berkurang. Ini kemudian hardcoded sebagai string. Kode itu sendiri membalik seluruh proses. Operasi pengubahan ukuran menggunakan kernel interpolasi Lanczos 3.
sumber
zsh + bpgdec, 4159.061760861207
Ya, solusi BPG lain. Saya pikir ini pada dasarnya berfungsi untuk membuktikan bahwa BPG adalah utilitas kompresi gambar terbaik saat ini tersedia. Anggap itu perbaikan dari solusi BPG asli Yallie .
Panjang file 1024 byte, tepat di batasnya. Terdiri dari garis
diikuti oleh output BPG mentah dari
Dalam hex, ini skripnya:
File yang dihasilkan adalah
out.png
(bpgdec
lokasi default), yang terlihat seperti ini:Saya merasa agak menakjubkan
bpg
, hanya dalam 996 byte, telah secara akurat merekonstruksi kontur tajam pohon, di sebelah kiri, dan bukit-bukit di sebelah kanan. Bahkan memiliki perkiraan yang lumayan untuk menara gereja! Tingkat detailnya sangat mengesankan (bagi saya) untuk ukuran file yang kecil. Tentu saja,bpgdec
itu sendiri bukan program kecil, tetapi jelas bagi saya bahwa BPG adalah urutan besarnya lebih baik daripada JPEG untuk kompresi gambar.Karena ini menggunakan
bpgdec
, jawaban ini jelas tidak memenuhi syarat untuk hadiah.Diedit: Menambahkan
-n
argumentail
untuk membuatnya kompatibel dengan GNUtail
.sumber
tail: cannot open ‘+2’ for reading
. Di Ubuntu dibutuhkan-n +2
, yang membuatnya pada 1025 bytes = /-n+2
yang membuatnya tepat 1024 byte - coba dan beri tahu saya jika itu berhasil. Saya akan mengubah jawaban saya untuk kompatibilitas.C, 6641
999 byte, hanya menggunakan
stdio.h
danmath.h
.Saya membuat fungsi lingkaran penuh
d()
yang menggambar lingkaran berwarna RGB konsentris di atas nilai radius r..0. 21 lingkaran digunakan di sini. Saya bisa memeras lebih banyak lagi jika saya menghapus lebih banyak ruang putih, tapi saya suka keterbacaan relatifnya.Saya menemukan penempatan lingkaran kasar menggunakan lapisan Gimp dalam
Difference
mode. Cari titik terang, tambahkan lingkaran, ulangi.Histogram
Alat yang digunakan saat pemilihan untuk menentukan warna awal yang akan digunakan.Saya mendapat skor sekitar 7700 menggunakan di atas, tetapi saya pikir saya bisa melakukan lebih baik dengan mengubah nilai warna dan jari-jari, jadi saya menulis beberapa kode perancah untuk brute-force mengoptimalkan setiap nilai dengan memodifikasi -10 .. +10, re- rendering, menjalankan validator (yang saya tulis ulang dalam C untuk kecepatan), dan menyimpan nilai yang menghasilkan skor terendah. Pada akhirnya dump array nilai, yang saya tempel kembali ke dalam kode dan kompilasi ulang. Saya berlari beberapa kali, dan itu membuat skor turun sekitar 1000. Kemudian saya menanggalkan kode perancah.
Kode,
sumber
((x-xo)*(x-xo) + (y-yo)*(y-yo)) <= (r*r)
) sepertinya akan lebih pendek dan menghilangkan ketergantunganmath.h
. Dengan ukuran gambar ini saya tidak berpikir ada yang punya peluang meluap juga.Python 3, skor 5390,25, 998 byte
Saya menggunakan program anil simulasi untuk menyesuaikan persegi panjang ke dalam bentuk Starry Night. Kemudian menggunakan blur Gaussian untuk menghaluskan tepi persegi panjang lurus.
Untuk menyimpan beberapa byte, saya mengompres data persegi panjang ke basis 94.
sumber
Python 2, 5238.59 poin
Mungkin ini saatnya untuk memposting jawaban saya sendiri. Ini gambarnya
Kode terlihat seperti ini
Atau sebagai hex dump:
Ini hanya membongkar string yang panjang itu ke dalam parameter untuk menggambar 95 elips yang tembus cahaya.
Seperti banyak jawaban lain, kode dihasilkan menggunakan algoritma genetika. Ia menggunakan jenis tertentu dari algoritma genetika yang saya temukan, yang saya sebut "algoritma gen pool", meskipun sangat mungkin bahwa orang lain juga telah menciptakannya dan memberinya nama yang berbeda. Alih-alih memiliki populasi individu, kami memiliki 95 "kumpulan gen", satu untuk setiap gen. Setiap kumpulan gen berisi 10.000 versi gen yang berbeda. Gen berisi parameter untuk satu elips (posisi, bentuk, warna, alfa dan tempatnya dalam urutan z). Pada setiap iterasi kami membuat dua gambar dengan memilih satu gen dari masing-masing 95 kelompok, dan gen dari gambar dengan skor terendah menggantikan gen dari gambar dengan skor terburuk, dengan sedikit mutasi.
Saya menjalankannya sampai sekitar iterasi ke-378000, yang membutuhkan beberapa hari. Pada saat itu skor masih turun, tetapi benar-benar sangat lambat, jadi saya ragu itu akan jauh lebih baik daripada ini tanpa beberapa perubahan pada algoritma.
Berikut kode algoritma genetika:
Akhirnya, ini adalah animasi , yang menunjukkan algoritma di tempat kerja. Ini menunjukkan gambar terbaik yang dihasilkan sejauh ini setelah setiap 1000 iterasi. (File gif terlalu besar untuk disematkan pada pos ini.)
Ini mungkin dapat ditingkatkan dengan (1) menggunakan trik enkode nneonneo untuk menjejalkan lebih banyak data ke dalam string; (2) menambahkan Gaussian blur ke akhir kode render (tapi itu akan membuatnya lebih lambat) dan (3) meningkatkan algoritme lebih jauh. Pada saat itu mencapai skor yang layak dengan sangat cepat tetapi kemudian berubah sangat lambat setelah itu - jika saya memperlambat konvergensi awal entah bagaimana, itu mungkin akan menemukan hasil yang lebih baik pada akhirnya. Mungkin saya akan menerapkan hal-hal ini di beberapa titik.
sumber
Penuh bintang ,
11428.189450210904.307927710874.1307958Starry mungkin bukan bahasa terbaik untuk melakukan ini, tetapi itu tentu yang paling pas.
Anda dapat mencobanya secara online namun tampaknya output terpotong sehingga Anda tidak akan mendapatkan gambar lengkap.
Program ini mengeluarkan file ppm yang tidak terkompresi ke standar keluar.
Ini adalah output program:
Penjelasan
Untuk membuat output program, semua 123.520 piksel diperlukan, saya membagi gambar menjadi 8 band horisontal dan membuat 7 loop pertama 6 masing-masing mencetak band sementara yang terakhir mencetak dua band dengan warna yang sama. Kode terdiri dari header, yang memberi tahu file ppm cara memformat dirinya sendiri dan 7 loop yang disebutkan di atas.
sumber
Python 2, 4684.46
1021 byte.
Ini menggunakan metode decode yang sangat mirip dengan beberapa jawaban lain, tetapi dalam Python 2 jadi itu base64 data yang di-encode bukannya base85.
Data yang dikodekan adalah gambar format WebP 64x48.
Berikut kode yang saya gunakan untuk menemukan ukuran gambar dan pengaturan kualitas terbaik. Saya membatasi ruang pencarian sehingga tidak perlu lebih dari beberapa menit untuk berjalan.
sumber
Python 2,
5098.245080.044869.154852.874755.88589004Tidak ada dekompresi bawaan yang digunakan! Utilitas pengubahan ukuran saja PIL dan gambar 16-warna yang diterjemahkan secara manual. Karena itu harus memenuhi syarat untuk hadiah.
Program ini berisi karakter non-ASCII tertanam. Panjangnya 1024 byte dan terlihat seperti ini:
dan dalam hex:
dan menghasilkan gambar ini:
Program ini menyalahgunakan fakta bahwa Anda pada dasarnya dapat mendorong byte mentah ke dalam kode sumber Python selama Anda lolos dari NUL dan backslash.
Program itu sendiri terdiri dari 16-entri palet (
|
string yang dipisahkan) dan gambar 16-warna 40x41 (dikodekan dengan 4 bit per piksel, dan diterjemahkan dengan menyalahgunakan.encode('hex')
). Gambar diubah ukurannya menjadi ukuran yang sesuai dengan filter bikubik, dan hanya itu.Gambar aktual dihasilkan dengan ImageMagick:
dan data palet dan gambar diekstraksi dari BMP yang dihasilkan. (Perhatikan bahwa kami meminta 18 warna dari ImageMagick, karena IM secara otomatis memasukkan beberapa entri yang tidak digunakan).
Palet disusun ulang sedikit untuk mengurangi jumlah karakter yang lolos dalam data biner, dan data biner akhir diedit sedikit dengan tangan untuk mendapatkan semuanya agar sesuai dengan 1024 byte.
Diedit: Memutar kode sedikit, dan meningkatkan akurasi dengan meminta 17 warna dari ImageMagick.
DIedit: Menonaktifkan dithering menghasilkan peningkatan besar dalam skor. Sekarang skor jauh di bawah 5.000, dan menjadi kompetitif dengan algoritma kompresi yang tersedia!
DIedit: Menambahkan
-filter Cosine
memberi peningkatan yang cukup besar. Bermain golf agresif, dengan terima kasih kepada @primo untuk trik UTF-8 BOM, memungkinkan saya untuk menempelkan baris lain pada gambar, semakin meningkatkan skor.sumber
!
Sebenarnya diapit di kedua sisi oleh karakter yang tidak dapat dicetak. Warna penuh adalah#1d211e
, yang abu-abu gelap agak kebiruan.#coding:latin
saluran dapat diganti dengan tanda pesanan byte UTF-8:
(0xEF, 0xBB, 0xBF).zsh + FLIF + ImageMagick, 4358.14
Dengan BPG mencuri sorotan sebagai codec lossy, saya telah memperbaiki pendekatan kelas atas lossless saya untuk menggunakan FLIF, bukan PNG, menggunakan zsh trick @ nneonneo. ImageMagick hanya digunakan di sini sebagai upscaler.
Hexdump (kali ini dengan
xxd
, saya tidak sadarihexdump
adalah tidak standar dalam jawaban terakhir saya):Saya telah membuat skrip menggunakan ... skrip lain:
sumber
Mathematica, 5076.54
Beratnya tepat pada 1024 byte, saya akhirnya berhasil mengalahkan skor nneonneo ... sampai dia memperbaikinya satu jam yang lalu = (
Tidak menggunakan algoritma kompresi "off-the-shelf".
(Deskripsi yang lebih baik nanti)
sumber
HTML / JavaScript,
10855.838000.55 (± ~ 5, berdasarkan browser)Skor mungkin sedikit berbeda karena perbedaan browser atau GPU.
Anda harus mengklik kanan> Simpan Gambar Sebagai untuk menyimpan data kanvas sebagai gambar, tetapi hanya itu interaksi yang diperlukan.
Saya menggunakan GIMP untuk memilih area tertentu dan menemukan rata-rata mereka. Secara khusus, alat pemilih warna dan fitur "perbedaan lapisan" sangat membantu.
Percobaan # 1 (10855.83)
Percobaan # 2 (8000.55)
sumber
Scala, 6003.56
993 karakter. Satu impor adalah scala image library . Impor kedua adalah basis 91 encoder .
Ini adalah data base91:
sumber
Java, skor 12251.19
Berdasarkan jawaban Mathematica ini , tetapi dengan lebih banyak persegi panjang. Saya mungkin akan terus memodifikasi ini nanti.
Hasil:
Beberapa versi sebelumnya:
sumber
Python 2 (tidak ada kompresi bawaan), skor 4497.730
Ini menggunakan pendekatan gambar 16-warna yang diterjemahkan secara manual sama seperti jawaban saya sebelumnya , tapi kali ini saya benar-benar menerapkan strategi optimasi gradient-descent untuk secara signifikan meningkatkan skor. Pengajuan sebelumnya mencetak 4755,886 poin, sedangkan pengajuan baru skor lebih dari 250 poin lebih baik, mengalahkan banyak pendekatan kompresi built-in dalam proses.
Seperti sebelumnya, program final panjangnya tepat 1024 byte. Bahkan, output mentah dari algoritma optimasi berisi empat byte yang lolos (
\0
), dan yang saya harus "fudge" untuk mengurangi jumlah byte menjadi 1024 byte. Tanpa fudge, program 1028-byte akan mencetak skor 4490,685 - 7 poin lebih baik.Ide dasarnya adalah untuk mengoptimalkan palet dan data secara bersama-sama. Dalam satu iterasi tunggal, saya mencari semua tweak palet (pada dasarnya, setiap palet yang dimodifikasi berbeda 1 dalam beberapa komponen warna) dan memilih palet yang dimodifikasi yang paling baik meningkatkan skor. Kemudian, saya mencari semua tweak data (setiap array indeks yang dimodifikasi di mana satu piksel diubah ke beberapa entri palet lainnya) dan memilih modifikasi yang mengurangi skor (di sini saya tidak peduli yang terbaik, karena saya tidak peduli ingin tanpa hasil mencari ruang penuh lebih dari 25000 tweak setiap iterasi).
Akhirnya, ketika menghasilkan output program akhir, saya menjalankan pass optimisasi lain yang mengatur ulang palet untuk meminimalkan jumlah backslash yang diperlukan dalam output akhir (misalnya untuk program yang ditunjukkan di bawah ini, palet disusun ulang menggunakan tabel hex "0e3428916b7df5ca").
Pendekatan ini menghasilkan peningkatan numerik dan persepsi yang signifikan dibandingkan dengan pendekatan ImageMagick naif sebelumnya. Hasil pengiriman sebelumnya:
Dan keluaran pengiriman baru:
Pendekatan berbasis optimasi baru memiliki reproduksi warna yang lebih detail dan akurat.
Berikut adalah hexdump dari program akhir:
Masih ada ruang untuk diperbaiki. Misalnya, histogram sederhana menunjukkan bahwa beberapa warna hampir tidak digunakan:
Ini menunjukkan bahwa palet yang diseimbangkan ulang dapat meningkatkan efisiensi, mungkin cukup untuk menangkap solusi BPG ke-5. Namun, saya sangat ragu bahwa pendekatan optimasi ini (atau benar-benar, apa pun yang tidak melibatkan mesin H.265 yang luar biasa) dapat menangkap penerapan BPG di tempat pertama.
sumber
Perl,
5955.968781245149.56218378Melihat pendekatan "omong kosong yang tidak dapat dicetak", saya memutuskan untuk mencobanya juga di Perl. Sekali lagi, saya tidak benar-benar tahu Perl, jadi saya yakin ini bisa diperbaiki (sebenarnya, peningkatan yang paling jelas, reduksi menjadi 7 byte per elips dengan menghilangkan saluran alpha, sudah diterapkan untuk versi berikutnya, tapi saya ' Saya masih bekerja pada bagian lain dari kode itu; Saya juga berpikir seluruh bisnis pop / push dapat golf lebih banyak).
Saya tidak berpikir ini akan benar-benar bekerja pada mesin Windows (saya tidak bisa menguji), karena saya tidak bisa menemukan cara mudah untuk membuka bagian DATA dalam mode biner - namun ini telah bekerja pada mesin linux saya.
Pada dasarnya saya dapat terus menggunakan kode GA yang sama untuk membuat:
Di mana output xxd adalah:
Yang menghasilkan gambar:
Sangat menarik bahwa meskipun skornya lebih baik, gambarnya terlihat agak buruk bagi saya - terlalu banyak yang terjadi dengan semua elips ekstra, entah bagaimana gambar yang lebih sederhana lebih mudah untuk ditangani secara visual.
Hasil Lama
Setelah melihat jawaban jamieguinan , saya menggunakan elips sebagai gambar primitif karena di Perl saya memiliki akses ke perpustakaan GD untuk menggambar. Saya bukan ahli Perl sama sekali, jadi saran apa pun akan berguna. Saya menggunakan algoritma genetika yang dimodifikasi dari jawaban C ++ saya .
Tampaknya bekerja dengan baik, tetapi jujur saya agak kecewa dengan skor. Saya mungkin bisa membiarkannya berjalan sedikit lebih lama karena Anda dapat dengan mudah melihat bahwa beberapa elips tidak dalam posisi optimal. Namun, bahkan sekarang itu terlihat lebih bagus di mata saya dibandingkan dengan solusi berbasis persegi panjang.
sumber
Bash + Netpbm,
4558.54394.1UPDATE: Saya telah meningkatkan skor dengan menggunakan SPIHT dan bukan FIASCO.
SPIHT adalah singkatan dari Set Partitioning In Hierarchical Trees. Ini adalah format kompresi gambar berbasis wavelet yang sangat efisien.
Saya mengecilkan PNG asli dengan kuartal, kemudian dikonversi ke PNM menggunakan
pngtopnm
dari Netpbm v. 10.68, kemudian menghapus header dan mengkonversi data RAW ke SPIHT dengancodecolr in.raw out.spi 80 96 0.95
dan mendapatkan file gambar 913-byte. Kemudian saya mengubahnya kembali menjadi RAW menggunakandecdcolr -s out.spi out.raw 0.95
, selanjutnya dikonversi ke format PNM menggunakanrawtoppm -bgr 96 80
, membalik menggunakanpamflip -tb
, upcaled ke ukuran asli menggunakanpamscale -xsize 386 -ysize 320 -filter sinc
dan disimpan ke file PNM, yang dibaca oleh PIL. Ini skrip saya (1KB):Berikut adalah output PNG:
Di bawah ini adalah jawaban awal saya:
FIASCO adalah singkatan dari Fractal Image And Sequence COdec, ini adalah implementasi kompresi fraktal lossy yang sangat efisien.
Saya menyusutkan PNG asli dengan kuartal, kemudian dikonversi ke PNM menggunakan
pngtopnm
dari Netpbm v. 10.68, kemudian dikonversi ke FIASCO denganpnmtofiasco -q=14 -z=3
dan mendapat file gambar 969-byte. Kemudian saya mengkonversikannya kembali ke menggunakan PNMfiascotopnm
, ditingkatkan ke ukuran asli menggunakanpamscale -xyfill 386 320
dan disimpan ke file PNM, yang dibaca oleh PIL. Ini skrip saya (1KB):Sebenarnya, saya pertama kali melakukan ini di Windows
cmd
, tetapi skrip tidak muat di 1KB. Lalu aku menulis ulangbash
. Berikut adalah output PNG:sumber
Ruby, 7834.38
Ini sangat menyenangkan!
Saya menggunakan program penghasil ruby untuk menulis skrip ruby sebagai berikut:
Sementara file ruby yang dihasilkan kurang dari 1024 byte:
Perhatikan bahwa algoritme pemberian skor saya secara acak sampel banyak warna dan memilih salah satu yang menghasilkan perbedaan terkecil dari ORIGINAL.png. Karena probabilistik, saya telah menjalankan kembali skrip beberapa kali dan memilih hasil skor terendah.
Berikut ini skrip terbaik saya:
Ini menghasilkan gambar berikut, yang mencetak 7834 poin:
Untuk melihat bagaimana algoritma saya menghasilkan ini, berikut ini adalah GIF animasi yang menunjukkan cara memecahnya menjadi empat persegi panjang:
Kode saya terserah pada GitHub di https://github.com/jrotter/starry_night_contest
sumber
Java, 9215.38294502
Membaca gambar sebagai GIF dengan ukuran 8x6 piksel (!) Dari String yang disandikan Base64 (berisi 368 karakter), dan memperbesarnya dengan bilinearly.
EDIT: Hasilnya, sesuai permintaan dalam komentar, ditunjukkan pada gambar ini:
sumber
Python 3, 5797.125628604383
Program kompresi pertama memotong bit gambar, dan kemudian mengubah basis 2 ke basis 36.
Program decode melakukan itu secara terbalik, dan mengubah ukuran gambar.
sumber