एक छवि को 4 KiB पूर्वावलोकन में संपीड़ित करें


30

इस चुनौती में आप एक छवि पूर्वावलोकन संपीड़न एल्गोरिदम बना रहे होंगे। यह लक्ष्य है कि एक मनमाना छवि फ़ाइल को 4 KiB पूर्वावलोकन छवि में कम किया जाए, जिसका उपयोग बहुत कम बैंडविड्थ के साथ छवियों को जल्दी से पहचानने के लिए किया जा सकता है।

आपको दो प्रोग्राम (या एक संयुक्त प्रोग्राम) लिखना होगा: एक कंप्रेसर और एक डिकम्प्रेसर। दोनों को इनपुट के रूप में एक फ़ाइल या स्टड लेना चाहिए, और फ़ाइल या स्टडआउट में आउटपुट करना चाहिए। कंप्रेसर को एक छवि को पसंद की मुख्यधारा दोषरहित छवि प्रारूप (जैसे पीएनजी, बीएमपी, पीपीएम) में स्वीकार करना चाहिए, और अधिकतम 4096 बाइट्स की एक फ़ाइल का उत्पादन करना चाहिए । डीकंप्रेसर को कंप्रेसर द्वारा उत्पन्न किसी भी फ़ाइल को स्वीकार करना चाहिए, और इनपुट के जितना संभव हो सके एक छवि को आउटपुट करना चाहिए। ध्यान दें कि एनकोडर / डिकोडर के लिए कोई स्रोत कोड आकार सीमा नहीं है, इसलिए आप अपने एल्गोरिथ्म में रचनात्मक हो सकते हैं।

प्रतिबंध:

  • बेईमानी नहीं'। हो सकता है कि आपके प्रोग्राम छिपे हुए इनपुट्स, इंटरनेट पर डेटा को स्टोर करने आदि का उपयोग न करें। आपको केवल स्कोरिंग छवियों के सेट से संबंधित सुविधाओं / डेटा को शामिल करने से भी मना किया गया है।

  • पुस्तकालयों / उपकरण / बनाया-इन के लिए आप कर रहे हैं उपयोग करने की अनुमति सामान्य छवि प्रसंस्करण संचालन (स्केलिंग, धुंधला, रंग स्थान परिवर्तन, आदि), लेकिन नहीं चित्र डिकोडिंग / एन्कोडिंग / संपीड़न (कंप्रेसर इनपुट और decompressor उत्पादन को छोड़कर) आपरेशनों। सामान्य संपीड़न / विघटन भी अस्वीकृत है । यह इरादा है कि आप इस चुनौती के लिए अपने स्वयं के संपीड़न को लागू करें।

  • डिकम्प्रेसर द्वारा छवि आउटपुट के आयामों को कंप्रेसर को दिए गए मूल फ़ाइल से बिल्कुल मेल खाना चाहिए। आप मान सकते हैं कि छवि आयाम किसी भी दिशा में 2 16 से अधिक नहीं है ।

  • आपके कंप्रेसर को औसत उपभोक्ता पीसी पर 5 मिनट से कम समय में चलना चाहिए, और डिकम्प्रेसर को नीचे दिए गए सेट में किसी भी छवि के लिए 10 सेकंड से कम में चलना चाहिए।

स्कोरिंग

त्वरित सत्यापन और दृश्य तुलना में मदद करने के लिए, अपने उत्तर का उपयोग करके संपीड़न के बाद परीक्षण कॉर्पस की दोषरहित छवि एल्बम को शामिल करें।

आपके कंप्रेशर को छवियों के निम्नलिखित कॉर्पस का उपयोग करके परीक्षण किया जाएगा :

तारों से जड़ा स्रोत कक्ष इंद्रधनुष
हाशिया लामा बच्चा जूलिया

आप यहाँ सभी चित्रों को एक ज़िप फ़ाइल में डाउनलोड कर सकते हैं

आपका स्कोर सभी छवियों पर आपके कंप्रेसर के लिए औसत संरचनात्मक समानता सूचकांक होगा । हम dssimइस चुनौती के लिए खुले स्रोत का उपयोग करेंगे । यह आसानी से स्रोत से बनाया गया है, या यदि आप उबंटू पर हैं तो इसमें एक पीपीए भी है। यह पसंद किया जाता है यदि आप अपना स्वयं का उत्तर देते हैं, लेकिन यदि आप नहीं जानते कि सी अनुप्रयोगों का निर्माण कैसे करें और आप डेबियन / उबंटू नहीं चलाते हैं, तो आप किसी और को आपके लिए स्कोर दे सकते हैं। dssimPNG में इनपुट / आउटपुट की अपेक्षा करता है, इसलिए यदि आप किसी भिन्न प्रारूप में आउटपुट करते हैं तो अपने आउटपुट को पहले PNG में परिवर्तित करें।

दर्द रहित बनाने के लिए, यहाँ एक त्वरित सहायक पायथन लिपि है, उपयोग python score.py corpus_dir compressed_dir:

import glob, sys, os, subprocess

scores = []
for img in sorted(os.listdir(sys.argv[1])):
    ref, preview = (os.path.join(sys.argv[i], img) for i in (1, 2))
    sys.stdout.write("Comparing {} to {}... ".format(ref, preview))
    out = subprocess.check_output(["dssim", ref, preview]).decode("utf-8").split()[0]
    print(out)
    scores.append(float(out))

print("Average score: {:.6f}".format(sum(scores) / len(scores)))

सबसे कम स्कोर जीतता है।


क्या संपीड़ित तस्वीर देखने योग्य है?
यूमेल

2
@Eumel आप एक दर्शक के रूप में डिकम्प्रेसर पर विचार कर सकते हैं। तो नहीं, आपका संकुचित प्रारूप मनमाना हो सकता है और पूरी तरह आप पर निर्भर है। विघटन के बाद ही एक देखने योग्य छवि सामने आती है।
orlp

7
You may assume that the image dimensions do not exceed 2^32 in either direction.क्या यह बहुत अधिक नहीं है? इसका मतलब है कि मुझे (x, y) निर्देशांक की एक जोड़ी को स्टोर करने के लिए 16 बाइट्स का उपयोग करना होगा। कुछ छवि फ़ाइलों में किसी भी दिशा में 2 ^ 16 (65536) पिक्सेल से अधिक के आयाम हैं, और कॉर्पस में सभी छवियों के लिए 2 ^ 11 पर्याप्त है।
पीटर ओल्सन

@PeterOlson मैं इसे बदल दूंगा 2^16
orlp

@orlp नियम बताता है कि एक छवि को डिकोड करने के लिए डिकम्प्रेसर को दस सेकंड से कम समय लेना चाहिए। मेरे पास जो विचार है, वह संभावित रूप से संदर्भ फ़ाइलों को उत्पन्न करने के लिए कुछ मिनट लेगा जो बाद के कॉल में डिकम्प्रेसर में उपयोग किए जाएंगे। यानी यह एक एप्लिकेशन को "इंस्टॉल" करने के समान एक बार बंद गतिविधि है। क्या यह समाधान अयोग्य होगा?
Moogie

जवाबों:


8

पीआईएल के साथ पायथन, स्कोर 0.094218

कंप्रेसर:

#!/usr/bin/env python
from __future__ import division
import sys, traceback, os
from PIL import Image
from fractions import Fraction
import time, io

def image_bytes(img, scale):
    w,h = [int(dim*scale) for dim in img.size]
    bio = io.BytesIO()
    img.resize((w,h), Image.LANCZOS).save(bio, format='PPM')
    return len(bio.getvalue())

def compress(img):
    w,h = img.size
    w1,w2 = w // 256, w % 256
    h1,h2 = h // 256, h % 256
    n = w*h
    total_size = 4*1024 - 8 #4 KiB minus 8 bytes for
                            # original and new sizes
    #beginning guess for the optimal scaling
    scale = Fraction(total_size, image_bytes(img, 1))
    #now we do a binary search for the optimal dimensions,
    # with the restriction that we maintain the scale factor
    low,high = Fraction(0),Fraction(1)
    best = None
    start_time = time.time()
    iter_count = 0
    while iter_count < 100: #scientifically chosen, not arbitrary at all
        #make sure we don't take longer than 5 minutes for the whole program
        #10 seconds is more than reasonable for the loading/saving
        if time.time() - start_time >= 5*60-10:
            break
        size = image_bytes(img, scale)
        if size > total_size:
            high = scale
        elif size < total_size:
            low = scale
            if best is None or total_size-size < best[1]:
                best = (scale, total_size-size)
        else:
            break
        scale = (low+high)/2
        iter_count += 1
    w_new, h_new = [int(dim*best[0]) for dim in (w,h)]
    wn1,wn2 = w_new // 256, w_new % 256
    hn1, hn2 = h_new // 256, h_new % 256
    i_new = img.resize((w_new, h_new), Image.LANCZOS)
    bio = io.BytesIO()
    i_new.save(bio, format='PPM')
    return ''.join(map(chr, (w1,w2,h1,h2,wn1,wn2,hn1,hn2))) + bio.getvalue()

if __name__ == '__main__':
    for f in sorted(os.listdir(sys.argv[1])):
        try:
            print("Compressing {}".format(f))
            with Image.open(os.path.join(sys.argv[1],f)) as img:
                with open(os.path.join(sys.argv[2], f), 'wb') as out:
                    out.write(compress(img.convert(mode='RGB')))
        except:
            print("Exception with {}".format(f))
            traceback.print_exc()
            continue

decompressor:

#!/usr/bin/env python
from __future__ import division
import sys, traceback, os
from PIL import Image
from fractions import Fraction
import io

def process_rect(rect):
    return rect

def decompress(compressed):
    w1,w2,h1,h2,wn1,wn2,hn1,hn2 = map(ord, compressed[:8])
    w,h = (w1*256+w2, h1*256+h2)
    wc, hc = (wn1*256+wn2, hn1*256+hn2)
    img_bytes = compressed[8:]
    bio = io.BytesIO(img_bytes)
    img = Image.open(bio)
    return img.resize((w,h), Image.LANCZOS)


if __name__ == '__main__':
    for f in sorted(os.listdir(sys.argv[1])):
        try:
            print("Decompressing {}".format(f))
            with open(os.path.join(sys.argv[1],f), 'rb') as img:
                decompress(img.read()).save(os.path.join(sys.argv[2],f))
        except:
            print("Exception with {}".format(f))
            traceback.print_exc()
            continue

दोनों लिपियाँ कमांड लाइन तर्कों के माध्यम से दो निर्देशिकाओं (इनपुट और आउटपुट) के रूप में इनपुट लेती हैं, और इनपुट निर्देशिका में सभी छवियों को परिवर्तित करती हैं।

विचार 4 केबी के तहत फिट होने वाले आकार को खोजने का है और मूल के समान पहलू अनुपात है, और संभव के रूप में डाउनसम्पल्ड छवि से उच्च गुणवत्ता प्राप्त करने के लिए लैंक्ज़ोस फ़िल्टर का उपयोग करें।

मूल आयामों के आकार के बाद, संपीड़ित चित्रों का इमगुर एल्बम

स्कोरिंग स्क्रिप्ट आउटपुट:

Comparing corpus/1 - starry.png to test/1 - starry.png... 0.159444
Comparing corpus/2 - source.png to test/2 - source.png... 0.103666
Comparing corpus/3 - room.png to test/3 - room.png... 0.065547
Comparing corpus/4 - rainbow.png to test/4 - rainbow.png... 0.001020
Comparing corpus/5 - margin.png to test/5 - margin.png... 0.282746
Comparing corpus/6 - llama.png to test/6 - llama.png... 0.057997
Comparing corpus/7 - kid.png to test/7 - kid.png... 0.061476
Comparing corpus/8 - julia.png to test/8 - julia.png... 0.021848
Average score: 0.094218

मुझे बस एहसास हुआ कि आपका समाधान वेबपी का उपयोग करता है, जो कि अस्वीकृत है। आपका समाधान अमान्य है।
orlp

@orlp यह PPM का उपयोग करने के लिए अब तय किया गया है, जो एक असम्पीडित प्रारूप है।
Mego

ठीक है। यह चुनौती हालांकि DSSIM की थोड़ी कमजोरी को उजागर करती है। मैं तर्क दूंगा कि ज्यादातर मोगी की छवियां काफी हद तक बेहतर दिखती हैं।
orlp

@orlp वे थंबनेल के रूप में अच्छे दिखते हैं। जब उनके मूल आयामों (लैंक्ज़ोस का उपयोग करके) को उड़ा दिया जाता है, तो वे एक ही गुणवत्ता या बदतर के बारे में देखते हैं। मैं अपने आउटपुट के थंबनेल प्राप्त करने पर काम कर रहा हूँ।
Mego

7

जावा (वेनिला, जावा 1.5+ के साथ काम करना चाहिए), स्कोर 0.672

यह विशेष रूप से अच्छे dssim स्कोर उत्पन्न नहीं करता है लेकिन, मेरी नजर में यह अधिक मानवीय अनुकूल छवियां पैदा करता है ...

तारों से जड़ा स्रोत कक्ष इंद्रधनुष
हाशिया लामा बच्चा जूलिया

एल्बम: http://imgur.com/a/yL31U

स्कोरिंग स्क्रिप्ट आउटपुट:

Comparing corpus/1 - starry.png to test/1 - starry.png... 2.3521
Comparing corpus/2 - source.png to test/2 - source.png... 1.738
Comparing corpus/3 - room.png to test/3 - room.png... 0.1829
Comparing corpus/4 - rainbow.png to test/4 - rainbow.png... 0.0633
Comparing corpus/5 - margin.png to test/5 - margin.png... 0.4224
Comparing corpus/6 - llama.png to test/6 - llama.png... 0.204
Comparing corpus/7 - kid.png to test/7 - kid.png... 0.36335
Comparing corpus/8 - julia.png to test/8 - julia.png... 0.05
Average score: 0.672

संपीड़न श्रृंखला:

1. if filter data has already been generated goto step 6
2. create sample images from random shapes and colours
3. take sample patches from these sample images
4. perform k-clustering of patches based on similarity of luminosity and chomanosity.
5. generate similarity ordered lists for each patch as compared to the other patches.
6. read in image
7. reduce image size to current multiplier * blocksize
8. iterate over image comparing each blocksize block against the list of clustered luminosity patches and chromanosity patches, selecting the closest match
9. output the index of the closet match from the similarity ordered list (of the previous block) (repeat 8 for chromanosity)
10. perform entropy encoding using deflate.
11. if output size is < 4096 bytes then increment current multiplier and repeat step 7
12. write previous output to disk.

डिकम्प्रेस करने के लिए, ब्लॉक इंडेक्स को पढ़ें और आउटपुट फाइल को संबंधित पैच आउटपुट करें, फिर मूल आयामों का आकार बदलें।

दुर्भाग्य से कोड ढेर होने के लिए बहुत बड़ा है इसलिए https://gist.github.com/anonymous/989ab8a1bb6ec14f6ea9 पर पाया जा सकता है

चलाने के लिए:

Usage: 
       For single image compression: java CompressAnImageToA4kibPreview -c <INPUT IMAGE> [<COMPRESSED IMAGE>]
       For multiple image compression: java CompressAnImageToA4kibPreview -c <INPUT IMAGES DIR> [<COMPRESSED IMAGE DIR>]
       For single image decompression: java CompressAnImageToA4kibPreview -d <COMPRESSED IMAGE> [<DECOMPRESSED IMAGE>
       For multiple image decompression: java CompressAnImageToA4kibPreview -d <COMPRESSED IMAGE DIR> [<DECOMPRESSED IMAGES DIR>]

If optional parameters are not set then defaults will be used:
       For single image compression, compressed image will be created in same directory are input image and have '.compressed' file extension.
       For multiple image compression, compressed images will be created in a new 'out' sub directory of <INPUT IMAGES DIR> and have '.compressed' file extensions.
       For single image decompression, decompressed image will be created in same directory are input image and have '.out.png' file extension.
       For multiple image decompression, decompressed images will be created a new 'out' sub directory of <COMPRESSED IMAGE DIR> and have '.png' file extensions.

पहली बार जब इस एप्लिकेशन को चलाया जाता है, तो आवश्यक फाइलें तैयार की जाएंगी और कार्यशील डीआईआर के निष्पादन के सापेक्ष एक निर्देशिका में सहेजा जाएगा। इसमें कुछ मिनट लग सकते हैं। बाद के निष्पादन के लिए, इस चरण को निष्पादित करने की आवश्यकता नहीं होगी।


यह अद्भुत लग रहा है। बस पुष्टि करने के लिए, चरण 1-6 लाश पर बिल्कुल भी भरोसा नहीं करते हैं? इसके अलावा, यदि आप इसके बजाय gist.github.com पर आपके कोड को पुनः साझा करते हैं तो क्या आप बुरा मानेंगे?
orlp

सही है, इनपुट के रूप में कॉर्पस फ़ाइलों में से किसी का उपयोग नहीं करता है। आप उन चित्रों को देख सकते हैं जो पैच को उत्पन्न करने के लिए निरंतर "OUTPUT_SAMPLE_IMAGES" को बदलते हुए खरीदते हैं। यह इन छवियों को कार्यशील फ़ोल्डर में आउटपुट करेगा: डेटा / इमेज / वर्किंग /
Moogie

@orlp अब gist.github का उपयोग कर रहा है
Moogie

परिणाम आश्चर्यजनक हैं, लेकिन सामान्य संपीड़न / विघटन को रोकने के बारे में नियम को तोड़ने / फुलाए जाने का उपयोग नहीं करता है?
अल्जाइमर

@algmyr कुछ समय हो गया है, लेकिन मुझे लगता है कि मैंने नो जेनरिक कम्प्रेशन रूल की व्याख्या की थी, जिसका अर्थ नो जेनरिक 'इमेज' कम्प्रेशन ... यानी जेपीईजी इत्यादि है, लेकिन हो सकता है कि मैंने गलत व्याख्या की हो, जिस स्थिति में, हाँ, यह सबमिशन को डिक्वालिफाई किया जाना चाहिए।
मोगी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.