लाइनों का उपयोग करके एक छवि को पुन: पेश करें


31

एक प्रोग्राम लिखें जो एक वास्तविक-रंग आरजीबी छवि I में होता है , L को खींचने के लिए अधिकतम पंक्तियाँ और प्रत्येक पंक्ति की न्यूनतम m और अधिकतम M लंबाई। आउटपुट एक छवि हे कि लगता तक संभव हो, की तरह मैं और तैयार की है का उपयोग कर एल या उससे कम सीधी रेखाएं, जो सभी के बीच इयूक्लिडियन लंबाई मीटर और एम

प्रत्येक पंक्ति का एक ठोस रंग होना चाहिए, दोनों छोरों को O की सीमा में होना चाहिए, और Bresenham की लाइन एल्गोरिथ्म का उपयोग करके तैयार किया जाना चाहिए (जो कि अधिकांश ग्राफिक्स लाइब्रेरी आपके लिए पहले से ही करेंगे)। व्यक्तिगत लाइनें केवल 1-पिक्सेल मोटी हो सकती हैं।

सभी पंक्तियों, यहां तक ​​कि उन की लंबाई 0, कम से कम एक पिक्सेल लेना चाहिए। एक दूसरे के ऊपर रेखाएँ खींची जा सकती हैं।

किसी भी रेखा को खींचने से पहले आप O की पृष्ठभूमि को किसी भी ठोस रंग से जोड़ सकते हैं (जो कि I पर निर्भर हो सकता है )।

विवरण

  • में मेरे जैसे ही आयाम होने चाहिए ।
  • एल हमेशा एक नॉनवेजेटिव पूर्णांक होगा। यह I के क्षेत्र से अधिक हो सकता है ।
  • m और M, M > = m के साथ नॉनवेजेटिव फ्लोटिंग पॉइंट नंबर हैं । दो पिक्सल के बीच की दूरी उनके केंद्रों के बीच यूक्लिडियन दूरी है। यदि यह दूरी m से कम या M से अधिक है , तो उन पिक्सेल के बीच एक रेखा की अनुमति नहीं है।
  • लाइनों को एंटीअलियास नहीं किया जाना चाहिए।
  • अपारदर्शिता और अल्फा का उपयोग नहीं किया जाना चाहिए।
  • आपके प्रोग्राम को एक लाख पिक्सेल से कम और 10,000 से कम एल के साथ छवियों पर एक सभ्य आधुनिक कंप्यूटर पर चलाने के लिए एक घंटे से अधिक समय नहीं लेना चाहिए ।

परीक्षण छवियाँ

आप निश्चित रूप से हमें अपने सबसे सटीक या दिलचस्प उत्पादन छवियों (जो मैं तब होगा जब उम्मीद दिखाना चाहिए एल में 5% और पिक्सेल की संख्या का 25% के बीच है मैं , और मीटर और एम के आसपास विकर्ण आकार का दसवां हैं)।

यहाँ कुछ परीक्षण चित्र (मूल के लिए क्लिक करें) हैं। आप अपनी खुद की पोस्ट भी कर सकते हैं।

मोना लीसा झरना Nighthawks तारों भरी रात गोल्डन गेट ब्रिज

सरल चित्र:

पेनरोज़ सीढ़ियाँमोबियस स्ट्रिप हिल्बर्ट वक्र

यह एक लोकप्रियता प्रतियोगिता है। सबसे अधिक मतदान प्रस्तुत करने वाली जीत।

टिप्पणियाँ

  • यह I में कुल पिक्सल के प्रतिशत के साथ-साथ निरपेक्ष मान से L को प्राप्त करने में मददगार हो सकता है । जैसे एक ही बात हो के रूप में होता है, तो एक 8 से 8 पिक्सेल छवि थे। कुछ इसी तरह के लिए किया जा सकता है मीटर और एम । इसकी आवश्यकता नहीं है।>>> imageliner I=img.png L=50% m=10 M=20>>> imageliner I=img.png L=32 m=10 M=20img.png
  • चूंकि रेखाएं सीमा से बाहर नहीं जा सकती हैं, इसलिए संभव सबसे लंबी लाइनें I की विकर्ण लंबाई होगी । इससे अधिक होने पर M को कुछ भी नहीं तोड़ना चाहिए।
  • स्वाभाविक रूप से, अगर मीटर 0 और एल अधिक है की तुलना में या में पिक्सेल की संख्या के बराबर रहा , हे के समान हो सकता है मैं प्रत्येक पिक्सेल स्थान पर लंबाई 0 "लाइनों" होने से। इस व्यवहार की आवश्यकता नहीं है।
  • यकीनन, रंग को पुन: प्रस्तुत करने की तुलना में I के आकार को पुन: प्रस्तुत करना अधिक महत्वपूर्ण है। आप एज डिटेक्शन में देखना चाहते हैं ।

स्पष्ट करने के लिए: क्या SimpleCV जैसी पुस्तकालयों की अनुमति है? और उत्तर में I, L, m, और M के लिए कोई विकल्प हो सकता है, जिसमें m = 0 और L = क्षेत्र शामिल है?
रैशनलिस

@epicwisdom हां, सभी पुस्तकालयों (उन चीजों को छोड़कर, जो पहले से ही विशेष रूप से इस कार्य को करने की अनुमति है)। जो भी हो, कीपिंग, एज डिटेक्शन का बेझिझक इस्तेमाल करें। आपके एल्गोरिदम को I , L , m , M के किसी भी वैध विकल्प के लिए काम करना चाहिए , जिसमें m = 0 और L = क्षेत्र शामिल हैं। (हालांकि, आपका एल्गोरिथ्म मापदंडों के विशेष ट्यूनिंग के लिए बेहतर लग सकता है।)
केल्विन के शौक

फिर, उदाहरण के लिए, इस विशेष लाइब्रेरी एल्गोरिदम को एक अमान्य उत्तर माना जाएगा?
तर्कसंगत

@epicwisdom दरअसल मैं इसकी और इसी तरह की अन्य चीजों की अनुमति दूंगा। ऐसा लगता है कि यह अभी भी कुछ चालाक ले जाएगा एक छवि बनाने के लिए लाइनों से यह आपको देता है।
केल्विन के शौक

1
क्या लाइनों की मोटाई 1 होनी चाहिए?
aditsu

जवाबों:


21

सी ++ - कुछ यादृच्छिक लाइनें और फिर कुछ

पहले कुछ बेतरतीब लाइनें

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

चीजें जो मैंने देखीं और कार्यान्वयन को प्रभावित किया:

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

मैं कुछ नंबरों के साथ प्रयोग कर रहा था, और चुना L=0.3*pixel_count(I)और छोड़ दिया m=10और M=50। यह लाइनों की संख्या के लिए चारों ओर 0.25से शुरू होने वाले अच्छे परिणामों का उत्पादन करेगा 0.26, लेकिन मैंने सटीक विवरण के लिए अधिक स्थान के लिए 0.3 का चयन किया।

पूर्ण आकार की गोल्डन गेट छवि के लिए, इसने 235929 पंक्तियों को चित्रित किया (जिसके लिए यहां 13 सेकंड का समय लगा)। ध्यान दें कि यहां सभी चित्र कम आकार में प्रदर्शित किए गए हैं और आपको उन्हें पूर्ण समाधान देखने के लिए एक नए टैब में खोलने / डाउनलोड करने की आवश्यकता है।

अयोग्य को मिटाओ

अगला कदम बल्कि महंगा है (235k लाइनों के लिए इसे लगभग एक घंटे का समय लगता है, लेकिन "1 मेगापिक्सेल पर 10k लाइनों के लिए एक घंटे के भीतर" अच्छी तरह से होना चाहिए), लेकिन यह भी थोड़ा आश्चर्य की बात है। मैं पहले से चित्रित सभी लाइनों के माध्यम से जाता हूं, और उन लोगों को हटा देता हूं जो छवि को बेहतर नहीं बनाते हैं। यह मुझे इस रन में केवल 97347 लाइनों के साथ छोड़ता है जो निम्नलिखित छवि का निर्माण करते हैं:

संभवतः आपको सबसे अधिक अंतरों को देखने के लिए एक उपयुक्त छवि दर्शक में डाउनलोड करने और उनकी तुलना करने की आवश्यकता है।

और फिर से शुरू करें

अब मेरे पास बहुत सारी लाइनें हैं जिन्हें मैं फिर से 235929 के लिए फिर से पेंट कर सकता हूं। कहने के लिए बहुत कुछ नहीं है, इसलिए यहां छवि है:

यहाँ छवि विवरण दर्ज करें

अल्प विश्लेषण

पूरी प्रक्रिया एक धुंधला फ़िल्टर की तरह काम करती है जो स्थानीय कंट्रास्ट और ऑब्जेक्ट आकारों के प्रति संवेदनशील है। लेकिन यह देखना भी दिलचस्प है कि लाइनें कहाँ चित्रित की जाती हैं, इसलिए कार्यक्रम इन्हें भी रिकॉर्ड करता है (प्रत्येक पंक्ति के लिए, पिक्सेल रंग को एक कदम व्हिटर बनाया जाएगा, अंत में इसके विपरीत अधिकतम होता है)। यहाँ ऊपर के तीन रंगों के अनुरूप हैं।

एनिमेशन

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

कुछ और

जैसा कि अनुरोध किया गया है, यहां अन्य छवियों के कुछ परिणाम हैं (फिर से आपको उन्हें नीचे नहीं करने के लिए एक नए टैब में खोलने की आवश्यकता हो सकती है)

भविष्य के विचार

कोड के साथ चारों ओर खेलना कुछ अंतरंग बदलाव दे सकता है।

  • औसत के आधार पर यादृच्छिक के बजाय लाइनों के रंग को चुनो। आपको दो से अधिक चक्रों की आवश्यकता हो सकती है।
  • पास्टबिन के कोड में एक आनुवंशिक एल्गोरिथ्म का भी कुछ विचार होता है, लेकिन छवि शायद पहले से ही इतनी अच्छी है कि इसमें कई पीढ़ियों का समय लगेगा, और यह कोड "एक घंटे" नियम में फिट होने के लिए बहुत धीमा है।
  • मिटा / दमन, या यहां तक ​​कि दो का एक और दौर ...
  • जहाँ रेखाएँ मिटाई जा सकती हैं, उनकी सीमा बदलें (जैसे "lest N पर छवि को बेहतर बनाना चाहिए")

कोड

ये सिर्फ दो मुख्य उपयोगी कार्य हैं, पूरा कोड यहां फिट नहीं है और http://ideone.com/Z2P6Ls पर पाया जा सकता है

bmpवर्गों rawऔर raw_lineसमारोह एक वस्तु है कि प्रारूप बीएमपी के लिए लिखा जा सकता है में क्रमशः पहुँच पिक्सल और लाइनों करते हैं (यह सिर्फ कुछ हैक चारों ओर झूठ बोल रही थी और मैंने सोचा कि यह कुछ हद तक किसी भी पुस्तकालय से स्वतंत्र करता है)।

इनपुट फ़ाइल प्रारूप PPM है

std::pair<bmp,std::vector<line>>  paint_useful( const bmp& orig, bmp& clone, std::vector<line>& retlines, bmp& layer, const std::string& outprefix, size_t x, size_t y )
{
        const size_t pixels = (x*y);
        const size_t lines = 0.3*pixels;
//      const size_t lines = 10000;

//      const size_t start_accurate_color = lines/4;

        std::random_device rnd;

        std::uniform_int_distribution<size_t> distx(0,x-1);
        std::uniform_int_distribution<size_t> disty(0,y-1);
        std::uniform_int_distribution<size_t> col(-15,15);
        std::uniform_int_distribution<size_t> acol(0,255);

        const ssize_t m = 1*1;
        const ssize_t M = 50*50;

        retlines.reserve( lines );

        for (size_t i = retlines.size(); i < lines; ++i)
        {
                size_t x0;
                size_t x1;

                size_t y0;
                size_t y1;

                size_t dist = 0;
                do
                {
                        x0 = distx(rnd);
                        x1 = distx(rnd);

                        y0 = disty(rnd);
                        y1 = disty(rnd);

                        dist = distance(x0,x1,y0,y1);
                }
                while( dist > M || dist < m );

                std::vector<std::pair<int32_t,int32_t>> points = clone.raw_line_pixels(x0,y0,x1,y1);

                ssize_t r = 0;
                ssize_t g = 0;
                ssize_t b = 0;

                for (size_t i = 0; i < points.size(); ++i)
                {
                        r += orig.raw(points[i].first,points[i].second).r;
                        g += orig.raw(points[i].first,points[i].second).g;
                        b += orig.raw(points[i].first,points[i].second).b;
                }

                r += col(rnd);
                g += col(rnd);
                b += col(rnd);

                r /= points.size();
                g /= points.size();
                b /= points.size();

                r %= 255;
                g %= 255;
                b %= 255;

                r = std::max(ssize_t(0),r);
                g = std::max(ssize_t(0),g);
                b = std::max(ssize_t(0),b);

//              r = acol(rnd);
//              g = acol(rnd);
//              b = acol(rnd);

//              if( i > start_accurate_color )
                {
                        ssize_t dp = 0; // accumulated distance of new color to original
                        ssize_t dn = 0; // accumulated distance of current reproduced to original
                        for (size_t i = 0; i < points.size(); ++i)
                        {
                                dp += rgb_distance(
                                                                                orig.raw(points[i].first,points[i].second).r,r,
                                                                                orig.raw(points[i].first,points[i].second).g,g,
                                                                                orig.raw(points[i].first,points[i].second).b,b
                                                                        );

                                dn += rgb_distance(
                                                                                clone.raw(points[i].first,points[i].second).r,orig.raw(points[i].first,points[i].second).r,
                                                                                clone.raw(points[i].first,points[i].second).g,orig.raw(points[i].first,points[i].second).g,
                                                                                clone.raw(points[i].first,points[i].second).b,orig.raw(points[i].first,points[i].second).b
                                                                        );

                        }

                        if( dp > dn ) // the distance to original is bigger, use the new one
                        {
                                --i;
                                continue;
                        }
                        // also abandon if already too bad
//                      if( dp > 100000 )
//                      {
//                              --i;
//                              continue;
//                      }
                }

                layer.raw_line_add(x0,y0,x1,y1,{1u,1u,1u});
                clone.raw_line(x0,y0,x1,y1,{(uint32_t)r,(uint32_t)g,(uint32_t)b});
                retlines.push_back({ (int)x0,(int)y0,(int)x1,(int)y1,(int)r,(int)g,(int)b});

                static time_t last = 0;
                time_t now = time(0);
                if( i % (lines/100) == 0 )
                {
                        std::ostringstream fn;
                        fn << outprefix + "perc_" << std::setw(3) << std::setfill('0') << (i/(lines/100)) << ".bmp"; 
                        clone.write(fn.str());
                        bmp lc(layer);
                        lc.max_contrast_all();
                        lc.write(outprefix + "layer_" + fn.str());
                }

                if( (now-last) > 10 )
                {
                        last = now;
                        static int st = 0;
                        std::ostringstream fn;
                        fn << outprefix + "inter_" << std::setw(8) << std::setfill('0') << i << ".bmp";
                        clone.write(fn.str());

                        ++st;
                }
        }
        clone.write(outprefix + "clone.bmp");
        return { clone, retlines };
}


void erase_bad( std::vector<line>& lines, const bmp& orig )
{
        ssize_t current_score = evaluate(lines,orig);

        std::vector<line> newlines(lines);

        uint32_t deactivated = 0;
        std::cout << "current_score = " << current_score << "\n";
        for (size_t i = 0; i < newlines.size(); ++i)
        {
                newlines[i].active = false;
                ssize_t score = evaluate(newlines,orig);
                if( score > current_score )
                {
                        newlines[i].active = true;
                }
                else
                {
                        current_score = score;
                        ++deactivated;
                }
                if( i % 1000 == 0 )
                {
                        std::ostringstream fn;
                        fn << "erase_" << std::setw(6) << std::setfill('0') << i << ".bmp";
                        bmp tmp(orig);
                        paint(newlines,tmp);
                        tmp.write(fn.str());
                        paint_layers(newlines,tmp);
                        tmp.max_contrast_all();
                        tmp.write("layers_" + fn.str());
                        std::cout << "\r i = " << i << std::flush;
                }
        }
        std::cout << "\n";
        std::cout << "current_score = " << current_score << "\n";
        std::cout << "deactivated = " << deactivated << "\n";


        bmp tmp(orig);

        paint(newlines,tmp);
        tmp.write("newlines.bmp");
        lines.clear();
        for (size_t i = 0; i < newlines.size(); ++i)
        {
                if( newlines[i].is_active() )
                {
                        lines.push_back(newlines[i]);
                }
        }
}

+1, वास्तव में बहुत अच्छा। क्या आपके पास अन्य परीक्षण छवियों के लिए परिणाम हैं?
नथानिएल

1
@ नथानियल: मैंने कुछ जोड़ा है। "सरल" छवियां अनपेक्षित हैं क्योंकि मनोरंजन लगभग पिक्सेल परिपूर्ण है।
प्लाज्माएचएच

17

जावा - यादृच्छिक लाइनें

एक बहुत ही मूल समाधान जो यादृच्छिक रेखा खींचता है और उनके लिए स्रोत चित्र औसत रंग की गणना करता है। पृष्ठभूमि रंग स्रोत औसत रंग पर सेट है।

एल = 5000, एम = 10, एम = 50

यहाँ छवि विवरण दर्ज करें

एल = 10000, एम = 10, एम = 50

यहाँ छवि विवरण दर्ज करें

संपादित करें

मैंने एक आनुवंशिक एल्गोरिथ्म जोड़ा है जो लाइनों की आबादी को संभालता है। प्रत्येक पीढ़ी में, हम केवल 50% सर्वश्रेष्ठ लाइनें रखते हैं, दूसरों को छोड़ देते हैं और बेतरतीब ढंग से नए उत्पन्न करते हैं। लाइनें रखने के मानदंड हैं:

  • स्रोत चित्र के रंगों से उनकी दूरी छोटी है
  • अन्य लाइनों के साथ चौराहों की संख्या (छोटे बेहतर)
  • उनकी लंबाई (जितनी लंबी होगी)
  • निकटतम पड़ोसी के साथ उनका कोण (छोटा बेहतर)

मेरी महान निराशा के लिए, एल्गोरिथ्म वास्तव में तस्वीर की गुणवत्ता में सुधार नहीं करता है :-( बस लाइनें अधिक समानांतर हो रही हैं।

पहली पीढ़ी (5000 लाइनें)

यहाँ छवि विवरण दर्ज करें

दसवीं पीढ़ी (5000 लाइनें)

यहाँ छवि विवरण दर्ज करें

मापदंडों के साथ खेलना

यहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करें

package line;

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;

import snake.Image;

public class Lines {

    private final static int NB_LINES = 5000;
    private final static int MIN_LENGTH = 10;
    private final static int MAX_LENGTH = 50;

    public static void main(String[] args) throws IOException {     
        BufferedImage src = ImageIO.read(Image.class.getClassLoader().getResourceAsStream("joconde.png"));
        BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);


        int [] bgColor = {0, 0, 0};
        int avgRed = 0, avgGreen = 0, avgBlue = 0, count = 0;
        for (int y = 0; y < src.getHeight(); y++) {
            for (int x = 0; x < src.getWidth(); x++) {
                int colsrc = src.getRGB(x, y);
                avgRed += colsrc & 255;
                avgGreen += (colsrc >> 8) & 255;
                avgBlue += (colsrc >> 16) & 255;
                count++;
            }
        }

        bgColor[0] = avgBlue/count; bgColor[1] = avgGreen/count; bgColor[2] = avgRed/count;
        for (int y = 0; y < src.getHeight(); y++) {
            for (int x = 0; x < src.getWidth(); x++) {
                dest.getRaster().setPixel(x, y, bgColor);
            }
        }
        List<List<Point>> lines = new ArrayList<List<Point>>();
        Random rand = new Random();
        for (int i = 0; i < NB_LINES; i++) {
            int length = rand.nextInt(MAX_LENGTH - MIN_LENGTH) + MIN_LENGTH;
            double ang = rand.nextDouble() * Math.PI;
            int lx = (int)(Math.cos(ang) * length); // can be negative or positive
            int ly = (int)(Math.sin(ang) * length); // positive only
            int sx = rand.nextInt(dest.getWidth() -1 - Math.abs(lx));
            int sy = rand.nextInt(dest.getHeight() - 1- Math.abs(ly));
            List<Point> line;
            if (lx > 0) {
                line = line(sx, sy, sx+lx, sy+ly);
            } else {
                line = line(sx+Math.abs(lx), sy, sx, sy+ly);
            }
            lines.add(line);    
        }

        // render the picture
        int [] color = {0, 0, 0};
        for (List<Point> line : lines) {

            avgRed = 0; avgGreen = 0; avgBlue = 0;
            count = 0;
            for (Point p : line) {
                int colsrc = src.getRGB(p.x, p.y);
                avgRed += colsrc & 255;
                avgGreen += (colsrc >> 8) & 255;
                avgBlue += (colsrc >> 16) & 255;
                count++;
            }
            avgRed /= count; avgGreen /= count; avgBlue /= count;
            color[0] = avgBlue; color[1] = avgGreen; color[2] = avgRed;
            for (Point p : line) {
                dest.getRaster().setPixel(p.x, p.y, color);
            }

        }
        ImageIO.write(dest, "png", new File("a0.png"));

    }

    private static List<Point> line(int x0, int y0, int x1, int y1) {
        List<Point> points = new ArrayList<Point>();
        int deltax = x1 - x0;
        int deltay = y1 - y0;
        int tmp;
        double error = 0;       
        double deltaerr = 0;
        if (Math.abs(deltax) >= Math.abs(deltay)) {
            if (x0 > x1) { // swap the 2 points
                tmp = x0; x0 = x1; x1 = tmp;
                tmp = y0; y0 = y1; y1 = tmp;
                deltax = - deltax; deltay = -deltay;
            }
            deltaerr = Math.abs (((double)deltay) / deltax); 
            int y = y0;
            for (int x = x0; x <= x1; x++) {
                points.add(new Point(x, y));
                error += deltaerr;
                if (error >= 0.5) {
                    if (y0 < y1) y++; else y--;
                    error -= 1.0;
                }
            }
        } else {
            if (y0 > y1) { // swap the 2 points
                tmp = x0; x0 = x1; x1 = tmp;
                tmp = y0; y0 = y1; y1 = tmp;
                deltax = - deltax; deltay = -deltay;
            }
            deltaerr = Math.abs (((double)deltax) / deltay);   // Assume deltay != 0 (line is not horizontal),
            int x = x0;
            for (int y = y0; y <= y1; y++) {
                points.add(new Point(x, y));
                error += deltaerr;
                if (error >= 0.5) {
                    if (x0 < x1) x++; else x--;
                    error -= 1.0;
                }
            }
        }
        return points;
    }
}

अंत में किसी ने उत्तर दिया: D मैं और उदाहरण देखना पसंद करूंगा।
केल्विन के शौक

@ कलालिन श्योर। अभी मैं लाइनों की आबादी को ध्यान में रखते हुए एल्गोरिथ्म को बेहतर बनाने पर काम कर रहा हूं, और उदाहरण के लिए 20% बदतर को खत्म कर रहा हूं, और नए लोगों (कुछ प्रकार के आनुवंशिक एल्गोरिथ्म) को फिर से पैदा कर रहा हूं
अरनौद

मेरे मन में ऐसा कुछ था, लेकिन इसे लिखने का समय नहीं था। जेनेटिक एल्ग के लिए आगे देख रहे हैं। परिणाम :)
एडिट्स

शायद आप छोटे कोण मानदंड को हटाना चाहते हैं? आपने इसे क्यों लगाया? मूल छवि अच्छी लगती है, हालांकि लाइनों में छोटे चौराहे कोण नहीं हैं।
justhalf

@ अन्यायपूर्ण कार्य। मैंने चित्रकार ब्रश को अनुकरण करने के प्रयास में कोण मानदंड जोड़ा है।
अरनौद

9

सी - सीधी रेखाएँ

सी में एक मूल दृष्टिकोण जो पीपीएम फाइलों पर संचालित होता है। एल्गोरिथ्म सभी पिक्सेल को भरने के लिए इष्टतम लाइन की लंबाई के साथ ऊर्ध्वाधर लाइनें रखने की कोशिश करता है। पृष्ठभूमि का रंग और रेखा के रंग की गणना मूल छवि के औसत मूल्य (प्रत्येक रंग चैनल के मध्यिका) के रूप में की जाती है:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define SIGN(x) ((x > 0) ? 1 : (x < 0) ? -1 : 0)
#define MIN(x, y) ((x > y) ? y : x)
#define MAX(x, y) ((x > y) ? x : y)

typedef struct {
    size_t width;
    size_t height;

    unsigned char *r;
    unsigned char *g;
    unsigned char *b;
} image;

typedef struct {
    unsigned char r;
    unsigned char g;
    unsigned char b;
} color;

void init_image(image *data, size_t width, size_t height) {
    data->width = width;
    data->height = height;
    data->r = malloc(sizeof(data->r) * data->width * data->height);
    data->g = malloc(sizeof(data->g) * data->width * data->height);
    data->b = malloc(sizeof(data->b) * data->width * data->height);
}

#define BUFFER_LEN 1024
int load_image(const char *filename, image* data) {
    FILE *f = fopen(filename, "r");
    char buffer[BUFFER_LEN];          /* read buffer */
    size_t max_value;
    size_t i;
    fgets(buffer, BUFFER_LEN, f);
    if (strncmp(buffer, "P3", 2) != 0) {
        printf("File begins with %s instead of P3\n", buffer);
        return 0;
    }

    fscanf(f, "%u", &data->width);
    fscanf(f, "%u", &data->height);
    fscanf(f, "%u", &max_value);
    assert(max_value==255);

    init_image(data, data->width, data->height);

    for (i = 0; i < data->width * data->height; i++) {
        fscanf(f, "%hhu", &(data->r[i]));
        fscanf(f, "%hhu", &(data->g[i]));
        fscanf(f, "%hhu", &(data->b[i]));
    }
    fclose(f);

    printf("Read %zux%zu pixels from %s.\n", data->width, data->height, filename);
}

int write_image(const char *filename, image *data) {
    FILE *f = fopen(filename, "w");
    size_t i;
    fprintf(f, "P3\n%zu %zu\n255\n", data->width, data->height);
    for (i = 0; i < data->width * data->height; i++) {
        fprintf(f, "%hhu %hhu %hhu ", data->r[i], data->g[i], data->b[i]);
    }
    fclose(f);
}

unsigned char average(unsigned char *data, size_t data_len) {
    size_t i;
    size_t j;
    size_t hist[256];

    for (i = 0; i < 256; i++) hist[i] = 0;
    for (i = 0; i < data_len; i++) hist[data[i]]++;
    j = 0;
    for (i = 0; i < 256; i++) {
        j += hist[i];
        if (j >= data_len / 2) return i;
    }
    return 255;
}

void set_pixel(image *data, size_t x, size_t y, unsigned char r, unsigned char g, unsigned char b) {
    data->r[x + data->width * y] = r;
    data->g[x + data->width * y] = g;
    data->b[x + data->width * y] = b;
}

color get_pixel(image *data, size_t x, size_t y) {
    color ret;
    ret.r = data->r[x + data->width * y];
    ret.g = data->g[x + data->width * y];
    ret.b = data->b[x + data->width * y];
    return ret;
}

void fill(image *data, unsigned char r, unsigned char g, unsigned char b) {
    size_t i;
    for (i = 0; i < data->width * data->height; i++) {
        data->r[i] = r;
        data->g[i] = g;
        data->b[i] = b;
    }
}

void line(image *data, size_t x1, size_t y1, size_t x2, size_t y2, unsigned char r, unsigned char g, unsigned char b) {
    size_t x, y, t, pdx, pdy, ddx, ddy, es, el;
    int dx, dy, incx, incy, err;

    dx=x2-x1;
    dy=y2-y1;
    incx=SIGN(dx);
    incy=SIGN(dy);
    if(dx<0) dx=-dx;
    if(dy<0) dy=-dy;
    if (dx>dy) {
        pdx=incx;
        pdy=0;
        ddx=incx;
        ddy=incy;
        es=dy;
        el=dx;
    } else {
        pdx=0;
        pdy=incy;
        ddx=incx;
        ddy=incy;
        es=dx;
        el=dy;
    }
    x=x1;
    y=y1;
    err=el/2;
    set_pixel(data, x, y, r, g, b);

    for(t=0; t<el; t++) {
        err -= es;
        if(err<0) {
            err+=el;
            x+=ddx;
            y+=ddy;
        } else {
            x+=pdx;
            y+=pdy;
        }
        set_pixel(data, x, y, r, g, b);
    }
}

color average_line(image *data, size_t x1, size_t y1, size_t x2, size_t y2) {
    size_t x, y, t, pdx, pdy, ddx, ddy, es, el;
    int dx, dy, incx, incy, err;
    color ret;
    color px;
    size_t i;
    size_t j;
    size_t hist_r[256];
    size_t hist_g[256];
    size_t hist_b[256];
    size_t data_len = 0;

    for (i = 0; i < 256; i++) {
        hist_r[i] = 0;
        hist_g[i] = 0;
        hist_b[i] = 0;
    }

    dx=x2-x1;
    dy=y2-y1;
    incx=SIGN(dx);
    incy=SIGN(dy);
    if(dx<0) dx=-dx;
    if(dy<0) dy=-dy;
    if (dx>dy) {
        pdx=incx;
        pdy=0;
        ddx=incx;
        ddy=incy;
        es=dy;
        el=dx;
    } else {
        pdx=0;
        pdy=incy;
        ddx=incx;
        ddy=incy;
        es=dx;
        el=dy;
    }
    x=x1;
    y=y1;
    err=el/2;
    px = get_pixel(data, x, y);
    hist_r[px.r]++;
    hist_g[px.g]++;
    hist_b[px.b]++;
    data_len++;

    for(t=0; t<el; t++) {
        err -= es;
        if(err<0) {
            err+=el;
            x+=ddx;
            y+=ddy;
        } else {
            x+=pdx;
            y+=pdy;
        }
        px = get_pixel(data, x, y);
        hist_r[px.r]++;
        hist_g[px.g]++;
        hist_b[px.b]++;
        data_len++;
    }

    j = 0;
    for (i = 0; i < 256; i++) {
        j += hist_r[i];
        if (j >= data_len / 2) {
            ret.r = i;
            break;
        }
    }
    j = 0;
    for (i = 0; i < 256; i++) {
        j += hist_g[i];
        if (j >= data_len / 2) {
            ret.g = i;
            break;
        }
    }
    j = 0;
    for (i = 0; i < 256; i++) {
        j += hist_b[i];
        if (j >= data_len / 2) {
            ret.b = i;
            break;
        }
    }
    return ret;
}


void lines(image *source, image *dest, size_t L, float m, float M) {
    size_t i, j;
    float dx;
    float mx, my;
    float mm = MAX(MIN(source->width * source->height / L, M), m);
    unsigned char av_r = average(source->r, source->width * source->height);
    unsigned char av_g = average(source->g, source->width * source->height);
    unsigned char av_b = average(source->b, source->width * source->height);
    fill(dest, av_r, av_g, av_b);
    dx = (float)source->width / L;
    mx = 0;
    my = mm / 2;
    for (i = 0; i < L; i++) {
        color avg;
        mx += dx;
        my += (source->height - mm) / 8;
        if (my + mm / 2 > source->height) {
            my = mm / 2 + ((size_t)(my + mm / 2) % (size_t)(source->height - mm));
        }
        avg = average_line(source, mx, my - mm / 2, mx, my + mm / 2);
        line(dest, mx, my - mm / 2, mx, my + mm / 2, avg.r, avg.g, avg.b);
    }
}

int main(int argc, char *argv[]) {
    image source;
    image dest;
    size_t L;
    float m;
    float M;

    load_image(argv[1], &source);
    L = atol(argv[2]);
    m = atof(argv[3]);
    M = atof(argv[4]);

    init_image(&dest, source.width, source.height);
    lines(&source, &dest, L, m, M);


    write_image(argv[5], &dest);
}

एल = 5000, एम = 10, एम = 50

एल = 5000, एम = 10, एम = 50

एल = 5000, एम = 10, एम = 50

एल = 5000, एम = 10, एम = 50

एल = 100000, एम = 10, एम = 50

यहाँ छवि विवरण दर्ज करें


6

पायथन 3 "कुछ हद तक यादृच्छिक रेखाओं और फिर कुछ" से दूर, प्लस सॉबल एज डिटेक्शन।

कोड सैद्धांतिक रूप से हमेशा के लिए चल सकता है (इसलिए मैं इसे रात भर मस्ती के लिए चला सकता हूं), लेकिन यह इसकी प्रगति को रिकॉर्ड करता है, इसलिए सभी चित्र 1-10 मिनट के निशान से लिए गए हैं।

यह पहले छवि को पढ़ता है, और फिर सभी किनारों के कोण को खोजने के लिए सोबेल एज डिटेक्शन का उपयोग करता है, यह सुनिश्चित करने के लिए कि लाइनें दूसरे रंग पर अतिचार न करें। एक बार (लंबाई, लंबाई) के भीतर यादृच्छिक लंबाई की एक पंक्ति निर्धारित की जाती है, तो यह देखने के लिए परीक्षण करती है कि क्या यह समग्र छवि में योगदान देता है। जबकि छोटी लाइनें बेहतर हैं, मैंने 10-50 से लाइन की लंबाई निर्धारित की है।

from random import randint, uniform
import json
from PIL import Image, ImageDraw, ImageFilter
import math
k=(-1,0,1,-2,0,2,-1,0,1)
k1=(-1,-2,-1,0,0,0,1,2,1)
population=[]
lengthmin=10
lengthmax=50
number_lines=10**8
im=Image.open('0.png')
[x1,y1]=im.size
dx=0
class drawer():
    def __init__(self,genome,score,filename):
        self.genome=genome
        self.score=score
        self.filename=filename
    def initpoint(self,g1):
        g2=self.genome
        im=Image.open('0.png')
        im1=im.filter(ImageFilter.Kernel((3,3),k,1,128))
        im2=im.filter(ImageFilter.Kernel((3,3),k1,1,128))
        im1=im1.filter(ImageFilter.GaussianBlur(radius=4))
        im2=im2.filter(ImageFilter.GaussianBlur(radius=4))
        for x in range(0,number_lines):
            if(x%10**4==0):
                print(x*100/number_lines)
                self.save()
                g1.save('1.png')
            (x,y)=(randint(0,x1-1),randint(0,y1-1))
            w=im1.getpixel((x,y))[0]-128
            z=im2.getpixel((x,y))[0]-128
            w=int(w)
            z=int(z)
            W=(w**2+z**2)**0.5
            if(W!=0):
                w=(w/W)*randint(lengthmin,lengthmax)
                z=(z/W)*randint(lengthmin,lengthmax)
                (w,z)=(z,w)
                (a,b)=(x+w,y+z)
                a=int(a)
                b=int(b)
                x=int(x)
                y=int(y)
                if(a>=x1):
                    a=x1-1
                if(b>=y1):
                    b=y1-1
                if(a<0):
                    a=0
                if(b<0):
                    b=0
                if(x>=x1):
                    x=x1-1
                if(y>=y1):
                    y=y1-1
                if(x<0):
                    x=0
                if(y<0):
                    y=0
                C=[0,0,0]
                D=0
                E=0
                F=0
                G=0
                W=((x-a)**2+(y-b)**2)**0.5
                if(W!=0):
                    for Z in range(0,int(W)):
                        w=(Z/W)
                        (c,d)=((w*x+(1-w)*a),(w*y+(1-w)*b))
                        c=int(c)
                        d=int(d)
                        C[0]+=im.getpixel((c,d))[0]
                        C[1]+=im.getpixel((c,d))[1]
                        C[2]+=im.getpixel((c,d))[2]
                    C[0]/=W
                    C[1]/=W
                    C[2]/=W
                    C[0]=int(C[0])
                    C[1]=int(C[1])
                    C[2]=int(C[2])
                    for Z in range(0,int(W)):
                        w=(Z/W)
                        (c,d)=((w*x+(1-w)*a),(w*y+(1-w)*b))
                        c=int(c)
                        d=int(d)
                        E=0
                        D=0
                        D+=(g1.getpixel((c,d))[0]-im.getpixel((c,d))[0])**2
                        D+=(g1.getpixel((c,d))[1]-im.getpixel((c,d))[1])**2
                        D+=(g1.getpixel((c,d))[2]-im.getpixel((c,d))[2])**2
                        F+=D**0.5
                        E+=(im.getpixel((c,d))[0]-C[0])**2
                        E+=(im.getpixel((c,d))[1]-C[1])**2
                        E+=(im.getpixel((c,d))[2]-C[2])**2
                        G+=E**0.5
                    #print((G/W,F/W))
                    if(G<F):
                        for Z in range(0,int(W)):
                            w=(Z/W)
                            (c,d)=((w*x+(1-w)*a),(w*y+(1-w)*b))
                            c=int(c)
                            d=int(d)
                            g1.putpixel((c,d),(int(C[0]),int(C[1]),int(C[2])))
                        g2.append((x,y,a,b,int(C[0]%256),int(C[1]%256),int(C[2]%256)))
        return(g1)
    def import_file(self):
        with open(self.filename, 'r') as infile:
            self.genome=json.loads(infile.read())
        print(len(self.genome))
    def save(self):
        with open(self.filename, 'w') as outfile:
            data = json.dumps(self.genome)
            outfile.write(data)
population.append(drawer([],0,'0.txt'))
G=0
g1=Image.new('RGB',(x1,y1),'black')
g1=population[0].initpoint(g1)
g1.save('1.png')

अमेरिकन गोथिक

Escher

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.