Aç Resim Yılan - Delik # 3


25

Delik # 1

Joe yılanı aç.

Her seferinde bir piksel resim yiyor.

Parlak piksellerden gerçekten hoşlanıyor.

Meydan okuma

Joe'yu bulabildiği en parlak pikselleri yemesi için programlayın, yalnızca yukarı, aşağı, sola veya sağa hareket edebilmesi.

Özellikler

  • Joe görüntünün sol üst pikselinden başlamalıdır.
  • Joe her hareketten sadece 1 tane yatay veya dikey olarak hareket edebilir
  • Joe’nun resimdeki piksel miktarının 1 / 3’ünü taşımak için yalnızca zamanı (1/3 piksel kadar hareket). Piksel sayısı 3'ün katı değilse, en yakın tam sayıya yuvarlayın.
  • Joe 0 parlaklık olarak sayılmasına rağmen yolunu geçebilir.
  • Parlaklık r, g ve b'nin toplamına dayanır, bu nedenle rgb (0,0,0), 0 parlaklığına sahipken rgb (255,255,255) maksimum parlaklığa sahiptir.

Giriş

İstediğiniz gibi görüntüyü girebilirsiniz.

Çıktı

  • Resminizin sonunu gösteren bir resim (siyah, yenen piksellerle).
  • Yenilen parlaklık miktarı (lütfen cevabınızdaki aralığı belirtin)

puanlama

Programınız derecelendirilecek:

  • Ortalama piksel parlaklığı Joe eats / Resimdeki piksellerin ortalama parlaklığı *

* bunu programında kodlayabilirsin

Toplam puanınız, aşağıdaki resimler için puanların ortalaması olacaktır:

Test görüntüleri:

görüntü tanımını buraya girin

görüntü tanımını buraya girin

http://upload.wikimedia.org/wikipedia/en/thumb/f/f4/The_Scream.jpg/800px-The_Scream.jpg

görüntü tanımını buraya girin

görüntü tanımını buraya girin

görüntü tanımını buraya girin


3
Eğlence Markdown gerçeği - Onların orijinallerine bağlantılara görüntüleri açabilirsiniz: [![image description](SE URL for downsized image)](URL for original image).
Calvin'in Hobileri

1
İnsanlardan cevaplarında "yenen" örnek bir örnek eklemelerini istemek bir fikir olabilir.
Nathaniel

Yanıtlar:


16

C ++, Puan: 1,42042 1,46766

Bu, esasen mevcut iki çözümün biraz daha karmaşık bir versiyonudur: Dört olası hareket arasından parlaklığı en üst düzeye çıkaranı seçer. Bununla birlikte, yalnızca hedef pikselin parlaklığına bakmak yerine, hedef pikselin yanındaki hedefin yakınındaki piksellerin daha fazla ağırlığa sahip olduğu piksel yoğunluğunun ağırlıklı toplamına bakar.

EDIT: Mahalle hesaplamasında doğrusal olmayan parlaklığı kullanmak, puanı biraz artırır.

İle derleyin g++ joe.cpp -ojoe -std=c++11 -O3 -lcairo. Kahire gerektirir.

İle koş joe <image-file> [<radius>]. <image-file>Giriş PNG görüntüsüdür. <radius>(isteğe bağlı argüman) toplanan mahallenin yarıçapıdır, piksel cinsinden (daha küçük daha hızlı, daha büyük (kabaca) daha iyidir.) Skoru ve adında bir görüntü çıktılar out.<image-file>.

#include <cairo/cairo.h>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>

using namespace std;

int main(int argc, const char* argv[]) {
    auto* img = cairo_image_surface_create_from_png(argv[1]);
    int width = cairo_image_surface_get_width(img),
        height = cairo_image_surface_get_height(img),
        stride = cairo_image_surface_get_stride(img);
    unsigned char* data = cairo_image_surface_get_data(img);

    double* brightness = new double[width * height];
    double total_brightness = 0;
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            const unsigned char* p = data + stride * y + 4 * x;
            total_brightness += brightness[y * width + x] = p[0] + p[1] + p[2];
        }
    }

    const int r = argc > 2 ? stoi(argv[2]) : 64, R = 2 * r + 1;
    double* weight = new double[R * R];
    for (int y = -r; y <= r; ++y) {
        for (int x = -r; x <= r; ++x)
            weight[R * (y + r) + (x + r)] = 1.0 / (x*x + y*y + 1);
    }

    auto neighborhood = [&] (int x, int y) {
        double b = 0;
        int x1 = max(x - r, 0), x2 = min(x + r, width - 1);
        int y1 = max(y - r, 0), y2 = min(y + r, height - 1);
        for (int v = y1; v <= y2; ++v) {
            const double *B = brightness + width * v + x1;
            const double *W = weight + R * (v - (y - r)) + (x1 - (x - r));
            for (int u = x1; u <= x2; ++u, ++B, ++W)
                b += (*W) * (*B) * (*B);
        }
        return b;
    };

    int n = (2 * width * height + 3) / 6;
    int x = 0, y = 0;
    double path_brightness = 0;
    int O[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    for (int i = 0; i < n; ++i) {
        if (i % 1000 == 0) cerr << (200 * i + n) / (2 * n) << "%\r";

        path_brightness += brightness[width * y + x]; brightness[width * y + x] = 0;
        unsigned char* p = data + stride * y + 4 * x;
        p[0] = p[1] = 16 * i % 255; p[2] = 0;

        auto O_end = partition(begin(O), end(O), [&] (const int* o) {
            return x + o[0] >= 0 && x + o[0] < width &&
                   y + o[1] >= 0 && y + o[1] < height;
        });
        const int* o_max; double o_max_neighborhood = -1;
        for (auto o = O; o != O_end; ++o) {
            double o_neighborhood = neighborhood(x + (*o)[0], y + (*o)[1]);
            if (o_neighborhood > o_max_neighborhood)
                o_max = *o, o_max_neighborhood = o_neighborhood;
        }
        x += o_max[0]; y += o_max[1];
    }

    cout << (path_brightness * width * height) / (n * total_brightness) << endl;

    cairo_surface_write_to_png(img, (string("out.") + argv[1]).c_str());

    delete []brightness;
    delete []weight;
    cairo_surface_destroy(img);
}

Sonuçlar

Bridge    1.39945
Balls     1.77714
Scream    1.38349
Fractal   1.31727
Vortex    1.66493
Tornado   1.26366
-----------------
Average   1.46766

Köprü taşaklar Çığlık Fraktal girdap Kasırga

Daha fazla göz şekeri

Girdap animasyonu Kasırga animasyonu


Programınızı kendi örnek resimlerimden bazılarında denedim ve birinin yalnızca başlangıç ​​noktası çevresinde çok siyah kaldığını ve burada NaN'ı döndüren mahalle lambasından dolayı program çöküyor.
PlazmaHH

@PlasmaHH Suçlu görüntüyü paylaşıyor musun?
Ell

Tatil görüntülerini besliyordum ... 400x400 saf siyah da "numara" yapıyor.
PlasmaHH

@PlasmaHH Tamamen siyah bir görüntünün tanımlanmamış bir puanı var, sıfırın üzerinde sıfır, bir NaN olurdu. Ancak mahalle hesaplamasını etkilememeli veya programı çökertmemelidir (bu kayan nokta ortamına bağlı olabilir.)
Ell

O_max göstergesine bir göz atın, if (o_neighborhood > o_max_neighborhood) o_max = *o, o_max_neighborhood = o_neighborhood;sadece bu kod onu ayarlar. bununla birlikte nan nedeniyle, karşılaştırma her zaman yanlıştır, dolayısıyla o_max hiçbir zaman kurulmaz ve başlatılmamış olarak kullanılır.
PlazmaHH

7

Python 3, puan = 1.57

İlk önce yılanımız görüntüyü birbirinden eşit mesafede dikey çizgiler oluşturarak hareket ettirir.

bir

Bu yılanı, yan yana dikey bir çizgide iki nokta alarak ve uç noktaları kendileri olan bir halka oluşturarak uzatabiliriz.

|      |
|  =>  +----+
|      +----+
|      |

Noktaları çiftler halinde düzenliyoruz ve her çift için en yüksek ortalama parlaklığa sahip olan döngünün boyutunu ve ortalama parlaklık değerini saklıyoruz.

Her adımda, uzatmada maksimum ortalama parlaklığı elde etmek için döngüsünü uzayan en yüksek değerli çifti seçer ve çift için yeni optimal döngü boyutunu ve parlaklık değerini hesaplar.

(Value, size, point_pair) tripletlerini değere göre sıralanmış bir yığın yapısında saklıyoruz, böylece en büyük elementi (O (1)) kaldırabilir ve yeni değiştirilmiş olanı (O (log n)) verimli bir şekilde ekleyebiliriz.

Piksel sayım sınırına ulaştığımızda duruyoruz ve o yılan son yılan olacak.

Dikey çizgiler arasındaki mesafe sonuçlarda çok az etkiye sahiptir, bu yüzden sabit bir 40 piksel seçilmiştir.

Sonuçlar

swirl    1.33084397946
chaos    1.76585674741
fractal  1.49085737611
bridge   1.42603926741
balls    1.92235115238
scream   1.48603818637
----------------------
average  1.57033111819

bir bir bir bir bir bir

Not: Orijinal "Çığlık" resmi mevcut değildi, bu yüzden benzer çözünürlükte başka bir "Çığlık" resmi kullandım.

Yılan genişletme işlemini "girdap" görüntüsü üzerinde gösteren GIF:

bir

Kod, bir (veya daha fazla boşlukla ayrılmış) dosya adını stdin'den alır ve elde edilen yılan görüntülerini png dosyalarına yazar ve puanları stdout'a yazdırır.

from PIL import Image
import numpy as np
import heapq as hq

def upd_sp(p,st):
    vs,c=0,0
    mv,mp=-1,0
    for i in range(st,gap):
        if p[1]+i<h:
            vs+=v[p[0],p[1]+i]+v[p[0]+1,p[1]+i]
            c+=2
            if vs/c>mv:
                mv=vs/c
                mp=i
    return (-mv,mp)

mrl=[]
bf=input().split()

for bfe in bf:
    mr,mg=0,0    
    for gap in range(40,90,1500):

        im=Image.open(bfe)
        im_d=np.asarray(im).astype(int)

        v=im_d[:,:,0]+im_d[:,:,1]+im_d[:,:,2]

        w,h=v.shape

        fp=[]
        sp=[]
        x,y=0,0
        d=1

        go=True
        while go:
            if 0<=x+2*d<w:
                fp+=[(x,y)]
                fp+=[(x+d,y)]
                sp+=[(x-(d<0),y)]
                x+=2*d
                continue
            if y+gap<h:
                for k in range(gap):
                    fp+=[(x,y+k)]
                y+=gap
                d=-d
                continue
            go=False

        sh=[]
        px=im.load()

        pl=[]

        for p in fp:
            pl+=[v[p[0],p[1]]]
            px[p[1],p[0]]=(0,127,0)   

        for p in sp:
            mv,mp=upd_sp(p,1)
            if mv<=0:
                hq.heappush(sh,(mv,1,mp+1,p))

        empty=False
        pleft=h*w//3
        pleft-=len(fp)
        while pleft>gap*2 and not empty:

            if len(sh)>0:
                es,eb,ee,p=hq.heappop(sh)
            else:
                empty=True
            pleft-=(ee-eb)*2

            mv,mp=upd_sp(p,ee)
            if mv<=0:
                hq.heappush(sh,(mv,ee,mp+1,p))    

            for o in range(eb,ee):
                pl+=[v[p[0],p[1]+o]]
                pl+=[v[p[0]+1,p[1]+o]]
                px[p[1]+o,p[0]]=(0,127,0)   
                px[p[1]+o,p[0]+1]=(0,127,0)

        pl+=[0]*pleft

        sb=sum(pl)/len(pl)
        ob=np.sum(v)/(h*w)

        im.save(bfe[:-4]+'snaked.png')

        if sb/ob>mr:
            mr=sb/ob
            mg=gap

    print(bfe,mr)
    mrl+=[mr]

print(sum(mrl)/len(mrl))

5

Python 2 (puan: 0,0797116)

Topu yuvarlamak için sadece çok basit ve naif açgözlü bir algoritma.

#!/usr/bin/python

from PIL import Image

OFFSETS = [(-1, 0), (0, -1), (1, 0), (0, 1)]
def test_img(filename):
    img = Image.open(filename)

    joe, eaten = (0, 0), []
    img_w, img_h = img.size
    all_pixels = [
        sum(img.getpixel((x, y)))
        for x in xrange(img_w)
        for y in xrange(img_h)
    ]
    total_brightness = float(sum(all_pixels)) / len(all_pixels)

    for _ in xrange(0, (img_w*img_h)/3):
        max_offset, max_brightness = (0, 0), 0
        for o in OFFSETS:
            try:
                brightness = sum(img.getpixel((joe[0] + o[0], joe[1] + o[1])))
            except IndexError:
                brightness = -1
            if brightness >= max_brightness:
                max_offset = o
                max_brightness = brightness

        joe = (joe[0] + max_offset[0], joe[1] + max_offset[1])
        eaten.append(max_brightness)
        img.putpixel(joe, (0, 0, 0))

    eaten_brightness = float(sum(eaten)) / len(eaten)
    print('%d of %d (score %f)' % (eaten_brightness, total_brightness, eaten_brightness / total_brightness))
    img.show()

test_img('img0.jpg')
test_img('img1.png')
test_img('img2.jpg')
test_img('img3.jpg')
test_img('img4.jpg')

Çıktı:

llama@llama:~/Code/python/ppcg40069hungrysnake$ ./hungrysnake.py 
15 of 260 (score 0.060699)
9 of 132 (score 0.074200)
16 of 300 (score 0.055557)
4 of 369 (score 0.010836)
79 of 400 (score 0.197266)

1
Bence puanın kapalı. Bu, tüm resim için ortalama parlaklığın üzerinde yenen Joe'nun parlaklığının ortalaması ... Rastgele bir Joe yaklaşık 1 puan almalı.
Stretch Maniac

@StretchManiac Hmm, yanlış bir şey görmüyorum. sum of brightnesses of eaten pixels / amount of eaten pixelsDoğru formül doğru mu? Belki de sadece gerçekten korkunç bir algoritma;)
Doorknob

@Doorknob öyleThe average brightness of pixels Joe eats / The average brightness of the pixels in the picture*
hmatt1

Turuncu ve siyah renkte girdaplı (mavi değil) bir tane için ortalama parlaklığı 68.0846 'dır. Belki toplamı (getPixel (...)) istediğinizi geri getirmiyor? (Ben bir python acemi tür). BTW, 6 fotoğraf var, ancak yalnızca 5 çıkışınız var. Resimleri bir şekilde etiketleyebilir misin?
Stretch Maniac

@StretchManiac Parlaklığınızı nasıl hesaplıyorsunuz? Mine sadece R, G ve B değerlerini toplar. Maalesef, en son ikinci olan swirly birisini özledim (yorumunuzda bahsettiğiniz bence). Bunu sabah ekleyeceğim (şimdi uyumam gerekiyor).
Doorknob

5

Java (puan: 0,6949)

Geçerli pikseli çevreleyen dört pikselden en parlak pikseli alan basit bir algoritma. Beraberlik durumunda, yenen piksel rastgeledir ve farklı skorlara ve sonuçta her bir uygulamada sonuçlara yol açar. Bu nedenle, aşağıdaki puanlar her bir görüntünün 50'den fazla yürütme ortalamasıdır.

Çalıştırmak için, kaynaktaki üç argümanı (sınıf sabitleri olarak var) düzenleyin ya da komut satırından , görüntünün kaynak dosyasının yer java HungryImageSnake <source> <iterations> <printScores>aldığı biçimdeki komut satırından geçirin <source>, görüntünün yeme <iterations>sayısı ( ortalama puan ve tüm yinelemelere göre en iyi puanı kaydetme), ve <printScores>her yinelemenin puanını yazdırmak doğru veya yanlış olmak doğru.

import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

public class HungryImageSnake {

    private static final String SOURCE = "tornado.jpg";
    private static final int ITERATIONS = 50;
    private static final boolean PRINT_SCORES = true;

    public static void main(String[] args) {
        try {
            String source = args.length > 0 ? args[0] : SOURCE;
            int iterations = args.length > 1 ? Integer.parseInt(args[1]) : ITERATIONS;
            boolean printScores = args.length > 2 ? Boolean.parseBoolean(args[2]) : PRINT_SCORES;

            System.out.printf("Reading '%s'...%n", source);
            System.out.printf("Performing %d meals...%n", iterations);
            BufferedImage image = ImageIO.read(new File(source));
            double totalScore = 0;
            double bestScore = 0;
            BufferedImage bestImage = null;
            for (int i = 0; i < iterations; i++) {
                HungryImageSnake snake = new HungryImageSnake(image);
                while (snake.isHungry()) {
                    snake.eat();
                }
                double score = snake.getScore();
                if (printScores) {
                    System.out.printf("    %d: score of %.4f%n", i + 1, score);
                }
                totalScore += score;
                if (bestImage == null || score > bestScore) {
                    bestScore = score;
                    bestImage = snake.getImage();
                }
            }
            System.out.printf("Average score: %.4f%n", totalScore / iterations);
            String formattedScore = String.format("%.4f", bestScore);
            String output = source.replaceFirst("^(.*?)(\\.[^.]+)?$", "$1-b" + formattedScore + "$2");
            ImageIO.write(bestImage, source.substring(source.lastIndexOf('.') + 1), new File(output));
            System.out.printf("Wrote best image (score: %s) to '%s'.%n", bestScore, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private int x;
    private int y;
    private int movesLeft;
    private int maximumMoves;
    private double eatenAverageBrightness;
    private double originalAverageBrightness;
    private BufferedImage image;

    public HungryImageSnake(BufferedImage image) {
        this.image = copyImage(image);
        int size = image.getWidth() * image.getHeight();
        this.maximumMoves = size / 3;
        this.movesLeft = this.maximumMoves;
        int totalBrightness = 0;
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                totalBrightness += getBrightnessAt(x, y);
            }
        }
        this.originalAverageBrightness = totalBrightness / (double) size;
    }

    public BufferedImage getImage() {
        return image;
    }

    public double getEatenAverageBrightness() {
        return eatenAverageBrightness;
    }

    public double getOriginalAverageBrightness() {
        return originalAverageBrightness;
    }

    public double getScore() {
        return eatenAverageBrightness / originalAverageBrightness;
    }

    public boolean isHungry() {
        return movesLeft > 0;
    }

    public void eat() {
        if (!isHungry()) {
            return;
        }
        int[][] options = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        shuffleArray(options); // prevent snake from getting stuck in corners
        int[] bestOption = null;
        int bestBrightness = 0;
        for (int[] option : options) {
            int optionX = this.x + option[0];
            int optionY = this.y + option[1];
            if (exists(optionX, optionY)) {
                int brightness = getBrightnessAt(optionX, optionY);
                if (bestOption == null || brightness > bestBrightness) {
                    bestOption = new int[]{ optionX, optionY };
                    bestBrightness = brightness;
                }
            }
        }

        image.setRGB(bestOption[0], bestOption[1], 0);
        this.movesLeft--;
        this.x = bestOption[0];
        this.y = bestOption[1];
        this.eatenAverageBrightness += bestBrightness / (double) maximumMoves;
    }

    private boolean exists(int x, int y) {
        return x >= 0 && x < image.getWidth() && y >= 0 && y < image.getHeight();
    }

    private int getBrightnessAt(int x, int y) {
        int rgb = image.getRGB(x, y);
        int r = (rgb >> 16) & 0xFF;
        int g = (rgb >> 8) & 0xFF;
        int b = rgb & 0xFF;
        return r + g + b;
    }

    private static <T> void shuffleArray(T[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            T temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    private static BufferedImage copyImage(BufferedImage source){
        BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
        Graphics g = b.getGraphics();
        g.drawImage(source, 0, 0, null);
        g.dispose();
        return b;
    }
}

Görüntüye göre elliden fazla yinelemeyle elde edilen ortalama puanlar:

Bridge - 0.7739
Spheres - 0.5580
Scream - 0.8197
Fractal - 0.3850
Vortex - 0.9158
Tornado - 0.7172

En iyi puanlar, aynı elli yinelemeden fazla, görüntüye göre:

Bridge - 0.8996
Spheres - 0.8741
Scream - 0.9183
Fractal - 0.5720
Vortex - 1.1520
Tornado - 0.9281

En yüksek puan alan koşu görüntüleri:

Köprü - 0.8996 Küreler - 0.8741 Çığlık - 0.9183 Fraktal - 0.5720 Girdap - 1.1520 Kasırga - 0.9281

Görüntülerden de anlaşılacağı gibi, piksellerin üçte birinden daha azı aslında yeniliyor; yılan, zaman zaman zaten yediği pikseller arasında sıkışıp kalıyor ve hareketlerinin rastgeleliği onu getirene kadar ölü alanda sıkışıp kalıyor. Resmin yenilebilir bir kısmı.

Ayrıca yılan yeniden yeme piksellerinin bir sonucu olarak, ölü piksellerin sıfır parlaklığı tekrar ortalamaya katıldığı için puanlar aşağıya doğru eğilir. Eğer puanlama algoritması, tüm hareketlerden ziyade (yılanın daha önce yemiş olduğu ölü bir pikseli yemiş olanlar da dahil), sadece yeni pikselleri yiyen hareket sayısıyla bölmek üzere değiştirilmişse, çok daha yüksek puanlar görmeyi beklerdim. ).

Tabii ki, daha iyi bir yaklaşım, her piksel için bir çeşit parlaklık sezgisel oluşturmak ve width * height / 3en yüksek ortalama parlaklığa sahip piksel yolunu bulmak olabilir , ancak bu yaklaşımın, özellikle daha büyük görüntülerde, sayı olarak, çalışma zamanında en uygun olacağından şüpheliyim. olası permütasyonların çok büyük olurdu. Daha sonra bu yaklaşımın bir türünü çekebilir ve eğer öyleyse ayrı bir cevapta gönderebilirim.


Eğer cevabım ne kadar büyük olursa olsun rahatsız olursanız (içindeki resimlerden dolayı), bana haber verin, görüntüleri linkler lehine veya daha az acayip bir alternatif olarak kaldıracağım. Ya da, herhangi biri "yenilmiş" görüntülerin tam çözünürlüğünde orijinallerini isterse, yorumda da bana bildirin.
FThompson

4

Python 2, Puan: 1.205

Bir süre önce hızlı bir Python çözümü hazırladım, ancak göndermeyi unuttum. İşte burada. Görüntüdeki en zengin blokları bulur, sonra gelen tüm blokları yiyerek her bir bloğa gider.

Sonuçlar

bridge.jpg: 591.97866/515.41501 =                               1.14855 
BallsRender.png: 493.24711/387.80635 =                          1.27189 
Mandel_zoom_04_seehorse_tail.jpg: 792.23990/624.60579 =         1.26838 
Red_Vortex_Apophysis_Fractal_Flame.jpg: 368.26121/323.08463 =   1.13983 
The_Scream.jpg: 687.18565/555.05221 =                           1.23806
swirl.jpg: 762.89469/655.73767 =                                1.16341

AVERAGE                                                         1.205

Örnek Resim

İşlenmiş köprü resim

Python 2.7 Kodu

from pygame.locals import *
import pygame, sys, random

fn = sys.argv[1]

screen = pygame.display.set_mode((1900,1000))
pic = pygame.image.load(fn)
pic.convert()
W,H = pic.get_size()
enough = W*H/3
screen.blit(pic, (0,0))

ORTH = [(-1,0), (1,0), (0,-1), (0,1)]
def orth(p):
    return [(p[0]+dx, p[1]+dy) for dx,dy in ORTH]

def look(p):
    x,y = p
    if 0 <= x < W and 0 <= y < H:
        return sum(pic.get_at(p))
    else:
        return -1

# index picture
locs = [(x,y) for x in range(W) for y in range(H)]
grid = dict( (p,sum(pic.get_at(p))) for p in locs )
rank = sorted( grid.values() )
median = rank[ len(rank)/2 ]
dark = dict( (k,v) for k,v in grid if v < median )
good = dict( (k,v) for k,v in grid if v > median )
pictotal = sum(rank)
picavg = 1.0 * pictotal/(W*H)
print('Indexed')

# compute zone values:
block = 16
xblocks, yblocks = (W-1)/block, (H-1)/block
zones = dict( ((zx,zy),0) for zx in range(xblocks) for zy in range(yblocks) )
for x,y in locs:
    div = (x/block, y/block)
    if div in zones:
        colsum = sum( pic.get_at((x,y)) )
        zones[div] += colsum

# choose best zones:
zonelist = sorted( (v,k) for k,v in zones.items() )
cut = int(xblocks * yblocks * 0.33)
bestzones = dict( (k,v) for v,k in zonelist[-cut:] )

# make segment paths:
segdrop = [(0,1)] * (block-1)
segpass = [(1,0)] * block
segloop = [(0,-1)] * (block-1) + [(1,0)] + [(0,1)] * (block-1)
segeat = ( segloop+[(1,0)] ) * (block/2)
segshort = [(1,0)] * 2 + ( segloop+[(1,0)] ) * (block/2 - 1)

def segtopath(path, seg, xdir):
    for dx,dy in seg:
        x,y = path[-1]
        newloc = (x+dx*xdir, y+dy)
        path.append(newloc)

# design good path:
xdir = 1
path = [(0,0)]
segtopath(path, segdrop, xdir)
shortzone = True
while True:
    x,y = path[-1]
    zone = (x/block, y/block)
    if zone in bestzones:
        if shortzone:
            seg = segshort
        else:
            seg = segeat
    else:
        seg = segpass
    segtopath(path, seg, xdir)
    shortzone = False
    # check end of x block run:
    x,y = path[-1]
    zone = (x/block, y/block)
    if not ( 0 <= x < xblocks*block ):
        del path[-1]
        segtopath(path, segdrop, xdir)
        shortzone = True
        xdir = xdir * -1
    if len(path) > enough:
        break
print('Path Found')

# show path on picture:
loc = path.pop(0)
eaten = 1
joetotal = grid[loc]
i = 0
while eaten <= enough:
    loc = path[i]
    i += 1
    pic.set_at(loc, (0,0,0))
    joetotal += grid[loc]
    eaten += 1
    if i % 1000 == 0:
        screen.blit(pic, (0,0))
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == QUIT: sys.exit(0)

# save picture and wait:
screen.blit(pic, (0,0))
pygame.display.flip()
pygame.image.save(pic, 'output/'+fn)
joeavg = 1.0 * joetotal/eaten
print '%s: %7.5f/%7.5f = %7.5f' % (fn, joeavg, picavg, joeavg/picavg)
while True:
    for event in pygame.event.get():
        if event.type == QUIT: sys.exit(0)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.