কম্পিউটার জেনারেটেড ক্র্যাকড মাটি


43

এমন একটি প্রোগ্রাম লিখুন যা 0 থেকে 65535 (2 16 -1) পর্যন্ত পূর্ণসংখ্যায় নিয়ে যায় এবং একটি অনন্য 500 × 500 পিক্সেল চিত্র তৈরি করে যা ফাটলযুক্ত মাটির এই 6 বাস্তব জীবনের চিত্রগুলির সাথে যথাসম্ভব অনুরূপ:

ফাটল মাটির নমুনা 1 ফাটল মাটির নমুনা 2 ফাটল মাটির নমুনা 3 ফাটল মাটির নমুনা 4 ফাটল মাটির নমুনা 5 ফাটল মাটির নমুনা 6
এগুলি থাম্বনেইলস, পূর্ণ আকারের 500 × 500 চিত্র দেখতে তাদের ক্লিক করুন।

এখানে লক্ষ্যটি হ'ল আপনার কম্পিউটার থেকে তৈরি চিত্রগুলি যথাসম্ভব আলোকিতাত্ত্বিক তৈরি করা । সুতরাং আদর্শগতভাবে, যদি আপনার প্রোগ্রামের কোনও চিত্রের আউটপুট উপরের 6 টি চিত্রের সাথে মিশ্রিত হয়, তবে প্রথমবারের মতো ছবিটি দেখছেন এমন কেউ প্রকৃত চিত্রগুলি বাদ দিয়ে কম্পিউটারের তৈরি কম্পিউটারগুলি বলতে সক্ষম হবে না।

নিখুঁত ফটোরিয়ালিজম কৌতুকময়, তাই আপনি যা পারেন সর্বোত্তমভাবে করুন। এটি একটি তাই যেগুলির উত্তরগুলিতে আরও বাস্তবসম্মত ফলাফল রয়েছে সেগুলি আরও উত্সাহিত হবে এবং জয়ের সম্ভাবনা বেশি থাকবে।

বিধি

  • আপনি ইমেজ প্রসেসিং ফাংশন বা লাইব্রেরি ব্যবহার করতে পারেন।

  • আপনি sample টি নমুনা চিত্র থেকে সংগৃহীত তথ্যের উপর ভিত্তি করে আপনার অ্যালগরিদমকে ভিত্তি করতে পারেন, তবে আপনার 65536 (2 16 ) সম্ভাব্য আউটপুট চিত্রগুলি একে অপরের এবং নমুনা চিত্রগুলির থেকে দৃশ্যমান পৃথক হওয়া উচিত , বিশেষত ফাটলগুলির ব্যবস্থা সম্পর্কিত। আপনাকে অবশ্যই সত্যই আপনার চিত্রগুলি তৈরি করতে হবে, কেবল একটি প্রিফিক্সিং ফটো থেকে কোনও ঘোরাঘুরি এবং অনুবাদ অনুবাদ করবেন না।

  • আপনার অন্যথায় আপনার আউটপুটগুলিকে হার্ডকোড করা উচিত নয়। একটি জেনেরিক অ্যালগরিদম ব্যবহার করা উচিত এবং তাত্ত্বিকভাবে বৈধ আউটপুট উত্পাদন করা উচিত 65535 এর চেয়ে বড় সংখ্যার। (আমি কেবল এটি সর্বাধিক সংখ্যার পূর্ণসংখ্যার ধরণের সংস্থান করতে সীমাবদ্ধ করেছি))

  • ইনপুট পূর্ণসংখ্যাকে একটি বীজ হিসাবে ভাবা যেতে পারে যা এলোমেলোভাবে ফাটল মাটির আউটপুট চিত্রের ফলস্বরূপ। এটি যদিও নির্বিচারে হওয়া উচিত, তাই একই ইনপুটটির সর্বদা একই আউটপুট তৈরি হওয়া উচিত।

  • আউটপুট চিত্রগুলি অবশ্যই 500 × 500 পিক্সেল হতে হবে।

  • আউটপুট চিত্রগুলি কোনও সাধারণ চিত্র ফাইল ফর্ম্যাটে সংরক্ষণ করা যেতে পারে, বা কেবল প্রদর্শিত।

  • আপনার উত্তরে কয়েকটি উদাহরণ আউটপুট চিত্র এবং তাদের সম্পর্কিত ইনপুট নম্বর অন্তর্ভুক্ত করার বিষয়ে নিশ্চিত হন।

  • সর্বাধিক ভোট সহ উত্তর জিতেছে। ভোটারদের অবশ্যই উত্তরগুলি উঁচু করে ফেলতে হবে যা 6 টি নমুনার অনুরূপ চিত্র উত্পাদন করার চেষ্টা করে, এবং এমন উত্তরগুলি ডাউনওয়েটে দেয় যা বিধিগুলি ভঙ্গ করে বা বেমানান ফলাফল দেয়।

Sample টি নমুনা চিত্রগুলি টেক্সচারিলিবো ডটকম থেকে নেওয়া হয়েছিল । ফাটলযুক্ত মাটির দুটি বৃহত্তর চিত্র থেকে 1000 × 1000 পিক্সেল অঞ্চল নির্বাচনগুলি নেওয়া হয়েছিল এবং তারপরে আকার পরিবর্তন করে 500 × 500 করা হয়েছে। আপনি আপনার প্রোগ্রামে এই বৃহত্তর চিত্রগুলি থেকে বিশ্লেষণ ব্যবহার করতে পারেন তবে আউটপুটটিতে বিশেষত 6 টি নির্বাচিত নমুনা চিত্র অনুকরণ করা উচিত।


6
আমি এই চ্যালেঞ্জটিকে খুব ব্রড হিসাবে বন্ধ করার পক্ষে ভোট দিয়েছি কারণ এতে উদ্দেশ্যগত বৈধতার মানদণ্ড নেই
অ্যাডমবর্কবার্ক

4
@ হেলকাহোম্বা একটি পুরানো চ্যালেঞ্জটি ভালভাবে গ্রহণ করা হয়েছিল কিনা তা sensকমত্যের ভিত্তিতে সিদ্ধান্ত নেওয়া অনুযায়ী কোনও চ্যালেঞ্জ এখন সাইটের নিয়মগুলির সাথে খাপ খায় কিনা তা বিবেচনা করা উচিত নয় । পপকনগুলির বিগত মাসগুলিতে অজস্র আলোচনা হয়েছে, ফলাফলগুলির মধ্যে একটি হ'ল সমস্ত পপকনগুলির একটি উদ্দেশ্য বৈধতার মানদণ্ডের প্রয়োজন। এই চ্যালেঞ্জের যে নেই। সুতরাং, এটি খুব বিস্তৃত।
অ্যাডমবর্কবার্ক

15
পপ কনসের সম্পর্কে বর্তমান নিয়মগুলি এতটাই বোবা যে আমি তাদের এড়ানো এবং এটি কীভাবে কার্যকর হয় তা দেখার জন্য আমি এই সুযোগটি নেব। এই বিষয়টি মেটাতে তুলে ধরা হয়েছে যেখানে এটি মৃত্যুর সাথে আলোচনা করা হয়েছে তবে বাস্তবে কিছুই পরিবর্তিত হয় না, তাই আমার মনে হয় যে কিছু ঘটতে যাওয়ার সর্বোত্তম সুযোগ হ'ল কিছু পপ কনস রাখা এবং তারা কীভাবে তা দেখায়।
xnor

6
এখানে উদ্দেশ্যগত বৈধতার মানদণ্ডগুলি "অনন্য" (অন্যান্য 65535 এর থেকে পৃথক) এবং "500x500 পিক্সেল"। উদাহরণ চিত্রগুলির সাদৃশ্যটি বস্তুনিষ্ঠভাবে সংজ্ঞায়িত করা যায় না, বা এটি কোনও জনপ্রিয়তা প্রতিযোগিতা নয়, কোড চ্যালেঞ্জ হতে পারে।
ট্রাইকোপলাক্স

14
আমি কোনও বাধা ছাড়াই "কিছু সুন্দর করে তুলুন" এর মতো খারাপ পপগুলি দেখতে পাচ্ছি এবং "এই স্পেসিফিকেশনটির সাথে ম্যাচ করুন" এর মতো ভাল পপ কনগুলি সবচেয়ে ভাল মেলে যার সাথে ভোট দেয় মানুষ voting আমি অবশ্যই এই চ্যালেঞ্জটিকে ভাল ধরণের হিসাবে দেখছি।
ট্রাইকোপল্যাক্স

উত্তর:


30

ম্যাথামেটিকাল

একটি ভোরোনাই চিত্রটি উইকিপিডিয়া থেকে এই অঙ্কনটির মতো দেখায়, 19 টি কোষ দেখায়, যার প্রত্যেকটিতে একটি করে বীজ পয়েন্ট থাকে। একটি ঘর বিন্দুগুলির সাবগ্রেইন নিয়ে গঠিত যা সম্পর্কিত উত্পন্ন বিন্দু অন্যান্য বীজের বিন্দুর তুলনায় খুব কাছাকাছি থাকে।

voronoi

নীচের কোডটি 80 এলোমেলো পয়েন্টগুলি ((-1, -1) এবং (1,1%) দ্বারা আবদ্ধ বর্গক্ষেত্র অঞ্চলে একটি চিত্র তৈরি করে।

পলিহেড্রা (3 ডি তে) তৈরি করতে এটি ডায়াগ্রামে বহুভুজ আদিম (2 ডি তে) ব্যবহার করে। কল্পনা করুন যে প্রতিটি বহুভুজের ঠিক তার নীচে একটি অনুবাদ রয়েছে (-08 z in z)। দুটি বহুভুজকে একটি পলিহেড্রনের উপরের এবং নীচের মুখ হিসাবে ভাবেন। পলিহেড্রন সম্পূর্ণ করার জন্য "সাইড ফেস" যুক্ত করা হয়।

প্রতিটি পলিহেড্রন তখন চিত্রের কেন্দ্র থেকে, এক্সওয়াই বিমানটিতে বাইরের দিকে অনুবাদ করা হয়; এটি মাঝখান থেকে সরে যায়। পলিহেড্রনের মূল উত্পাদক এলোমেলো পয়েন্ট এবং পর্দার কেন্দ্রের মধ্যবর্তী দূরত্বের সাথে অনুবাদটির মাত্রা সরাসরি পরিবর্তিত হয়। এক্সআই প্লেনে পলিহেডারের এই "ছড়িয়ে পড়ার" ফলে ক্রাভাইসের ফলাফল হয়।

crackedMud[1]

এক

crackedMud[65535]

গত

কোড

ClearAll[polyhedronFromPolygon, voronoiPolygons, generatingPointFromPolygon, crackedMud]


(* polyhedronFromPolygon returns a single polyhedron from a polygon *)

polyhedronFromPolygon[polygon_] :=      
 Module[{twoPolygons, verticesOfUpperPolygonCell, nVertices, n = 1},
 verticesOfUpperPolygonCell = Join @@ (polygon[[1]] /. {x_, y_} :> {{x, y, 0}, {x, y, -.08}});
 (* number of vertices in a single *Voronoi* cell *)
 nVertices = Length[verticesOfUpperPolygonCell]/2;   

(*vertex indices of the upper and lower polygon faces *)  
twoPolygons = Select[Range@(2*nVertices), #] & /@ {OddQ, EvenQ};    

(*vertex indices of a rectangular face of the polyhedron *)
While[n < nVertices + 1, AppendTo[twoPolygons,
    {twoPolygons[[1, n]], twoPolygons[[2, n]], 
     twoPolygons[[2, If[n + 1 < nVertices + 1, n + 1, 1]]], 
     twoPolygons[[1, If[n + 1 < nVertices + 1, n + 1, 1]]]}]; n++];
(*the graphics complex returned is a polyhedron, even though it says Polygon *)
 GraphicsComplex[verticesOfUpperPolygonCell, Polygon[twoPolygons]] ] 


(* takes two dimensional coordinates and returns all of the cells of a Voronoi diagram *)

voronoiPolygons[pts_] := 
Module[{voronoiRegion, data},
  voronoiRegion = VoronoiMesh[pts, ImageSize -> Medium, 
  PlotTheme -> "Lines", Axes -> True, AxesOrigin -> {0, 0}];
  data = Join @@ (MeshPrimitives[voronoiRegion, 2][[All, 1]] /. {x_, y_} :> {{x, y, 0}, {x, y, .04}});
 (* the mesh primitives are the polygons *)
  MeshPrimitives[voronoiRegion, 2]]   

(* Returns, in 3D, the point which was used to generate the nth Voronoi cell. *)
generatingPointFromPolygon[n_, points_, pgons_] := 
 FirstCase[points, {x_, y_} /; RegionMember[pgons[[n]], {x, y}] :> {x,y,0}]

crackedMud[seedNumber_] :- 
 Module[{pts, pts3D, geometricImage, nPts, polygons, polyhedra, centerPtinImage},
  SeedRandom[seedNumber];
  nPts = 80;
  pts = RandomReal[{-1, 1}, {nPts, 2}];
  pts3D = pts /. {x_, y_} :> {x, y, .0};
  polygons = voronoiPolygons[pts];
  polyhedra = polyhedronFromPolygon /@ polygons;
  centerPtinImage =   (Mean /@ (PlotRange /. 
        AbsoluteOptions[
         Graphics3D[{polyhedra, Blue, Point@pts3D}, Axes -> False, 
         Boxed -> False]])) /. {x_Real, y_, _} :> {x, y, 0};
  geometricImage =
  Graphics3D[{RGBColor[0.75, 0.75, 0.8], EdgeForm[Darker@Gray],
        (* # is the nth polygon which yields the nth polyhedron *)
        (* generatingPointFromPolygon returns the point the generated the #th polygon *)

     GeometricTransformation[{polyhedronFromPolygon[polygons[[#]]]},   
        TranslationTransform[(generatingPointFromPolygon[#, pts, polygons] - centerPtinImage)/5]] & /@ Range@nPts},
         Axes -> False,  Boxed -> False, ViewPoint -> {0., -1, 1.5}, 
         Background -> Black, ImageSize -> 1200];

     (*ImageTrim returns a 500 by 500 pixel clip from the center of the image *)
     ImageTrim[
        (*ImageEffect speckles the image *)
        ImageEffect[Rasterize[geometricImage], {"Noise", 1/5}], 
     {{250, 250}, {750, 750}}]
  ] 

ছড়িয়ে ছিটিয়ে থাকা কাচের প্যাটার্ন নির্মাতার সাথে এটি খাপ খাইয়ে নিতে আপনি ভাল করতে পারেন।
স্পার

@ স্পার, হ্যাঁ এটি দেখতে ছিন্নভিন্ন কাচের (বা টাইলস) মতো লাগে না।
ডেভিডসি

Golfed ........?
বিড়াল

@ কেট না, এটি গল্ফ হয়নি।
ডেভিডসি

@ ডেভিডসি সমস্ত সাদা স্থান কোথায়? তুমি কি এ রকম লিখো? ওল্ফ্রাম কি অপঠনযোগ্য কোড প্রয়োগ করে?
বিড়াল

24

জাভা

আমি পুনরাবৃত্তিতে ভোরোনাই চিত্রের উপর ভিত্তি করে একটি পদ্ধতির ব্যবহার করেছি। ফলাফলগুলি খুব বাস্তববাদী মনে হয় না, তবে আমি অনুমান করি যে তারা ঠিক আছে।

এখানে কয়েকটি উদাহরণ চিত্র (250x250 আকারে আকার দেওয়া হয়েছে যাতে এটি পুরো স্ক্রিনটি পূরণ করে না):

0:

চিত্র 0

1:

ছবি 1

অ্যালগরিদম সম্পর্কে আরও বিশদ:

এই বিভাগের সমস্ত চিত্র একই বীজ ব্যবহার করছে।

অ্যালগরিদমটি 5 পয়েন্ট সহ ভোরোনাই চিত্রটি তৈরি করে শুরু হয়:

ভোরোনাই চিত্র

যদি আমরা চ্যালেঞ্জের মূল চিত্রগুলি দেখি তবে আমরা দেখতে পাই যে রেখাগুলি সবগুলি এর মতো সোজা নয়, তাই আমরা বিন্দুটির কোণের উপর ভিত্তি করে একটি এলোমেলো মান দ্বারা দূরত্বকে ওজন করি, কাছাকাছি কোণগুলিও নিকটতর মান দেয় :

ওজনযুক্ত ভোরোনাই ডায়াগ্রাম

এখন, আমরা প্রতিটি অঞ্চলের অভ্যন্তরে পাতলা এবং আরও স্বচ্ছ লাইন দ্বারা পুনরাবৃত্তভাবে এই ধরণের ভোরোনাই চিত্রগুলি আঁকুন এবং সর্বাধিক 3 এর পুনরাবৃত্তি গভীরতার সাথে ব্যাকগ্রাউন্ডটি সরিয়ে ফেলি এবং আমরা পাই:

পুনরাবৃত্তি ভোরোনাই

এখন, আমরা কেবল ফ্যাকাশে বাদামী ব্যাকগ্রাউন্ড যুক্ত করব, এবং আমরা শেষ করেছি!

সম্পন্ন!

কোড:

কোডটিতে তিনটি শ্রেণি Main.java, VoronoiPoint.javaএবং রয়েছে Vector.java:

Main.java:

import java.awt.Desktop;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;

import javax.imageio.ImageIO;

public class Main {
    public static int WIDTH = 500;
    public static int HEIGHT = 500;
    public static int RECURSION_LEVELS = 3;
    public static int AMOUNT_OF_POINTS = 5;
    public static int ROTATION_RESOLUTION = 600;
    public static int ROTATION_SMOOTHNESS = 10;
    public static int BACKGROUND = 0xFFE0CBAD;

    public static Random RAND;

    public static void main(String[] args) {

        int seed = new Random().nextInt(65536);
        if (args.length == 1) {
            System.out.println(Arrays.toString(args));
            seed = Integer.parseInt(args[0]);
        } else {
            System.out.println("Generated seed: " + seed);
        }
        RAND = new Random(seed);

        ArrayList<Vector> points = new ArrayList<Vector>();
        for (int x = 0; x < WIDTH; x++) {
            for (int y = 0; y < HEIGHT; y++) {
                points.add(new Vector(x, y));
            }
        }
        BufferedImage soil = generateSoil(WIDTH, HEIGHT, seed, points, AMOUNT_OF_POINTS, RECURSION_LEVELS);

        BufferedImage background = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        for (int x = 0; x < background.getWidth(); x++) {
            for (int y = 0; y < background.getHeight(); y++) {
                background.setRGB(x, y, BACKGROUND ^ (RAND.nextInt(10) * 0x010101));
            }
        }

        Graphics g = background.getGraphics();
        g.drawImage(soil, 0, 0, null);
        g.dispose();

        String fileName = "soil";
        File output = new File(fileName + ".png");
        for (int i = 0; output.exists(); i++) {
            output = new File(fileName + i + ".png");
        }
        try {
            ImageIO.write(background, "png", output);
            Desktop.getDesktop().open(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Done. Saved as " + output);
    }

    private static BufferedImage generateSoil(int width, int height, int seed, ArrayList<Vector> drawPoints,
            int amountOfPoints, int recursionLevel) {

        BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        ArrayList<VoronoiPoint> points = new ArrayList<VoronoiPoint>();
        for (int i = 0; i < amountOfPoints; i++) {
            points.add(new VoronoiPoint(drawPoints.get(RAND.nextInt(drawPoints.size()))));
        }

        HashMap<Integer, ArrayList<Vector>> pointMaps = new HashMap<Integer, ArrayList<Vector>>();
        for (VoronoiPoint point : points) {
            pointMaps.put(point.hashCode(), new ArrayList<Vector>());
        }
        System.out.println(pointMaps);

        System.out.println(points);

        for (Vector v : drawPoints) {
            VoronoiPoint closest = null;
            VoronoiPoint secondClosest = null;

            for (VoronoiPoint point : points) {
                double distance = point.getMultiplicativeDistanceTo(v);
                if (closest == null || distance < closest.getMultiplicativeDistanceTo(v)) {
                    secondClosest = closest;
                    closest = point;
                } else if (secondClosest == null || distance < secondClosest.getMultiplicativeDistanceTo(v)) {
                    secondClosest = point;
                }
            }

            int col = 0;
            if (Math.abs(closest.getMultiplicativeDistanceTo(v)
                    - secondClosest.getMultiplicativeDistanceTo(v)) < (recursionLevel * 5 / RECURSION_LEVELS)) {
                col = 0x01000000 * (recursionLevel * 255 / RECURSION_LEVELS);
            } else {
                pointMaps.get(closest.hashCode()).add(v);
            }
            result.setRGB((int) v.getX(), (int) v.getY(), col);
        }
        Graphics g = result.getGraphics();
        if (recursionLevel > 0) {
            for (ArrayList<Vector> pixels : pointMaps.values()) {
                if (pixels.size() > 10) {
                    BufferedImage img = generateSoil(width, height, seed, pixels, amountOfPoints,
                            recursionLevel - 1);
                    g.drawImage(img, 0, 0, null);
                }
            }
        }
        g.dispose();

        return result;
    }

    public static int modInts(int a, int b) {
        return (int) mod(a, b);
    }

    public static double mod(double a, double b) {
        a = a % b;
        while (a < 0)
            a += b;
        return a;
    }
}

VoronoiPoint.java:

public class VoronoiPoint {

    private Vector pos;
    private double[] distances;

    public VoronoiPoint(Vector pos) {
        this.pos = pos;
        distances = new double[Main.ROTATION_RESOLUTION];
        for (int i = 0; i < distances.length; i++)
            distances[i] = Main.RAND.nextFloat() / 2 + 0.51;

        for (int iter = 0; iter < Main.ROTATION_SMOOTHNESS; iter++) {
            for (int i = 0; i < distances.length; i++) {
                distances[i] = (distances[Main.modInts(i - Main.RAND.nextInt(4) - 2, distances.length)] + distances[i]
                        + distances[Main.modInts(i + Main.RAND.nextInt(4) - 2, distances.length)]) / 3;
            }
        }
    }

    public Vector getPos() {
        return pos;
    }

    public double getRotationFromAngle(double radians) {
        return distances[(int) (Main.mod(Math.toDegrees(radians) / 360, 1) * distances.length)];
    }

    public double getRotationFromVector(Vector vec) {
        return getRotationFromAngle(Math.atan2(pos.getY() - vec.getY(), -(pos.getX() - vec.getX())));
    }

    public double getMultiplicativeDistanceTo(Vector other) {
        return pos.getLengthTo(other) * getRotationFromVector(other);
    }

    public String toString() {
        return "VoronoiPoint(pos=[" + pos.getX() + ", " + pos.getY() + "])";
    }

    public int hashCode() {
        return distances.hashCode() ^ pos.hashCode();
    }
}

Vector.java: (এই শ্রেণিটি আমার অন্যান্য প্রকল্পগুলির একটির থেকে অনুলিপি করা হয়েছে, সুতরাং এতে কিছু অপ্রয়োজনীয় কোড রয়েছে)

package com.loovjo.soil;

import java.util.ArrayList;
import java.util.Random;

public class Vector {
    private static final float SMALL = 1f / Float.MAX_EXPONENT * 100;
    private float x, y;

    public Vector(float x, float y) {
        this.setX(x);
        this.setY(y);
    }

    public Vector(int x, int y) {
        this.setX(x);
        this.setY(y);
    }

    public Vector(double x, double y) {
        this.setX((float) x);
        this.setY((float) y);
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    /*
     * Gets the length ^ 2 This is faster than getting the length.
     */
    public float getLengthToSqrd(float x, float y) {
        return (float) ((this.x - x) * (this.x - x) + (this.y - y) * (this.y - y));
    }

    public float getLengthToSqrd(Vector v) {
        return getLengthToSqrd(v.x, v.y);
    }

    public float getLengthSqrd() {
        return getLengthToSqrd(0, 0);
    }

    public float getLengthTo(float x, float y) {
        return (float) Math.sqrt(getLengthToSqrd(x, y));
    }

    public float getLengthTo(Vector v) {
        return getLengthTo(v.x, v.y);
    }

    public float getLength() {
        return getLengthTo(0, 0);
    }

    public Vector setLength(float setLength) {
        float length = getLength();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public float getFastLengthTo(float x, float y) {
        return getFastLengthTo(new Vector(x, y));
    }

    public float getFastLengthTo(Vector v) {
        float taxiLength = getTaxiCabLengthTo(v);
        float chebyDist = getChebyshevDistanceTo(v);
        return Float.min(taxiLength * 0.7f, chebyDist);
    }

    public float getFastLength() {
        return getLengthTo(0, 0);
    }

    public Vector setFastLength(float setLength) {
        float length = getFastLength();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public float getTaxiCabLengthTo(float x, float y) {
        return Math.abs(this.x - x) + Math.abs(this.y - y);
    }

    public float getTaxiCabLengthTo(Vector v) {
        return getTaxiCabLengthTo(v.x, v.y);
    }

    public float getTaxiCabLength() {
        return getTaxiCabLengthTo(0, 0);
    }

    public Vector setTaxiCabLength(float setLength) {
        float length = getTaxiCabLength();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public Vector absIfBoth() {
        if (x < 0 && y < 0)
            return new Vector(-x, -y);
        return this;
    }

    public Vector abs() {
        return new Vector(x < 0 ? -x : x, y < 0 ? -y : y);
    }

    public float getChebyshevDistanceTo(float x, float y) {
        return Math.max(Math.abs(this.x - x), Math.abs(this.y - y));
    }

    public float getChebyshevDistanceTo(Vector v) {
        return getChebyshevDistanceTo(v.x, v.y);
    }

    public float getChebyshevDistance() {
        return getChebyshevDistanceTo(0, 0);
    }

    public Vector setChebyshevLength(float setLength) {
        float length = getChebyshevDistance();
        x *= setLength / length;
        y *= setLength / length;
        return this;
    }

    public Vector sub(Vector v) {
        return new Vector(this.x - v.getX(), this.y - v.getY());
    }

    public Vector add(Vector v) {
        return new Vector(this.x + v.getX(), this.y + v.getY());
    }

    public Vector mul(Vector v) {
        return new Vector(this.x * v.getX(), this.y * v.getY());
    }

    public Vector mul(float f) {
        return mul(new Vector(f, f));
    }

    public Vector div(Vector v) {
        return new Vector(this.x / v.getX(), this.y / v.getY());
    }

    public Vector div(float f) {
        return div(new Vector(f, f));
    }

    public Vector mod(Vector v) {
        return new Vector(this.x % v.getX(), this.y % v.getY());
    }

    public Vector mod(int a, int b) {
        return mod(new Vector(a, b));
    }

    public Vector mod(int a) {
        return mod(a, a);
    }

    public String toString() {
        return "Vector(" + getX() + ", " + getY() + ")";
    }

    /*
     * Returns a list with vectors, starting with this, ending with to, and each
     * one having length between them
     */
    public ArrayList<Vector> loop(Vector to, float length) {
        Vector delta = this.sub(to);
        float l = delta.getLength();
        ArrayList<Vector> loops = new ArrayList<Vector>();
        for (float i = length; i < l; i += length) {
            delta.setLength(i);
            loops.add(delta.add(to));
        }
        loops.add(this);

        return loops;
    }

    public boolean intersects(Vector pos, Vector size) {
        pos.sub(this);
        if (pos.getX() < getX())
            return false;
        if (pos.getY() < getY())
            return false;
        return true;
    }

    public Vector copy() {
        return new Vector(x, y);
    }

    public void distort(float d) {
        x += Math.random() * d - d / 2;
        y += Math.random() * d - d / 2;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Vector) {
            Vector v = (Vector) o;
            return getLengthToSquared(v) < SMALL * SMALL;
        }
        return false;
    }

    private float getLengthToSquared(Vector v) {
        return sub(v).getLengthSquared();
    }

    private float getLengthSquared() {
        return x * x + y * y;
    }

    public boolean kindaEquals(Vector o, int i) {
        if (o.x + i < x)
            return false;
        if (o.x - i > x)
            return false;
        if (o.y + i < y)
            return false;
        if (o.y - i > y)
            return false;
        return true;
    }
    /*
     * Gets the direction, from 0 to 8.
     */
    public int getDirection() {
        return (getDirectionInDegrees()) / (360 / 8);
    }
    /*
     * Gets the direction in degrees.
     */
    public int getDirectionInDegrees() {
        return (int) positize((float) Math.toDegrees(Math.atan2(x, -y)), 360f);
    }

    private float positize(float f, float base) {
        while (f < 0)
            f += base;
        return f;
    }
    // 0 = north,
            // 1 = northeast,
            // 2 = east,
            // 3 = southeast,
            // 4 = south,
            // 5 = southwest,
            // 6 = west,
            // 7 = northwest
    public Vector moveInDir(int d) {
        d = d % 8;
        d = (int) positize(d, 8);

        if (d == 0)
            return this.add(new Vector(0, -1));
        if (d == 1)
            return this.add(new Vector(1, -1));
        if (d == 2)
            return this.add(new Vector(1, 0));
        if (d == 3)
            return this.add(new Vector(1, 1));
        if (d == 4)
            return this.add(new Vector(0, 1));
        if (d == 5)
            return this.add(new Vector(-1, 1));
        if (d == 6)
            return this.add(new Vector(-1, 0));
        if (d == 7)
            return this.add(new Vector(-1, -1));
        return this;
    }
    /*
     * Gets the angle in degrees to o.
     */
    public float getRotationTo(Vector o) {
        float d = (float) Math.toDegrees((Math.atan2(y - o.y, -(x - o.x))));
        while (d < 0)
            d += 360;
        while (d > 360)
            d -= 360;
        return d;
    }
    public float getRotation() {
        return getRotationTo(new Vector(0, 0));
    }
    /*
     * In degrees
     */
    public Vector rotate(double n) {
        n = Math.toRadians(n);
        float rx = (float) ((this.x * Math.cos(n)) - (this.y * Math.sin(n)));
        float ry = (float) ((this.x * Math.sin(n)) + (this.y * Math.cos(n)));
        return new Vector(rx, ry);
    }

    public int hashCode() {
        int xx = (int) x ^ (int)(x * Integer.MAX_VALUE);
        int yy = (int) y ^ (int)(y * Integer.MAX_VALUE);
        return new Random(12665 * xx).nextInt() ^ new Random(5349 * yy).nextInt() + new Random((30513 * xx) ^ (19972 * yy)).nextInt();
    }

    public boolean isPositive() {
        return x >= 0 && y >= 0;
    }

    public Vector clone() {
        return new Vector(x, y);
    }
}

তবে আমি জাভা ক্লাসের একগুচ্ছ সংকলন করতে চাই না!

এখানে একটি জার ফাইল রয়েছে যা আপনি নিজেরাই এই চিত্রগুলি তৈরি করতে চালাতে পারেন। বীজ java -jar Soil.jar numberকোথায় রয়েছে numberতা চালান (2 31 -1 অবধি কিছু হতে পারে ) বা এর মতো চালান java -jar Soil.jar, এবং এটি নিজেই একটি বীজ পছন্দ করে। কিছু ডিবাগ আউটপুট হবে।


কিছু কারণে আমি এই চিত্রগুলি মোটামুটি বাস্তববাদী এবং সম্পূর্ণ জাল উভয়ই পেয়েছি। প্রাকৃতিক ছায়ার অভাব আমাকে দূরে সরিয়ে দিচ্ছে।
ফ্যাটালাইজ করুন

যদি এটি সহায়তা করে তবে আপনি পূর্ণ আকারের চিত্রগুলি আপলোড করতে এবং চ্যালেঞ্জ পোস্টের মতো ছোট ছোট থাম্বনেইলগুলি তৈরি করতে পারেন বা মাঝারি চিত্রগুলি যা কম উল্লম্ব স্থান নিতে 2 পারের ফিট fit ইন চ্যালেঞ্জের উৎস কেমন imgur ঠিকানাতে যোগ করার সময় একটি "s" এর দেখতে পারেন ইমেজ ছোট করে তোলে, এবং আপনার কাছে মাঝারি জন্য একটি "M" ব্যবহার করতে পারেন। উত্সটিও দেখায় যে কীভাবে ছোট চিত্রটিকে পূর্ণ আকারের চিত্রের লিঙ্ক তৈরি করতে হয়।
ট্রাইকোপল্যাক্স

2
আমি মনে করি রঙগুলি আরও কাছাকাছি হতে পারে - আরও ধূসর, কম বেইজ। তবে অন্যথায় সুন্দর উত্তর!
ক্যালভিনের শখ

12

পাইথন 3 (কিভি লাইব্রেরি এবং জিএলএসএল ব্যবহার করে)

প্রথম উত্পন্ন চিত্র

এখানে চিত্র বর্ণনা লিখুন

পাইথন কোড:

import os
os.environ['KIVY_NO_ARGS'] = '1'

from kivy.config import Config
Config.set('input','mouse','mouse,disable_multitouch')
Config.set('graphics', 'width', '500')
Config.set('graphics', 'height', '500')
Config.set('graphics', 'resizable', '0')
Config.set('graphics', 'borderless', '1')
Config.set('graphics', 'fbo', 'force-hardware')

from kivy.app import App
from kivy.graphics import RenderContext, Fbo, Color, Rectangle
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.factory import Factory
from kivy.core.window import Window

class ShaderSurface(FloatLayout):
    seed = 0.

    def __init__(self, **kwargs):
        self.canvas = RenderContext(use_parent_projection=True, use_parent_modelview=True)
        with self.canvas:
            self.fbo = Fbo(size=Window.size, use_parent_projection=True)

        with self.fbo:
            Color(0,0,0)
            Rectangle(size=Window.size)

        self.texture = self.fbo.texture

        super(ShaderSurface, self).__init__(**kwargs)
        self.keyboard = Window.request_keyboard(self.keyboard_closed, self)
        self.keyboard.bind(on_key_down=self.on_key_down)
        Clock.schedule_once(self.update_shader,-1)

    def keyboard_closed(self):
        self.keyboard.unbind(on_key_down=self.on_key_down)
        self.keyboard = None

    def update_shader(self, dt=0.):
        self.canvas['resolution'] = list(map(float, self.size))
        self.canvas['seed'] = self.seed
        self.canvas.ask_update()

    def on_key_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'spacebar':
            self.seed += 1.
            self.update_shader()
            Window.screenshot()

Factory.register('ShaderSurface', cls=ShaderSurface)

class RendererApp(App):
    def build(self):
        self.root.canvas.shader.source = 'cracks_sub.glsl'

if __name__ == '__main__':
    RendererApp().run()

কেভি ফাইল:

#:kivy 1.9

ShaderSurface:
    canvas:
        Color:
            rgb: 1, 1, 1
        Rectangle:
            size: self.size
            pos: self.pos
            texture: root.fbo.texture

জিএলএসএল কোড:

---VERTEX---
uniform vec2        resolution;
in vec2             vPosition;

void main()
{
    gl_Position = vec4(vPosition.xy-resolution/2., 0, 1);
}
---FRAGMENT---
#version 330
precision highp float;

out vec4 frag_color;

uniform vec2 resolution;
uniform float seed;

vec2 tr(vec2 p)
{
    p /= resolution.xy;
    p = -1.0+2.0*p;
    p.y *= resolution.y/resolution.x;
    return p;
}

float hash( float n ){
    return fract(sin(n)*43758.5453);
}

float noise( vec2 uv ){
    vec3 x = vec3(uv, 0);

    vec3 p = floor(x);
    vec3 f = fract(x);

    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;

    return mix(mix(mix( hash(n+0.0), hash(n+1.0),f.x),
                   mix( hash(n+57.0), hash(n+58.0),f.x),f.y),
               mix(mix( hash(n+113.0), hash(n+114.0),f.x),
                   mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

mat2 m = mat2(0.8,0.6,-0.6,0.8);

float fbm(vec2 p)
{
    float f = 0.0;
    f += 0.5000*noise( p ); p*=m*2.02;
    f += 0.2500*noise( p ); p*=m*2.03;
    f += 0.1250*noise( p ); p*=m*2.01;
    f += 0.0625*noise( p );
    f /= 0.9375;
    return f;
}

vec2 hash2( vec2 p )
{
    return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}

float voronoi(vec2 x, out vec2 rt)
{
    vec2 p = floor(x);
    vec2 f = fract(x);

    vec2 mb, mr;

    float res = 8.0;
    for( int j=-1; j<=1; j++)
    for( int i=-1; i<=1; i++)
    {
        vec2 b = vec2(float(i),float(j));
        vec2 r = b+hash2(p+b)-f;
        float d = dot(r,r);

        if( d<res )
        {
            res = d;
            mr = r;
            mb = b;
            rt=r;
        }
    }


    res = 8.0;
    for( int j=-2; j<=2; j++ )
    for( int i=-2; i<=2; i++ )
    {
        vec2 b = mb + vec2(float(i),float(j));
        vec2 r = b + hash2(p+b)-f;
        float d = dot((res*res)*(mr+r),normalize(r-mr));

        res = min(res,d);
    }


    return res;
}

float crack(vec2 p)
{
    float g = mod(seed,65536./4.);
    p.x+=g;
    p.y-=seed-g;
    p.y*=1.3;
    p.x+=noise(p*4.)*.08;
    float k = 0.;
    vec2 rb = vec2(.0);
    k=voronoi(p*2.,rb);
    k=smoothstep(.0,.3,k*.05);
    float v = 0.;
    v=voronoi(rb*4.,rb);
    v=smoothstep(.0,.5,v*.05);
    k*=v;
    k-=fbm(p*128.)*.3;
    return k;
}

void main( void )
{
    vec2 fc = gl_FragCoord.xy;
    vec2 p = tr(fc);
    vec3 col = vec3(.39,.37,.25);

    vec3 abb = vec3(.14,.12,.10)/5.;

    p*=(1.+length(p)*.1);

    col.r*=crack(vec2(p.x+abb.x,p.y));
    col.g*=crack(vec2(p.x+abb.y,p.y));
    col.b*=crack(vec2(p.x+abb.z,p.y));

    col*=smoothstep(4.,1.2,dot(p,p));
    col*=exp(.66);

    //col=vec3(crack(p));
    frag_color = vec4(col,1.);
}

Voronoi GLSL কোডে ফাংশন Íñigo Quílez থেকে। প্রতিটি ভোরোনাই সম্পর্কিত গণনা খণ্ড তৈরির জন্য কিছু প্রক্রিয়াজাতীয় শোর ফাংশনগুলির সাথে পুরোপুরি খণ্ড শ্যাডারে ঘটে এবং ভেরোনাই প্যাটার্নটির লাইনগুলিকে কিছুটা বিঘ্নিত করতে।

স্পেস টিপে বীজ 1 দ্বারা বাড়ানো হবে এবং একটি নতুন চিত্র উত্পন্ন এবং .pngফাইল হিসাবে সংরক্ষণ করা হবে।

আপডেট: আরও ফটো-বাস্তবসম্মত করার জন্য লেন্সের বিকৃতি, ভিগনেটিং এবং ক্রোম্যাটিক ক্ষয় যুক্ত করা হয়েছে। সাব ভোরোনাই প্যাটার্ন যুক্ত হয়েছে।


এটি কি ইনপুট হিসাবে একটি বীজ নিতে পারে?
ট্রাইকোপলাক্স

শ্যাডসারফেস ক্লাসে ক্লাস মেম্বার রয়েছে seed। এটি শ্যাডারে একটি অভিন্ন ফ্লোট ভেরিয়েবল হিসাবে পাইপ করা হবে। শ্যাডারের ক্র্যাক ফাংশনে বীজটি বীজের মান দ্বারা বিন্দু অনুবাদ করতে ব্যবহৃত হয়।
গ্যাবার ফেকেতে

1

জাভা

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;

import javax.imageio.ImageIO;

public class CrackedSoil {
    static BufferedImage b;
    static Random rand;
    public static int distance(int col1,int col2){
        Color a=new Color(col1);
        Color b=new Color(col2);
        return (int)(Math.pow(a.getRed()-b.getRed(), 2)+Math.pow(a.getGreen()-b.getGreen(), 2)+Math.pow(a.getBlue()-b.getBlue(), 2));
    }
    public static void edge(){
        boolean[][] edges=new boolean[500][500];
        int threshold=125+rand.nextInt(55);
        for(int x=1;x<499;x++){
            for(int y=1;y<499;y++){
                int rgb=b.getRGB(x, y);
                int del=0;
                for(int i=-1;i<=1;i++){
                    for(int j=-1;i<=j;i++){
                        del+=distance(rgb,b.getRGB(x+i, y+j));
                    }
                }
                edges[x][y]=del>threshold;
            }
        }
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                if(edges[x][y])b.setRGB(x, y,new Color(4+rand.nextInt(4),4+rand.nextInt(4),4+rand.nextInt(4)).getRGB());
            }
        }
    }
    public static void main(String[]arg) throws IOException{
        b=new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
        Scanner scanner=new Scanner(System.in);
        rand=new Random(scanner.nextInt());
        int numPoints=10+rand.nextInt(15);
        Color[]c=new Color[numPoints];
        int[][]ints=new int[numPoints][2];
        int[]weights=new int[numPoints];
        for(int i=0;i<numPoints;i++){
            switch(i%4){
            case 0:ints[i]=new int[]{251+rand.nextInt(240),7+rand.nextInt(240)};break;
            case 1:ints[i]=new int[]{7+rand.nextInt(240),7+rand.nextInt(240)};break;
            case 2:ints[i]=new int[]{7+rand.nextInt(240),251+rand.nextInt(240)};break;
            case 3:ints[i]=new int[]{251+rand.nextInt(240),251+rand.nextInt(240)};break;
            }

            c[i]=new Color(40+rand.nextInt(200),40+rand.nextInt(200),40+rand.nextInt(200));
            weights[i]=50+rand.nextInt(15);
        }
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                double d=999999;
                Color col=Color.BLACK;
                for(int i=0;i<numPoints;i++){
                    double d2=weights[i]*Math.sqrt((x-ints[i][0])*(x-ints[i][0])+(y-ints[i][1])*(y-ints[i][1]));
                    if(d2<d){
                        d=d2;
                        col=c[i];
                    }
                }
                b.setRGB(x, y,col.getRGB());
            }
        }
        //ImageIO.write(b,"png",new File("voronoi1.png"));
        for(int i=0;i<numPoints/3;i++){
            ints[i]=new int[]{7+rand.nextInt(490),7+rand.nextInt(490)};
            c[i]=new Color(40+rand.nextInt(200),40+rand.nextInt(200),40+rand.nextInt(200));
            weights[i]=50+rand.nextInt(5);
        }
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                double d=999999;
                Color col=Color.BLACK;
                for(int i=0;i<numPoints/3;i++){
                    double d2=weights[i]*Math.sqrt((x-ints[i][0])*(x-ints[i][0])+(y-ints[i][1])*(y-ints[i][1]));
                    if(d2<d){
                        d=d2;
                        col=c[i];
                    }
                }
                Color col3=new Color(b.getRGB(x, y));
                b.setRGB(x, y,new Color((col3.getRed()+col.getRed()*3)/4,(col3.getGreen()+col.getGreen()*3)/4,(col3.getBlue()+col.getBlue()*3)/4).getRGB());
            }
        }
        //ImageIO.write(b,"png",new File("voronoi2.png"));
        for(int i=2+rand.nextInt(3);i>0;i--)edge();
        //ImageIO.write(b,"png",new File("voronoi_edge.png"));
        for(int x=0;x<500;x++){
            for(int y=0;y<500;y++){
                Color col=new Color(b.getRGB(x, y));
                if(col.getRed()+col.getBlue()+col.getGreen()>50){
                    if(rand.nextDouble()<0.95){
                        b.setRGB(x, y,new Color(150+rand.nextInt(9),145+rand.nextInt(9),135+rand.nextInt(9)).getRGB());
                    }else{
                        b.setRGB(x, y,new Color(120+col.getRed()/7+rand.nextInt(12),115+col.getGreen()/7+rand.nextInt(12),105+col.getBlue()/7+rand.nextInt(12)).getRGB());
                    }
                }
            }
        }
        ImageIO.write(b,"png",new File("soil.png"));
    }
}

দুটি এলোমেলো চিত্রের সংমিশ্রণ তৈরি করে যা একটি সাধারণ প্রান্ত সনাক্তকরণের মাধ্যমে চালিত হয় এবং শেষ পর্যন্ত চূড়ান্ত ফলাফলে রূপান্তরিত হয়।

কিছু ফলাফল:

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

শেষটির মধ্যবর্তী কয়েকটি পদক্ষেপ:

এখানে চিত্র বর্ণনা লিখুন

(প্রথম ভোরোনাই চিত্র)

এখানে চিত্র বর্ণনা লিখুন

(দুটি ভোরোনাই চিত্রের সংমিশ্রণ)

এখানে চিত্র বর্ণনা লিখুন

(প্রান্ত সনাক্তকরণ পদক্ষেপের পরে তবে চূড়ান্ত পুনরুদ্ধারের আগে)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.