बीज पर आधारित यादृच्छिक शोर


16

मैं वर्तमान में एक ऐसे प्रोग्राम पर काम कर रहा हूं, जिसमें एक पिक्सेल के 'निर्देशांक' के आधार पर स्क्रीन पर रैंडम शोर उत्पन्न करना चाहिए। जब भी आप प्रोग्राम को पुनरारंभ करते हैं, तो निर्देशांक में एक ही रंग होना चाहिए। हालांकि, जावा के उपयोग का उपयोग करते हुए। आयामी, मुझे मिलने वाले परिणाम उतने यादृच्छिक नहीं हैं जितना मैं चाहूंगा:

प्रिंट स्क्रीन

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

यह वह कोड है जिसका मैंने उपयोग किया है:

public class Generate {

static Random Random;

    public static int TileColor(int x, int y){          
        Random = new Random(Integer.valueOf(Integer.toString(x)+Integer.toString(y)));
        int b = 1 + Random.nextInt(50);
        int g = 1 + Random.nextInt(50);
        int r = 1 + Random.nextInt(50);
        int color = -Color.rgb888(r, g, b);
        return color;
    }
}

जिस तरह से जावा का रैंडम फ़ंक्शन काम करता है या क्या मैं कुछ गलत कर रहा हूं और क्या मुझे एक अलग दृष्टिकोण की कोशिश करनी चाहिए, के कारण यह पैटर्न बनता है?

अद्यतन: मैंने अब निम्नलिखित कोड का उपयोग करके समवर्ती आसपास की समस्याओं से छुटकारा पाने की कोशिश की:

public static int TileColor(int x, int y){  
            Randomy = new Random(y);
            Randomx = new Random(x);
            Random = new Random(Integer.valueOf(Integer.toString(Randomx.nextInt(1234))+Integer.toString(Randomy.nextInt(1234))));
            int b = 1 + Random.nextInt(100);
            int g = 1 + Random.nextInt(100);
            int r = 1 + Random.nextInt(100);
            int color = -Color.rgb888(r, g, b);
            return color;
}

किसी तरह, इसने एक (मेरी राय में) पर्याप्त रूप से यादृच्छिक छवि प्रदान की:

मेव छवि

हालाँकि यह कोड प्रति पिक्सेल तीन गुना अधिक है। भले ही यह अभी मेरे लिए कोई समस्या नहीं है, लेकिन मैं इस कोड को बदलने के बारे में सोचता हूं कि मुझे बाद में बेहतर सुधार की आवश्यकता है।


3
जावा के रैंडम के बारे में निश्चित नहीं है, लेकिन मुझे पूरा यकीन है कि यह वास्तविक रैंडम नहीं है ... en.wikipedia.org/wiki/Pseudorandom_number_generator पढ़ें आप समझेंगे कि आप उन पैटर्नों को क्यों देखते हैं।
साल्केटर

23
कुछ महत्वपूर्ण जो अन्य उत्तरों से गायब है: प्रत्येक पिक्सेल के लिए RNG को फिर से न बनाएँ। इसे एक बार सीड करें और अपनी छवि के सभी पिक्सेल के लिए लगातार मान उत्पन्न करें जो कि बंद है।
कोनराड रुडोल्फ

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

6
@Bakuriu यदि X, Y और Z स्वतंत्र समान यादृच्छिक चर हैं, तो मुझे पूरा यकीन है (X, Y, Z) 3 डी अंतरिक्ष में समान है।
जैक एम

2
आप Mersenne Twister की तरह विभिन्न RNG का उपयोग करके प्रयोग कर सकते हैं ।
केविन

जवाबों:


21

जावा की java.util.Randomकक्षा आपको आमतौर पर छद्म आयामी संख्याओं के अनुक्रम देती है जो खेल 1 में उपयोग के लिए पर्याप्त हैं । हालाँकि, यह विशेषता केवल एक बीज के आधार पर कई नमूनों के अनुक्रम पर लागू होती है। जब आप RNG को वृद्धिशील बीज मानों के साथ पुनर्निमित करते हैं और केवल प्रत्येक अनुक्रम के पहले मूल्य को देखते हैं, तो यादृच्छिकता विशेषताएँ लगभग उतनी अच्छी नहीं होंगी।

आप इसके बजाय क्या कर सकते हैं:

  • एक बार में पिक्सेल के पूरे विखंडन को उत्पन्न करने के लिए एक ही बीज का उपयोग करें। उदाहरण के लिए, जब आपको पिक्सेल 425: 487 के रंग मूल्य की आवश्यकता होती है, तो निर्देशांक 400: 400 को आरएनजी में फ़ीड करें, 10000 यादृच्छिक रंग उत्पन्न करें और सूचकांक 2587 (25 * 100 + 87) पर रंग का उपयोग करें। उस तरीके से उत्पन्न चनों को उस चंक के हर एक पिक्सेल के लिए उन 10000 यादृच्छिक रंगों को फिर से पैदा करने से बचने के लिए कैश किया जाना चाहिए।
  • एक यादृच्छिक संख्या जनरेटर का उपयोग करने के बजाय, एक समन्वय मूल्य को एक रंग मूल्य में बदलने के लिए एक संदेश डाइजेस्ट फ़ंक्शन का उपयोग करें । यादृच्छिकता के अधिकांश परीक्षणों को पूरा करने के लिए अधिकांश एमडीएफ का उत्पादन अप्रत्याशित है। आउटपुट आमतौर पर आरजीबी मूल्य के लिए आवश्यक 24 बिट से अधिक होता है, लेकिन उन्हें छोटा करना आमतौर पर कोई समस्या नहीं है।

    प्रदर्शन को बेहतर बनाने के लिए आप संदेश डाइजेस्ट जनरेशन को चंक्स के साथ जोड़ सकते हैं। पिक्सेल के छोटे विखंडू उत्पन्न करें जो आपके पाचन कार्य के एक आउटपुट की पूरी लंबाई का उपयोग करने के लिए पर्याप्त बड़े हैं।

1 जब यह पूरी तरह से आवश्यक है कि कोई भी अगली संख्या की भविष्यवाणी नहीं कर सकता है, तो धीमी लेकिन कम पूर्वानुमान का उपयोग करेंjava.security.SecureRandom


13

निर्देशांक में वही रंग होना चाहिए जिसे आप प्रोग्राम को पुनरारंभ करते हैं

उस स्थिति में, आप एक नियतात्मक शोर फ़ंक्शन का उपयोग करना चाहते हैं जैसे कि पेर्लिन शोर या सिंप्लेक्स शोर

( कुछ सुंदर चित्रों के साथ पर्लिन शोर पर कुछ और जानकारी के लिए इस प्रश्न को देखें। )

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

एक अन्य विकल्प "शोर मानचित्र" को एक बार, ऑफ़लाइन, और उसके बाद अपने यादृच्छिक संख्या स्रोत के रूप में उपयोग करना है।

आपके कार्यान्वयन में, आप x के स्ट्रिंग निरूपण को समाप्‍त कर रहे हैं और y। यह बुरा है क्योंकि यह पूरे डोमेन में अद्वितीय नहीं है। उदाहरण के लिए,

x    y   concatenated
40   20  4020
402   0  4020
10   10  1010
101   0  1010
12   34  1234
123   4  1234
1   234  1234

सौभाग्य!


1
समवर्ती संख्याओं के बारे में अच्छी बात। हालाँकि प्रोग्राम हमेशा सटीक एक ही परिणाम देता है अगर मैं कई बार प्रोग्राम चलाता हूँ। मैंने पेर्लिन / सिम्पलेक्स शोर को भी माना है, उस पर एक नज़र डाल सकता है और देख सकता है कि क्या यह बेहतर काम करता है। मैं अभी तक निश्चित नहीं हूं कि जावा पैटर्न क्यों बनाता है, क्योंकि समसामयिक समस्या इसे पूरी तरह से हल करने के लिए प्रतीत नहीं होती है
dragonfly

1
क्या पिक्सल पैदा करने से पहले एक निरंतर बीज मूल्य के साथ बस रैंडम सीड करना पर्याप्त नहीं है?
जैक एम

1
@JackM जो पूरी तरह से खेलने में PRNG एल्गोरिथ्म पर निर्भर करता है।
डीवेट

4
"मैंने एक बार एक रैंड () कार्यान्वयन देखा था जो प्रत्येक मूल्य को अगले मूल्य के लिए बीज के रूप में इस्तेमाल करता था।" क्या यह नहीं है कि सबसे गैर-क्रिप्टोग्राफिक छद्म आयामी संख्या जनरेटर कैसे काम करते हैं? वे अगले यादृच्छिक संख्या / स्थिति उत्पन्न करने के लिए इनपुट के रूप में पिछले यादृच्छिक संख्या (या राज्य) का उपयोग करते हैं।
JAB

2
@DavidLively वस्तुतः सभी PRNG ऐसा या कुछ समतुल्य करते हैं, जब तक कि उनकी आंतरिक स्थिति उनके द्वारा उत्पन्न संख्या की सीमा से बड़ी नहीं होती (जैसे Mersenne twisters), और फिर भी यादृच्छिक संख्याओं का क्रम निश्चित रूप से बीज द्वारा पूरी तरह से निर्धारित होता है।
कोनराड रुडोल्फ

9

आइए देखें कि आप वास्तव में क्या कर रहे हैं:

  • आप एक-एक करके सभी पिक्सल के माध्यम से लूप करते हैं
  • प्रत्येक पिक्सेल के लिए, आप एक बीज के रूप में इसके निर्देशांक के संघनन का उपयोग करते हैं
  • फिर आप दिए गए बीज से एक नया यादृच्छिक शुरू करते हैं और 3 नंबर निकालते हैं

यह सब ठीक लगता है, लेकिन आप एक पैटर्न प्राप्त कर रहे हैं क्योंकि:

1,11 में पिक्सेल और 11,1 पर पिक्सेल दोनों 111 नंबर पर हैं, इसलिए उनका रंग एक जैसा होना निश्चित है।

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


बात यह है कि छवि का दृश्य शिफ्ट करने में सक्षम होना चाहिए (आगे सकारात्मक निर्देशांक)। तो यह दृष्टिकोण पूरी तरह से काम नहीं करेगा
dragonfly

4
वास्तव में "यह सब" ठीक नहीं लगता - प्रत्येक पिक्सेल के लिए एक नियतात्मक RNG का निर्धारण तब तक एक भयानक रणनीति है जब तक कि बीज स्वयं एक क्रिप्टोग्राफिक RNG से न हो (और फिर भी यह वितरण के लिए असंबंधित कारणों के लिए एक शानदार रणनीति है)।
कोनराड रुडोल्फ

आप इस संदर्भ में संख्याओं को समाप्‍त करने का सही तरीका शामिल कर सकते हैं। अर्थात। (x + y * चौड़ाई)
तैमूर

1

एक रंग जनरेटर बनाओ, फिर अपनी टाइल के लिए अपने रंगों का उत्पादन करें। केवल एक बार बीज! आपको कम से कम प्रति टाइल से अधिक बीज लगाने की आवश्यकता नहीं है।

public class RandomColorGenerator {
  private final int minValue;
  private final int range;
  private final Random random;
  public RandomColorGenerator(int minValue, int maxValue, Random random) {
    if (minValue > maxValue || (long)maxValue - (long)minValue > (long)Integer.MAX_VALUE) {
      throw new IllegalArgumentException();
    }
    this.minValue = minValue;
    this.range = maxValue - minValue + 1;
    this.random = Objects.requireNonNull(random);
  }

  public int nextColor() {
    int r = minValue + random.nextInt(range);
    int g = minValue + random.nextInt(range);
    int b = minValue + random.nextInt(range);
    return -Color.rgb888(r, g, b);
  }
}

public class Tile {
  private final int[][] colors;
  public Tile(int width, int height, RandomColorGenerator colorGenerator) {
    this.colors = new int[width][height];
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        this.colors[x][y] = colorGenerator.nextColor();
      }
    }
  }

  public int getColor(int x, int y) {
    return colors[x][y];
  }
}

और उपयोग इस प्रकार होगा:

RandomColorGenerator generator = new RandomColorGenerator(1, 100, new Random(0xcafebabe));
Tile tile = new Tile(300, 200, generator);
...
// getting the color for x, y:
tile.getColor(x, y);

इसके साथ यदि आप परिणाम से खुश नहीं हैं तो बस Randomबीज बदल दें । इसके अलावा, आपको केवल बीज और आकारों को स्टोर / संचार करना होगा ताकि सभी ग्राहकों की छवि समान हो।


1

रैंडम का उपयोग करने के बजाय, एमडी 5 जैसे हैश डाइजेस्ट का उपयोग करने पर विचार करें। यह एक निश्चित इनपुट के आधार पर 'यादृच्छिक' मान की भविष्यवाणी करने के लिए एक कठिन प्रदान करता है, लेकिन हमेशा एक ही इनपुट के लिए समान मूल्य।

उदाहरण:

public static int TileColor(int x, int y){
        final MessageDigest md = MessageDigest.getInstance("MD5");
        final ByteBuffer b = ByteBuffer.allocate(8);
        b.putInt(x).putInt(y);
        final byte[] digest = md.digest(b.array());
        return -Color.rgb888(digest[0], digest[1], digest[2]);
}

नोट: मुझे नहीं पता कि Color.rgb888 (..) कहां से आता है, इसलिए मुझे नहीं पता कि अनुमत सीमा क्या है। 0-255 हालांकि सामान्य है।

विचार करने के लिए सुधार:

  • प्रदर्शन में सुधार करने के लिए, मैसेजडेस्ट और बाइटबफ़र चर को कक्षा के बाहर करें। आपको ऐसा करने के लिए बाइटबफ़र को रीसेट करना होगा, और यह विधि अब थ्रेड सुरक्षित नहीं होगी।
  • डाइजेस्ट ऐरे में बाइट वैल्यू 0-255 होगी, यदि आप अन्य रेंज चाहते हैं, तो आपको उन पर कुछ गणित करना होगा।
  • यदि आप अलग-अलग 'यादृच्छिक' परिणाम चाहते हैं, तो आप कुछ प्रकार के 'बीज' जोड़ सकते हैं। उदाहरण के लिए ByteBuffer.allocate (12) में परिवर्तन करें, और एक .putInt (बीज) जोड़ें।

1

दूसरों ने बताया है कि व्यवहार को प्राप्त करने का एक तरीका हैश फ़ंक्शन, उर्फ ​​"संदेश डाइजेस्ट फ़ंक्शन" का उपयोग करना है। समस्या यह है कि ये अक्सर एमडी 5 जैसे एल्गोरिदम पर आधारित होते हैं, जो क्रिप्टोग्राफिक रूप से सुरक्षित होते हैं (यानी वास्तव में, वास्तव में, वास्तव में यादृच्छिक) लेकिन बहुत धीमी गति से। यदि आप एक क्रिप्टोग्राफ़िक हैश फ़ंक्शन का उपयोग करते हैं, तो आपको हर बार एक यादृच्छिक पिक्सेल की आवश्यकता होती है जो आप काफी गंभीर प्रदर्शन समस्याओं में भाग लेंगे।

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


1

मैं 2000 से अधिक प्राइम का उपयोग करूँगा (अधिकतम विशिष्ट रिज़ॉल्यूशन)
यह डुप्लिकेट बीजों को कम करेगा (या खत्म करेगा)

public class Generate {

    static Random Random;

    public static int TileColor(int x, int y){          
        Random = new Random(x + 2213 * y);
        int b = 1 + Random.nextInt(50);
        int g = 1 + Random.nextInt(50);
        int r = 1 + Random.nextInt(50);
        int color = -Color.rgb888(r, g, b);
        return color;
    }
}

0

Randomपर्याप्त यादृच्छिक है। आप इसे दो मुख्य कारणों से गलत उपयोग कर रहे हैं।

  • यह बार-बार पुन: सींचे जाने के लिए नहीं बनाया गया था। यादृच्छिक गुण केवल यादृच्छिक संख्याओं के एकल अनुक्रम के लिए धारण करते हैं।
  • Integer.valueOf(Integer.toString(x)+Integer.toString(y))आपके बीच बोने वाले पिक्सेल के बीच बहुत बड़ा संबंध है ।

मैं सिर्फ निम्नलिखित कोड की कुछ भिन्नता का उपयोग करूंगा, जहां आप /programming/9624963/java-simplest-integer- पर उत्तरों से एक हैश फ़ंक्शन (इंटेगर.गेटशॉड का उपयोग न करें) कर सकते हैं। हैश

public static int TileColor(int x, int y) {
    return hash(x ^ hash(y));
}

जहाँ हैश फ़ंक्शन हो सकता है


0

आप इस तरह से बीज के रूप में मौजूदा घड़ी समय का उपयोग कर सिस्टम की कोशिश कर सकते हैं:

Random random = new Random(System.currentTimeMillis())

उम्मीद है कि यह एक अधिक यादृच्छिक मूल्य पैदा करता है।


हालांकि, डेम कोऑर्डिनेट करने के लिए डेम मूल्य नहीं बनता है, हालांकि।
ड्रैगनफ्लाई

0

यहाँ एक लाइन स्टैटिक शेडर फंक्शन है जिसे मैं लेकर आया था - पॉलीगेटिस्ट (नॉइज़ घोस्ट)।

यह एक 2 डी समन्वय और एक बीज लेता है, और अनुरोध के अनुसार मोनोटोन में रेंडर करता है। यह स्क्रीन रिज़ॉल्यूशन की परवाह किए बिना रीयलटाइम एफपीएस पर चलता है। यह वही है जो GPU के लिए है।

// poltergeist (noisy ghost) pseudo-random noise generator function
// dominic.cerisano@standard3d.com 03/24/2015

precision highp float;

float poltergeist(in vec2 coordinate, in float seed) 
{
    return fract(sin(dot(coordinate*seed, vec2(12.9898, 78.233)))*43758.5453); 
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) 
{   
    fragColor = vec4(poltergeist(fragCoord, iGlobalTime)); 
}

जीएल का समर्थन करने वाले किसी भी उपकरण (मोबाइल पर भी) पर कोई भी रिज़ॉल्यूशन, कोई बनावट, (जो स्क्रीन के साथ बहुत अधिक है)।

इसे यहीं पर चलते हुए देखें!

https://www.shadertoy.com/view/ltB3zD

आप इस shader को आसानी से मानक opengl, या मानक webgl का उपयोग करके किसी भी ब्राउज़र में अपने जावा प्रोग्राम में शामिल कर सकते हैं।

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

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