छवि में पिक्सेल पुनर्व्यवस्थित करें ताकि इसे पहचाना न जा सके और फिर इसे वापस लाया जा सके


86

एक ऐसा प्रोग्राम बनाएं जो छवि में पिक्सेल को पुनर्व्यवस्थित कर सके इसलिए इसे पहचाना नहीं जा सकता है। हालाँकि आपका कार्यक्रम इसे मूल छवि में बदलने में सक्षम होना चाहिए।

आप दो फ़ंक्शन लिख सकते हैं - एन्कोडिंग और डिकोडिंग के लिए, हालांकि एक फ़ंक्शन जो बार-बार लागू होता है वह मूल छवि देता है (उदाहरण के लिए गणित - f(x) = 1 - x ) एक बोनस है।

आउटपुट में कुछ पैटर्न का उत्पादन भी बोनस देता है।

यदि आपकी भाषा इसका समर्थन करती है तो छवि को 1D / 2D सरणी या छवि ऑब्जेक्ट के रूप में दर्शाया जा सकता है। ध्यान दें कि आप केवल पिक्सेल का क्रम बदल सकते हैं!

विजेता कोड के रूप में चयन करने के लिए तार्किक होगा जो कम पहचानने योग्य छवि का उत्पादन करता है, हालांकि मुझे नहीं पता कि इसे बिल्कुल कैसे मापना है, सभी तरीकों से मैं कल्पना कर सकता हूं कि धोखा दिया जा सकता है। इसलिए मैंने इस सवाल को लोकप्रियता प्रतियोगिता के लिए चुना - उपयोगकर्ताओं को सबसे अच्छा जवाब चुनने दें!

टेस्ट इमेज 1 (800 x 422 px): टेस्ट इमेज 2 (800 x 480 px): कृपया कोड आउटपुट इमेज प्रदान करें।


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

3
@DavidRicherby ... जो समान पिक्सेल / रंगों का उपयोग करता है। "सादे छवि" में पांच काले पिक्सेल -> "सिफर छवि" में पांच काले पिक्सेल।
डैनियल बेक

2
@ user2992539 ठीक है, उस स्थिति में आप स्पष्ट रूप से यह बताना चाहेंगे कि इसका उपयोग टाई-ब्रेकर के रूप में किया जाता है। अन्यथा, सिर्फ यह कहना कि यह बोनस बहुत सार्थक नहीं है।
मार्टिन एंडर

3
इस सवाल ने मुझे अर्नोल्ड के बिल्ली के नक्शे के बारे में सोचा । मुझे नहीं लगता कि यह इस उद्देश्य के लिए काफी उपयुक्त है, लेकिन यह उसी तरह से दिलचस्प है - मानचित्र को पर्याप्त बार दोहराने से आपको मूल छवि वापस मिल जाती है।
ट्राइकोप्लाक्स

4
अब कहीं और स्टैक एक्सचेंज नेटवर्क पर: Security.SE सभी स्थानों के
दरवाज़े

जवाबों:


58

पायथन 2.7 (पीआईएल के साथ) - कोई छद्म आयामीता नहीं

मैं छवि को 2 में 2 ब्लॉक (शेष को अनदेखा करता हूं) को तोड़ता हूं और प्रत्येक ब्लॉक को 180 डिग्री से घुमाता हूं, फिर मैं 3 के साथ 3 ब्लॉक करता हूं, फिर 4, कुछ पैरामीटर BLKSZ तक। फिर मैं BLKSZ-1 के लिए भी ऐसा ही करता हूं, फिर BLKSZ-2, सभी तरह से नीचे 3 पर वापस जाता है, फिर 2. यह विधि खुद को बिल्कुल उलट देती है; अनचाहा फ़ंक्शन स्क्रैम्बल फ़ंक्शन है।

कोड :

from PIL import Image
import math

im = Image.open("ST1.png", "r")
arr = im.load() #pixel data stored in this 2D array

def rot(A, n, x1, y1): #this is the function which rotates a given block
    temple = []
    for i in range(n):
        temple.append([])
        for j in range(n):
            temple[i].append(arr[x1+i, y1+j])
    for i in range(n):
        for j in range(n):
            arr[x1+i,y1+j] = temple[n-1-i][n-1-j]


xres = 800
yres = 480
BLKSZ = 50 #blocksize
for i in range(2, BLKSZ+1):
    for j in range(int(math.floor(float(xres)/float(i)))):
        for k in range(int(math.floor(float(yres)/float(i)))):
            rot(arr, i, j*i, k*i)
for i in range(3, BLKSZ+1):
    for j in range(int(math.floor(float(xres)/float(BLKSZ+2-i)))):
        for k in range(int(math.floor(float(yres)/float(BLKSZ+2-i)))):
            rot(arr, BLKSZ+2-i, j*(BLKSZ+2-i), k*(BLKSZ+2-i))

im.save("ST1OUT "+str(BLKSZ)+".png")

print("Done!")

रुकावट के आधार पर, आप मूल छवि से सभी समानता को मिटा सकते हैं: यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें

या अभिकलन को कुशल बनाएं: (BLKSZ = 10) यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें


6
सबसे अच्छा परिणाम की तरह ध्वनि अगर BLKSZ छवि आकार का लगभग आधा होगा। वैसे भी, मुझे एल्गोरिथ्म पसंद है और छोटे BLKSZ के लिए यह एक आधुनिक कला की तरह दिखता है! ठंडा!
सोमनियम

11
मैं हमेशा अजगर को पालता हूं।
qwr

2 से 50 तक के सभी मूल्यों के लिए पांव मारने के बजाय, शायद आपको केवल प्राइम नंबर का उपयोग करना चाहिए?
नील

@ नील शायद तब यह अधिक यादृच्छिक और कम कलात्मक लगेगा।
सोमनियम

BLKSZ = 10परिदृश्य बहुत अच्छा है!
wchargin

52

C #, Winform

जिस तरह से आप निर्देशांक सरणी भरते हैं उसे बदलते हुए संपादित करें आपके पास विभिन्न पैटर्न हो सकते हैं - नीचे देखें

क्या आपको इस तरह का पैटर्न पसंद है?

परिदृश्य

सार

बोनस:

चीख चीख पुकार मच गई

रैंडम स्वैप ठीक एक समय में सभी पिक्सेल ऊपरी आधे में सभी पिक्सेल निचले आधे हिस्से में होते हैं। अप्रतिबंधित (बोनस) के लिए एक ही प्रक्रिया दोहराएं।

कोड

Scramble.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;

namespace Palette
{
    public partial class Scramble : Form
    {
        public Scramble()
        {
            InitializeComponent();
        }

        public struct Coord
        {
            public int x, y;
        }

        private void Work(Bitmap srcb, Bitmap outb)
        {
            int w = srcb.Width, h = srcb.Height;
            Coord[] coord = new Coord[w * h];

            FastBitmap fsb = new FastBitmap(srcb);
            FastBitmap fob = new FastBitmap(outb);
            fsb.LockImage();
            fob.LockImage();
            ulong seed = 0;
            int numpix = 0;
            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; numpix++, x++)
                {
                    coord[numpix].x = x;
                    coord[numpix].y = y;
                    uint color = fsb.GetPixel(x, y);
                    seed += color;
                    fob.SetPixel(x, y, color);
                }
            fsb.UnlockImage();
            fob.UnlockImage();
            pbOutput.Refresh();
            Application.DoEvents();

            int half = numpix / 2;
            int limit = half;
            XorShift rng = new XorShift(seed);
            progressBar.Visible = true;
            progressBar.Maximum = limit;

            fob.LockImage();
            while (limit > 0)
            {
                int p = (int)(rng.next() % (uint)limit);
                int q = (int)(rng.next() % (uint)limit);
                uint color = fob.GetPixel(coord[p].x, coord[p].y); 
                fob.SetPixel(coord[p].x, coord[p].y, fob.GetPixel(coord[half+q].x, coord[half+q].y)); 
                fob.SetPixel(coord[half+q].x, coord[half+q].y, color); 
                limit--;
                if (p < limit)
                {
                    coord[p]=coord[limit];
                }
                if (q < limit)
                {
                    coord[half+q]=coord[half+limit];
                }
                if ((limit & 0xfff) == 0)
                {
                    progressBar.Value = limit;
                    fob.UnlockImage();
                    pbOutput.Refresh();
                    fob.LockImage();
                }
            }
            fob.UnlockImage();
            pbOutput.Refresh();
            progressBar.Visible = false; 
        }

        void DupImage(PictureBox s, PictureBox d)
        {
            if (d.Image != null)
                d.Image.Dispose();
            d.Image = new Bitmap(s.Image.Width, s.Image.Height);  
        }

        void GetImagePB(PictureBox pb, string file)
        {
            Bitmap bms = new Bitmap(file, false);
            Bitmap bmp = bms.Clone(new Rectangle(0, 0, bms.Width, bms.Height), PixelFormat.Format32bppArgb);
            bms.Dispose(); 
            if (pb.Image != null)
                pb.Image.Dispose();
            pb.Image = bmp;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.InitialDirectory = "c:\\temp\\";
            openFileDialog.Filter = "Image Files(*.BMP;*.JPG;*.PNG)|*.BMP;*.JPG;*.PNG|All files (*.*)|*.*";
            openFileDialog.FilterIndex = 1;
            openFileDialog.RestoreDirectory = true;

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string file = openFileDialog.FileName;
                    GetImagePB(pbInput, file);
                    pbInput.Tag = file;
                    DupImage(pbInput, pbOutput);
                    Work(pbInput.Image as Bitmap, pbOutput.Image as Bitmap);
                    file = Path.GetDirectoryName(file) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + ".scr.png";
                    pbOutput.Image.Save(file);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }

            }
        }
    }

    //Adapted from Visual C# Kicks - http://www.vcskicks.com/
    unsafe public class FastBitmap
    {
        private Bitmap workingBitmap = null;
        private int width = 0;
        private BitmapData bitmapData = null;
        private Byte* pBase = null;

        public FastBitmap(Bitmap inputBitmap)
        {
            workingBitmap = inputBitmap;
        }

        public BitmapData LockImage()
        {
            Rectangle bounds = new Rectangle(Point.Empty, workingBitmap.Size);

            width = (int)(bounds.Width * 4 + 3) & ~3;

            //Lock Image
            bitmapData = workingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            pBase = (Byte*)bitmapData.Scan0.ToPointer();
            return bitmapData;
        }

        private uint* pixelData = null;

        public uint GetPixel(int x, int y)
        {
            pixelData = (uint*)(pBase + y * width + x * 4);
            return *pixelData;
        }

        public uint GetNextPixel()
        {
            return *++pixelData;
        }

        public void GetPixelArray(int x, int y, uint[] Values, int offset, int count)
        {
            pixelData = (uint*)(pBase + y * width + x * 4);
            while (count-- > 0)
            {
                Values[offset++] = *pixelData++;
            }
        }

        public void SetPixel(int x, int y, uint color)
        {
            pixelData = (uint*)(pBase + y * width + x * 4);
            *pixelData = color;
        }

        public void SetNextPixel(uint color)
        {
            *++pixelData = color;
        }

        public void UnlockImage()
        {
            workingBitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
        }
    }

    public class XorShift
    {
        private ulong x; /* The state must be seeded with a nonzero value. */

        public XorShift(ulong seed)
        {
            x = seed;
        }

        public ulong next()
        {
            x ^= x >> 12; // a
            x ^= x << 25; // b
            x ^= x >> 27; // c
            return x * 2685821657736338717L;
        }
    }
} 

Scramble.designer.cs

namespace Palette
{
    partial class Scramble
    {
        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.panel = new System.Windows.Forms.FlowLayoutPanel();
            this.pbInput = new System.Windows.Forms.PictureBox();
            this.pbOutput = new System.Windows.Forms.PictureBox();
            this.progressBar = new System.Windows.Forms.ProgressBar();
            this.btnOpen = new System.Windows.Forms.Button();
            this.panel.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbInput)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbOutput)).BeginInit();
            this.SuspendLayout();
            // 
            // panel
            // 
            this.panel.AutoScroll = true;
            this.panel.AutoSize = true;
            this.panel.Controls.Add(this.pbInput);
            this.panel.Controls.Add(this.pbOutput);
            this.panel.Dock = System.Windows.Forms.DockStyle.Top;
            this.panel.Location = new System.Drawing.Point(0, 0);
            this.panel.Name = "panel";
            this.panel.Size = new System.Drawing.Size(748, 306);
            this.panel.TabIndex = 3;
            // 
            // pbInput
            // 
            this.pbInput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pbInput.Location = new System.Drawing.Point(3, 3);
            this.pbInput.MinimumSize = new System.Drawing.Size(100, 100);
            this.pbInput.Name = "pbInput";
            this.pbInput.Size = new System.Drawing.Size(100, 300);
            this.pbInput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.pbInput.TabIndex = 3;
            this.pbInput.TabStop = false;
            // 
            // pbOutput
            // 
            this.pbOutput.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pbOutput.Location = new System.Drawing.Point(109, 3);
            this.pbOutput.MinimumSize = new System.Drawing.Size(100, 100);
            this.pbOutput.Name = "pbOutput";
            this.pbOutput.Size = new System.Drawing.Size(100, 300);
            this.pbOutput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.pbOutput.TabIndex = 4;
            this.pbOutput.TabStop = false;
            // 
            // progressBar
            // 
            this.progressBar.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.progressBar.Location = new System.Drawing.Point(0, 465);
            this.progressBar.Name = "progressBar";
            this.progressBar.Size = new System.Drawing.Size(748, 16);
            this.progressBar.TabIndex = 5;
            // 
            // btnOpen
            // 
            this.btnOpen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.btnOpen.Location = new System.Drawing.Point(12, 429);
            this.btnOpen.Name = "btnOpen";
            this.btnOpen.Size = new System.Drawing.Size(53, 30);
            this.btnOpen.TabIndex = 6;
            this.btnOpen.Text = "Start";
            this.btnOpen.UseVisualStyleBackColor = true;
            this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
            // 
            // Scramble
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.ControlDark;
            this.ClientSize = new System.Drawing.Size(748, 481);
            this.Controls.Add(this.btnOpen);
            this.Controls.Add(this.progressBar);
            this.Controls.Add(this.panel);
            this.Name = "Scramble";
            this.Text = "Form1";
            this.panel.ResumeLayout(false);
            this.panel.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbInput)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pbOutput)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }


        private System.Windows.Forms.FlowLayoutPanel panel;
        private System.Windows.Forms.PictureBox pbOutput;
        private System.Windows.Forms.ProgressBar progressBar;
        private System.Windows.Forms.PictureBox pbInput;
        private System.Windows.Forms.Button btnOpen;
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Palette
{
  static class Program
  {
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Scramble());
    }
  }
}

संकलन करने के लिए प्रोजेक्ट संपत्ति में 'असुरक्षित कोड' की जाँच करें।

जटिल पैटर्न

संघर्ष

अनुप्रयोग कार्य के पहले भाग को बदलें।

        int w = srcb.Width, h = srcb.Height;
        string Msg = "Scramble";

        Graphics gr = Graphics.FromImage(outb);

        Font f = new Font("Arial", 100, FontStyle.Bold);
        var size = gr.MeasureString(Msg, f);
        f = new Font("Arial", w / size.Width * 110, FontStyle.Bold);
        size = gr.MeasureString(Msg, f);
        gr.DrawString(Msg, f, new SolidBrush(Color.White), (w - size.Width) / 2, (h - size.Height) / 2);

        gr.Dispose();

        Coord[] coord = new Coord[w * h];
        FastBitmap fsb = new FastBitmap(srcb);
        FastBitmap fob = new FastBitmap(outb);
        fsb.LockImage();
        fob.LockImage();
        ulong seed = 1;
        int numpix = h * w;
        int c1 = 0, c2 = numpix;
        int y2 = h / 2;

        int p2 = numpix/2;

        for (int p = 0; p < p2; p++)
        {
            for (int s = 1; s > -2; s -= 2)
            {
                int y = (p2+s*p) / w;
                int x = (p2+s*p) % w;

                uint d = fob.GetPixel(x, y);
                if (d != 0)
                {
                    c2--;
                    coord[c2].x = x;
                    coord[c2].y = y;
                }
                else
                {
                    coord[c1].x = x;
                    coord[c1].y = y;
                    c1++;
                }
                fob.SetPixel(x, y, fsb.GetPixel(x, y));
            }
        }
        fsb.UnlockImage();
        fob.UnlockImage();
        pbOutput.Refresh();
        Application.DoEvents();

1
दिलचस्प) मैं सोच रहा हूँ कि क्या इसी तरह के दृष्टिकोण से आउटपुट में अधिक जटिल पैटर्न बनाना संभव है।
सोमनियम

1
अच्छा विचार - जब विषम संख्या में रेखाएँ होती हैं तो मध्य रेखा का क्या होता है?
दोष

1
@flawr विभाजन प्रति पिक्सेल है। यदि पिक्सेल की एक विषम संख्या है, तो अंतिम को अछूता छोड़ दिया जाता है। यदि विषम संख्या में पंक्तियाँ हैं, तो मध्य पंक्ति का बायाँ भाग 'ऊपरी ओर' है और दाएँ आधा 'निचला पक्ष' है।
edc65

1
@ user2992539 मुझे लगता है कि आप और भी अधिक कर सकते हैं - यहां तक ​​कि चेकरबोर्ड। अधिक उपखंडों के साथ, छवि अधिक पहचानने योग्य है।
edc65

7
अपने "हाथापाई" संस्करण की तरह!)
सोमनील

43

सी, मनमाना धुंधला, आसानी से प्रतिवर्ती

पार्टी के लिए देर से। यहाँ मेरा प्रवेश है!

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

यह पुनरावृत्तियों की एक नकारात्मक संख्या निर्दिष्ट करके प्रतिवर्ती है (यह केवल एक कमांड-लाइन इंटरफ़ेस सुविधा है; वास्तव में नकारात्मक पुनरावृत्तियों जैसी कोई चीज नहीं है)। आंतरिक रूप से, यह एक कस्टम 64-बिट LCPRNG (रैखिक congruential छद्म आयामी संख्या जनरेटर) का उपयोग करता है और मूल्यों के एक ब्लॉक को पूर्व उत्पन्न करता है। तालिका ब्लॉक के माध्यम से लूपिंग की अनुमति देती है, जो क्रमशः स्क्रैचिंग या अनस्क्रिमिंग के लिए आगे या पीछे होती है।

डेमो

पहली दो छवियों के लिए, जैसा कि आप नीचे स्क्रॉल करते हैं, प्रत्येक छवि एक उच्च अधिकतम ऑफसेट का उपयोग करके धुंधला हो जाती है: सबसे ऊपर की मूल छवि है (जैसे, 0-पिक्सेल ऑफसेट), इसके बाद 1, 2, 4, 8, 16, 32, 64 , 128, और अंत में 256। नीचे की सभी छवियों के लिए पुनरावृत्ति गणना 10। = 1,000,000 है।

दूसरी दो छवियों के लिए, प्रत्येक छवि को उत्तरोत्तर उपयोग करके धुंधला किया जाता है कम ऑफसेट - उदाहरण के लिए, सबसे धुंधली कम से कम धुंधली - अधिकतम 256 से 0. ऑफसेट तक आनंद लें!

परिदृश्य सार

और इन अगली दो छवियों के लिए, आप यहां और यहां पूर्ण-प्रगति देख सकते हैं :

ब्रेकिंग बैड सिम्पसंस

कोड

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

//=============================================================================
// SCRAMBLUR
//
// This program is a image-processing competition entry which scrambles or
// descrambles an image based on a pseudorandom process.  For more details,
// information, see:
//
//    http://codegolf.stackexchange.com/questions/35005
//
// It is assumed that you have the NETPBM package of image-processing tools
// installed on your system.  This can be obtained from:
//
//    http://netpbm.sourceforge.net/
//
// or by using your system's package manager, e.g., yum, apt-get, port, etc.
//
// Input to the program is a 24-bit PNM image (type "P6").  Output is same.
// Example command-line invocation:
//
// pngtopnm original.png  | scramblur 100  1000000 | pnmtopng >scrambled.png
// pngtopnm scrambled.png | scramblur 100 -1000000 | pnmtopng >recovered.png
//
//
// Todd S. Lehman, July 2014

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

typedef uint8_t uint8;
typedef uint64_t uint64;

//-----------------------------------------------------------------------------
// PIXEL STRUCTURE

#pragma pack(push, 1)
typedef struct
{
  uint8 r, g, b;     // Red, green, and blue color components
}
Pixel;
#pragma pack(pop)

//-----------------------------------------------------------------------------
// IMAGE STRUCTURE

typedef struct
{
  int width;          // Width of image in pixels
  int height;         // Height of image in pixels
  int pixel_count;    // Total number of pixels in image (e.g., width * height)
  int maxval;         // Maximum pixel component value (e.g., 255)
  Pixel *data;        // One-dimensional array of pixels
}
Image;

//-----------------------------------------------------------------------------
// 64-BIT LCG TABLE

static const long lcg64_table_length = 1000000;  // 10⁶ entries => 8 Megabytes

static uint64 lcg64_table[lcg64_table_length];

//-----------------------------------------------------------------------------
// GET 64-BIT LCG VALUE FROM TABLE

uint64 lcg64_get(long const iteration)
{
  return lcg64_table[iteration % lcg64_table_length];
}

//-----------------------------------------------------------------------------
// INITIALIZE 64-BIT LCG TABLE

void lcg64_init(uint64 const seed)
{
  uint64 x = seed;
  for (long iteration = 0; iteration < lcg64_table_length; iteration++)
  {
    uint64 const a = UINT64_C(6364136223846793005);
    uint64 const c = UINT64_C(1442695040888963407);
    x = (x * a) + c;
    lcg64_table[iteration] = x;
  }
}

//-----------------------------------------------------------------------------
// READ BINARY PNM IMAGE

Image image_read(FILE *const file)
{
  Image image = { .data = NULL };

  char *line = NULL;
  size_t linecap = 0;

  // Read image type.  (Currently only P6 is supported here.)
  if (getline(&line, &linecap, file) < 0) goto failure;
  if (strcmp(line, "P6\n") != 0) goto failure;

  // Read width and height of image in pixels.
  {
    if (getline(&line, &linecap, file) < 0) goto failure;
    char *pwidth = &line[0];
    char *pheight = strchr(line, ' ');
    if (pheight != NULL) pheight++; else goto failure;
    image.width = atoi(pwidth);
    image.height = atoi(pheight);
    image.pixel_count = image.width * image.height;
  }

  // Read maximum color value.  (Currently only 255 is supported here.)
  {
    if (getline(&line, &linecap, file) < 0) goto failure;
    image.maxval = atoi(line);
    if (image.maxval != 255)
      goto failure;
  }

  // Allocate image buffer and read image data.
  if (!(image.data = calloc(image.pixel_count, sizeof(Pixel))))
    goto failure;

  if (fread(image.data, sizeof(Pixel), image.pixel_count, file) !=
      image.pixel_count)
    goto failure;

success:
  free(line);
  return image;

failure:
  free(line);
  free(image.data); image.data = NULL;
  return image;
}

//-----------------------------------------------------------------------------
// WRITE BINARY PNM IMAGE

void image_write(const Image image, FILE *const file)
{
  printf("P6\n");
  printf("%d %d\n", image.width, image.height);
  printf("%d\n", image.maxval);
  (void)fwrite(image.data, sizeof(Pixel), image.pixel_count, file);
}

//-----------------------------------------------------------------------------
// DISCARD IMAGE

void image_discard(Image image)
{
  free(image.data);
}

//-----------------------------------------------------------------------------
// SCRAMBLE OR UNSCRAMBLE IMAGE

void image_scramble(Image image,
                    int const max_delta,
                    long const iterations,
                    uint64 const lcg64_seed)
{
  if (max_delta == 0) return;

  int neighborhood1 = (2 * max_delta) + 1;
  int neighborhood2 = neighborhood1 * neighborhood1;

  lcg64_init(lcg64_seed);

  long iteration_start = (iterations >= 0)? 0 : -iterations;
  long iteration_end   = (iterations >= 0)? iterations : 0;
  long iteration_inc   = (iterations >= 0)? 1 : -1;

  for (long iteration = iteration_start;
       iteration != iteration_end;
       iteration += iteration_inc)
  {
    uint64 lcg64 = lcg64_get(iteration);

    // Choose random pixel.
    int pixel_index = (int)((lcg64 >> 0) % image.pixel_count);

    // Choose random pixel in the neighborhood.
    int d2 = (int)((lcg64 >> 8) % neighborhood2);
    int dx = (d2 % neighborhood1) - (neighborhood1 / 2);
    int dy = (d2 / neighborhood1) - (neighborhood1 / 2);
    int other_pixel_index = pixel_index + dx + (dy * image.width);
    while (other_pixel_index < 0)
      other_pixel_index += image.pixel_count;
    other_pixel_index %= image.pixel_count;

    // Swap pixels.
    Pixel t = image.data[pixel_index];
    image.data[pixel_index] = image.data[other_pixel_index];
    image.data[other_pixel_index] = t;
  }
}

//-----------------------------------------------------------------------------
int main(const int argc, char const *const argv[])
{
  int max_delta     = (argc > 1)? atoi(argv[1]) : 1;
  long iterations   = (argc > 2)? atol(argv[2]) : 1000000;
  uint64 lcg64_seed = (argc > 3)? (uint64)strtoull(argv[3], NULL, 10) : 0;

  Image image = image_read(stdin);
  if (!image.data) { fprintf(stderr, "Invalid input\n"), exit(1); }

  image_scramble(image, max_delta, iterations, lcg64_seed);

  image_write(image, stdout);

  image_discard(image);

  return 0;
}

4
बस इस जवाब को पिछले स्क्रॉल, भयानक लग रहा है
थॉमस

1
यह उत्तर वास्तव में लंबा है। क्या आपको लगता है कि आप अतिरिक्त छवियों को स्थानांतरित कर सकते हैं (यानी दो परीक्षण छवियों को छोड़कर सब कुछ, पूरी तरह से धुंधला हो जाना) एक ऑफ-साइट गैलरी के लिए?
टिम एस।

@TimS। - किया हुआ! छोटे थंबनेल के लिए उन्हें नीचे सिकोड़ें।
टॉड लेहमैन

42

अजगर 3.4

  • बोनस 1: स्व उलटा: दोहराता मूल छवि को पुनर्स्थापित करता है।
  • वैकल्पिक कुंजी छवि: मूल छवि को केवल उसी कुंजी छवि का उपयोग करके फिर से बहाल किया जा सकता है।
  • बोनस 2: आउटपुट में पैटर्न का निर्माण: मुख्य छवि तले हुए पिक्सेल में अनुमानित होती है।

जब एक अतिरिक्त कुंजी छवि का उपयोग करके बोनस 2 प्राप्त किया जाता है, तो बोनस 1 खो नहीं जाता है। यह कार्यक्रम अभी भी उलटा है, बशर्ते इसे फिर से उसी महत्वपूर्ण छवि के साथ चलाया जाए।

मानक उपयोग

टेस्ट छवि 1:

तले हुए परीक्षण छवि 1

परीक्षण छवि 2:

तले हुए चित्र 2

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

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

2-चक्र का सुझाव देने वाले पहले व्यक्ति के रूप में mfvonh के उत्तर के लिए धन्यवाद ।

एक प्रमुख छवि के साथ उपयोग

प्रमुख छवि के रूप में टेस्ट छवि 2 के साथ स्क्रैच टेस्ट छवि 1

परीक्षा 2 के साथ हाथापाई परीक्षण 1

मुख्य छवि के रूप में टेस्ट छवि 1 के साथ स्क्रैच टेस्ट छवि 2

1 परीक्षण के साथ हाथापाई परीक्षण 2

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

रनिंग फिर से प्रत्येक क्षेत्र में पिक्सल के एक ही जोड़े को स्वैप करता है, इसलिए प्रत्येक क्षेत्र अपनी मूल स्थिति में बहाल हो जाता है, और छवि पूरी तरह से दिखाई देती है।

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

कोड

import os.path
from PIL import Image   # Uses Pillow, a fork of PIL for Python 3
from random import randrange, seed


def scramble(input_image_filename, key_image_filename=None,
             number_of_regions=16777216):
    input_image_path = os.path.abspath(input_image_filename)
    input_image = Image.open(input_image_path)
    if input_image.size == (1, 1):
        raise ValueError("input image must contain more than 1 pixel")
    number_of_regions = min(int(number_of_regions),
                            number_of_colours(input_image))
    if key_image_filename:
        key_image_path = os.path.abspath(key_image_filename)
        key_image = Image.open(key_image_path)
    else:
        key_image = None
        number_of_regions = 1
    region_lists = create_region_lists(input_image, key_image,
                                       number_of_regions)
    seed(0)
    shuffle(region_lists)
    output_image = swap_pixels(input_image, region_lists)
    save_output_image(output_image, input_image_path)


def number_of_colours(image):
    return len(set(list(image.getdata())))


def create_region_lists(input_image, key_image, number_of_regions):
    template = create_template(input_image, key_image, number_of_regions)
    number_of_regions_created = len(set(template))
    region_lists = [[] for i in range(number_of_regions_created)]
    for i in range(len(template)):
        region = template[i]
        region_lists[region].append(i)
    odd_region_lists = [region_list for region_list in region_lists
                        if len(region_list) % 2]
    for i in range(len(odd_region_lists) - 1):
        odd_region_lists[i].append(odd_region_lists[i + 1].pop())
    return region_lists


def create_template(input_image, key_image, number_of_regions):
    if number_of_regions == 1:
        width, height = input_image.size
        return [0] * (width * height)
    else:
        resized_key_image = key_image.resize(input_image.size, Image.NEAREST)
        pixels = list(resized_key_image.getdata())
        pixel_measures = [measure(pixel) for pixel in pixels]
        distinct_values = list(set(pixel_measures))
        number_of_distinct_values = len(distinct_values)
        number_of_regions_created = min(number_of_regions,
                                        number_of_distinct_values)
        sorted_distinct_values = sorted(distinct_values)
        while True:
            values_per_region = (number_of_distinct_values /
                                 number_of_regions_created)
            value_to_region = {sorted_distinct_values[i]:
                               int(i // values_per_region)
                               for i in range(len(sorted_distinct_values))}
            pixel_regions = [value_to_region[pixel_measure]
                             for pixel_measure in pixel_measures]
            if no_small_pixel_regions(pixel_regions,
                                      number_of_regions_created):
                break
            else:
                number_of_regions_created //= 2
        return pixel_regions


def no_small_pixel_regions(pixel_regions, number_of_regions_created):
    counts = [0 for i in range(number_of_regions_created)]
    for value in pixel_regions:
        counts[value] += 1
    if all(counts[i] >= 256 for i in range(number_of_regions_created)):
        return True


def shuffle(region_lists):
    for region_list in region_lists:
        length = len(region_list)
        for i in range(length):
            j = randrange(length)
            region_list[i], region_list[j] = region_list[j], region_list[i]


def measure(pixel):
    '''Return a single value roughly measuring the brightness.

    Not intended as an accurate measure, simply uses primes to prevent two
    different colours from having the same measure, so that an image with
    different colours of similar brightness will still be divided into
    regions.
    '''
    if type(pixel) is int:
        return pixel
    else:
        r, g, b = pixel[:3]
        return r * 2999 + g * 5869 + b * 1151


def swap_pixels(input_image, region_lists):
    pixels = list(input_image.getdata())
    for region in region_lists:
        for i in range(0, len(region) - 1, 2):
            pixels[region[i]], pixels[region[i+1]] = (pixels[region[i+1]],
                                                      pixels[region[i]])
    scrambled_image = Image.new(input_image.mode, input_image.size)
    scrambled_image.putdata(pixels)
    return scrambled_image


def save_output_image(output_image, full_path):
    head, tail = os.path.split(full_path)
    if tail[:10] == 'scrambled_':
        augmented_tail = 'rescued_' + tail[10:]
    else:
        augmented_tail = 'scrambled_' + tail
    save_filename = os.path.join(head, augmented_tail)
    output_image.save(save_filename)


if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if arguments:
        scramble(*arguments[:3])
    else:
        print('\n'
              'Arguments:\n'
              '    input image          (required)\n'
              '    key image            (optional, default None)\n'
              '    number of regions    '
              '(optional maximum - will be as high as practical otherwise)\n')

जेपीईजी छवि जला

.jpg फाइलें बहुत जल्दी संसाधित हो जाती हैं, लेकिन बहुत गर्म चलाने की लागत पर। जब मूल को बहाल किया जाता है, तो यह छवि के बाद जला दिया जाता है:

jpg बर्न

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

स्क्रैच करने से पहले .png (या किसी भी गैर-हानिपूर्ण प्रारूप) में बदलना यह सुनिश्चित करता है कि अनियंत्रित छवि बिना बर्न या विरूपण के मूल के समान है:

बिना किसी जले के साथ पींग

थोड़ा विवरण

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

2
+1 तालियाँ! मैंने अस्पष्ट रूप से इस बारे में सोचा था, लेकिन इसे लागू करना बहुत मुश्किल था।
edc65

1
ये जबरदस्त है। मुझे एक प्रविष्टि सबमिट की गई है, लेकिन मुझे आपकी मुख्य छवि की वजह से बेहतर पसंद है।
टॉड लेहमैन

मुझे उत्सुकता होगी कि ये दोनों छवियां एक दूसरे के खिलाफ किस की तरह दिखती हैं: lardlad.com/assets/wallpaper/simpsons1920.jpg और blogs.nd.edu/oblation/files/2013/09/BreakingBad.jpg (720x450 या डाउनसाइज़ किए गए) जो कुछ भी समझ में आता है, और निश्चित रूप से जेपीईजी बर्न से बचने के लिए पीएनजी में पूर्व-परिवर्तित किया गया है)।
टॉड लेहमैन

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

2
प्रमुख छवि विशेषता इस सिर और कंधों को बाकी हिस्सों से ऊपर रखती है।
जैक ऐडली

33

यहां बदलाव के लिए एक गैर-यादृच्छिक परिवर्तन है

  1. बाईं ओर सभी कॉलम और दाईं ओर सभी अजीब कॉलम रखें।
  2. बार nxबार
  3. पंक्तियों के nyसमय के लिए भी ऐसा ही करें

परिवर्तन लगभग स्व-उलटा है, परिवर्तन को दोहराते हुए कुल size_xबार (x- दिशा में) मूल छवि लौटाता है। मैंने सटीक गणित का पता नहीं लगाया, लेकिन पूर्णांक के गुणकों का उपयोग करके int(log_2(size_x))सबसे छोटी भूत चित्रों के साथ सर्वश्रेष्ठ फेरबदल का निर्माण किया

हिल गए पहाड़ यहाँ छवि विवरण दर्ज करें

from numpy import *
from pylab import imread, imsave

def imshuffle(im, nx=0, ny=0):
    for i in range(nx):
        im = concatenate((im[:,0::2], im[:,1::2]), axis=1)
    for i in range(ny):
        im = concatenate((im[0::2,:], im[1::2,:]), axis=0)
    return im

im1 = imread('circles.png')
im2 = imread('mountain.jpg')

imsave('s_circles.png', imshuffle(im1, 7,7))
imsave('s_mountain.jpg', imshuffle(im2, 8,9))

यह है कि पहले चरण 20 पुनरावृत्तियों कैसे दिखते हैं (nx = ny, विभिन्न प्रस्तावों के प्रभाव पर ध्यान दें) यहाँ छवि विवरण दर्ज करें


7
यह एक बहुत अच्छा एल्गोरिथ्म है। और आपको लीना सॉडरबर्ग की तस्वीर का उपयोग करने के लिए पूरी तरह से बोनस मिलना चाहिए। :)
टॉड लेहमैन

हमेशा लीना को

24

मेथेमेटिका

यह बहुत सीधा है। मैं 5 * nPixelsयादृच्छिक समन्वय जोड़े चुनता हूं और उन दो पिक्सल को स्वैप करता हूं (जो पूरी तरह से तस्वीर को अस्पष्ट करता है)। इसे अनसुना करने के लिए मैं इसे उल्टा करता हूं। बेशक, मुझे दोनों चरणों में समान समन्वय जोड़े प्राप्त करने के लिए PRNG को बीजने की आवश्यकता है।

scramble[image_] := Module[
   {data, h, w, temp},
   data = ImageData@image;
   {h, w} = Most@Dimensions@data;
   SeedRandom[42];
   (
      temp = data[[#[[1]], #[[2]]]];
      data[[#[[1]], #[[2]]]] = data[[#2[[1]], #2[[2]]]];
      data[[#2[[1]], #2[[2]]]] = temp;
      ) & @@@
    Partition[
     Transpose@{RandomInteger[h - 1, 10*h*w] + 1, 
       RandomInteger[w - 1, 10*h*w] + 1}, 2];
   Image@data
   ];
unscramble[image_] := Module[
   {data, h, w, temp},
   data = ImageData@image;
   {h, w} = Most@Dimensions@data;
   SeedRandom[42];
   (
      temp = data[[#[[1]], #[[2]]]];
      data[[#[[1]], #[[2]]]] = data[[#2[[1]], #2[[2]]]];
      data[[#2[[1]], #2[[2]]]] = temp;
      ) & @@@
    Reverse@
     Partition[
      Transpose@{RandomInteger[h - 1, 10*h*w] + 1, 
        RandomInteger[w - 1, 10*h*w] + 1}, 2];
   Image@data
   ];

दो कार्यों के बीच फर्क सिर्फ इतना है Reverse@में unscramble। दोनों कार्य एक वास्तविक छवि वस्तु लेते हैं। आप उन्हें निम्नानुसार उपयोग कर सकते हैं:

in = Import["D:\\Development\\CodeGolf\\image-scrambler\\circles.png"]
scr = scramble[im]
out = unscramble[scr]

outऔर inसमान हैं। यहाँ जैसा scrदिखता है वैसा है:

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


4
महान! केवल समस्या यह है कि यह स्वयं को PRNG बनाने के लिए अधिक सुरक्षित है, क्योंकि अगर कुछ समय बाद Mathematica PRNG एल्गोरिदम को बदलने की सोचता है, तो यह पुरानी एन्कोडेड छवियों को डिकोड नहीं करेगा!
सोमनियम

1
अच्छा लगा। आपको Permute और FindPermutation के साथ समान परिणाम प्राप्त करने में सक्षम होना चाहिए।
डेविड जेएल

मुझे यकीन नहीं कि मैं समझा हूँ। आप चक्रों की सूची के रूप में इच्छित सटीक क्रमांकन दर्ज कर सकते हैं।
डेविड

@DavidCarraher एचएम, दिलचस्प। क्या मुझे FindPermutationहालांकि इस्तेमाल करने के लिए मूल क्रमांकन याद नहीं रखना होगा ?
मार्टिन एंडर

या शायद कुछ के रूप में {c, a, b}[[{2, 3, 1}]] इस्तेमाल किया जा सकता है?
सोमनियम

22

सी # (+ सममित एल्गोरिथ्म के लिए बोनस)

यह एक खोजने के द्वारा काम करता है x ऐसा है कि x^2 == 1 mod (number of pixels in image), और उसके बाद से प्रत्येक पिक्सेल के सूचकांक गुणा xक्रम उसके नए स्थान खोजने के लिए। इससे आप एक ही एल्गोरिथ्म का उपयोग करके किसी छवि को देख सकते हैं और उसे हटा सकते हैं।

using System.Drawing;
using System.IO;
using System.Numerics;

namespace RearrangePixels
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var arg in args)
                ScrambleUnscramble(arg);
        }

        static void ScrambleUnscramble(string fileName)
        {
            using (var origImage = new Bitmap(fileName))
            using (var newImage = new Bitmap(origImage))
            {
                BigInteger totalPixels = origImage.Width * origImage.Height;
                BigInteger modSquare = GetSquareRootOf1(totalPixels);
                for (var x = 0; x < origImage.Width; x++)
                {
                    for (var y = 0; y < origImage.Height; y++)
                    {
                        var newNum = modSquare * GetPixelNumber(new Point(x, y), origImage.Size) % totalPixels;
                        var newPoint = GetPoint(newNum, origImage.Size);
                        newImage.SetPixel(newPoint.X, newPoint.Y, origImage.GetPixel(x, y));
                    }
                }
                newImage.Save("scrambled-" + Path.GetFileName(fileName));
            }
        }

        static BigInteger GetPixelNumber(Point point, Size totalSize)
        {
            return totalSize.Width * point.Y + point.X;
        }

        static Point GetPoint(BigInteger pixelNumber, Size totalSize)
        {
            return new Point((int)(pixelNumber % totalSize.Width), (int)(pixelNumber / totalSize.Width));
        }

        static BigInteger GetSquareRootOf1(BigInteger modulo)
        {
            for (var i = (BigInteger)2; i < modulo - 1; i++)
            {
                if ((i * i) % modulo == 1)
                    return i;
            }
            return modulo - 1;
        }
    }
}

पहले परीक्षण छवि, तले हुए

दूसरा परीक्षण छवि, तले हुए


1
चतुर एक) क्या हमेशा उस अनुरूप समीकरण का समाधान होगा?
सोमनियम

1
@ user2992539 हमेशा तुच्छ समाधान होंगे, 1(मूल छवि) और modulo-1(उल्टा / उलट छवि)। अधिकांश संख्याओं में गैर-तुच्छ समाधान होते हैं, लेकिन कुछ अपवाद हैं, ऐसा लगता है । (प्रधान गुणनखंड से संबंधित modulo)
टिम एस।

जैसा कि मैं समझता हूं कि तुच्छ समाधान इनपुट एक के समान छवि का नेतृत्व करते हैं।
सोमनि जूल 25'14

सही: 1मूल छवि को आउटपुट करता है, और -1आउटपुट जैसे imgur.com/EiE6VW2
टिम एस।

19

सी #, आत्म-विलोम, कोई यादृच्छिकता नहीं

यदि मूल छवि में आयाम हैं जो दो की शक्तियां हैं, तो प्रत्येक पंक्ति और स्तंभ का उस पंक्ति और स्तंभ के साथ आदान-प्रदान होता है, जिसका उलटा बिट पैटर्न होता है, उदाहरण के लिए चौड़ाई 256 की छवि के लिए तो पंक्ति 0xB4 पंक्ति 0x2D के साथ बदली जाती है। अन्य आकारों की छवियों को 2 की शक्तियों के पक्षों के साथ आयतों में विभाजित किया गया है।

namespace CodeGolf
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var arg in args)
                Scramble(arg);
        }

        static void Scramble(string fileName)
        {
            using (var origImage = new System.Drawing.Bitmap(fileName))
            using (var tmpImage = new System.Drawing.Bitmap(origImage))
            {
                {
                    int x = origImage.Width;
                    while (x > 0) {
                       int xbit = x & -x;
                        do {
                            x--;
                            var xalt = BitReverse(x, xbit);
                            for (int y = 0; y < origImage.Height; y++)
                                tmpImage.SetPixel(xalt, y, origImage.GetPixel(x, y));
                        } while ((x & (xbit - 1)) != 0);
                    }
                }
                {
                    int y = origImage.Height;
                    while (y > 0) {
                        int ybit = y & -y;
                        do {
                            y--;
                            var yalt = BitReverse(y, ybit);
                            for (int x = 0; x < origImage.Width; x++)
                                origImage.SetPixel(x, yalt, tmpImage.GetPixel(x, y));
                        } while ((y & (ybit - 1)) != 0);
                    } 
                }
                origImage.Save(System.IO.Path.GetFileNameWithoutExtension(fileName) + "-scrambled.png");
            }
        }

        static int BitReverse(int n, int bit)
        {
            if (bit < 4)
                return n;
            int r = n & ~(bit - 1);
            int tmp = 1;
            while (bit > 1) {
                bit >>= 1;
                if ((n & bit) != 0)
                    r |= tmp;
                tmp <<= 1;
            }
            return r;
        }
    }
}

पहली छवि:

तले हुए पहले चित्र

दूसरी छवि:

हाथापाई दूसरी छवि


2
मुझे इस पर "प्लेड" आउटपुट पसंद है।
ब्रायन रोजर्स

14

सी#

स्क्रैचिंग और अनक्रिम्बिंग के लिए समान विधि। मैं इसमें सुधार के सुझावों की सराहना करूंगा।

using System;
using System.Drawing;
using System.Linq;

public class Program
{
    public static Bitmap Scramble(Bitmap bmp)
    {
        var res = new Bitmap(bmp);
        var r = new Random(1);

        // Making lists of even and odd numbers and shuffling them
        // They contain numbers between 0 and picture.Width (or picture.Height)
        var rX = Enumerable.Range(0, bmp.Width / 2).Select(x => x * 2).OrderBy(x => r.Next()).ToList();
        var rrX = rX.Select(x => x + 1).OrderBy(x => r.Next()).ToList();
        var rY = Enumerable.Range(0, bmp.Height / 2).Select(x => x * 2).OrderBy(x => r.Next()).ToList();
        var rrY = rY.Select(x => x + 1).OrderBy(x => r.Next()).ToList();

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < rX.Count; x++)
            {
                // Swapping pixels in a row using lists rX and rrX
                res.SetPixel(rrX[x], y, bmp.GetPixel(rX[x], y));
                res.SetPixel(rX[x], y, bmp.GetPixel(rrX[x], y));
            }
        }
        for (int x = 0; x < bmp.Width; x++)
        {
            for (int y = 0; y < rY.Count; y++)
            {
                // Swapping pixels in a column using sets rY and rrY
                var px = res.GetPixel(x, rrY[y]);
                res.SetPixel(x, rrY[y], res.GetPixel(x, rY[y]));
                res.SetPixel(x, rY[y], px);
            }
        }

        return res;
    }
}

साइकेडेलिक प्लेड में आउटपुट का परिणाम होता है पेहला दूसरा


अच्छा लगा कि इसके कुछ धारीदार पैटर्न हैं)
सोनामियम

1
क्या आप कृपया 2 चित्र स्वैप कर सकते हैं? प्रश्न में पहाड़ों की छवि पहले है।
AL

1
क्या आप एल्गोरिथ्म का संक्षिप्त विवरण शामिल कर सकते हैं?
ट्राइकोप्लाक्स

14

पायथन 2 (स्व-विलोम, कोई यादृच्छिकता, संदर्भ-संवेदनशील नहीं)

यह "कम से कम पहचानने योग्य" के लिए कोई पुरस्कार नहीं जीतेगा, लेकिन शायद यह "दिलचस्प" के रूप में स्कोर कर सकता है। :-)

मैं कुछ संदर्भ-संवेदनशील बनाना चाहता था, जहां पिक्सल्स का फड़कना वास्तव में छवि पर ही निर्भर करता है।

यह विचार काफी सरल है: पिक्सेल के रंग से प्राप्त कुछ मनमाने मूल्य के अनुसार सभी पिक्सेल को क्रमबद्ध करें और फिर उस सूची में पहले पिक्सेल की स्थिति को अंतिम के साथ स्वैप करें, दूसरे को दूसरे के साथ, और इसी तरह।

दुर्भाग्य से इस सरल दृष्टिकोण में एक ही रंग के पिक्सल के साथ एक समस्या है, इसलिए अभी भी इसे आत्म-उलटा करने के लिए मेरा कार्यक्रम थोड़ा और बढ़ गया ...

from PIL import Image

img = Image.open('1.png', 'r')
pixels = img.load()
size_x, size_y = img.size

def f(colour):
    r,g,b = colour[:3]
    return (abs(r-128)+abs(g-128)+abs(b-128))//128

pixel_list = [(x,y,f(pixels[x,y])) for x in xrange(size_x) for y in xrange(size_y)]
pixel_list.sort(key=lambda x: x[2])
print "sorted"

colours = {}
for p in pixel_list:
    if p[2] in colours:
        colours[p[2]] += 1
    else:
        colours[p[2]] = 1
print "counted"

for n in set(colours.itervalues()):
    pixel_group = [p for p in pixel_list if colours[p[2]]==n]
    N = len(temp_list)
    for p1, p2 in zip(pixel_group[:N//2], pixel_group[-1:-N//2:-1]):
        pixels[p1[0],p1[1]], pixels[p2[0],p2[1]] = pixels[p2[0],p2[1]], pixels[p1[0],p1[1]]
print "swapped"

img.save('1scrambled.png')
print "saved"

यह परिणाम है: (पेट (आर -128) + पेट (छ-128) + पेट (ख-128)) // 128 (पेट (आर -128) + पेट (छ-128) + पेट (ख-128)) // 128

हैश फ़ंक्शन को बदलकर आप काफी अलग परिणाम प्राप्त कर सकते हैं f:

  • r-g-b:

    आरजीबी

  • r+g/2.**8+b/2.**16:

    आर + g / 2। ** 8 + बी / 2। ** 16

  • math.sin(r+g*2**8+b*2**16):

    गणित.पाप (आर + g * 2 ** 8 + ब * 2 ** 16)

  • (r+g+b)//600:

    (आर + g + b) // 600

  • 0:

    0


3
वाह! यह एक महान है !!! अच्छा काम!
टोड लेहमैन

1
यह अब तक का सबसे दिलचस्प है। अच्छा कार्य!
bebe

12

गणितज्ञ (+ बोनस)

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

एक टिप्पणी थी कि यह मान्य नहीं हो सकता क्योंकि यह प्रति चैनल स्क्रैम्बल है। मुझे लगता है कि यह होना चाहिए, लेकिन यह कोई बड़ी बात नहीं है। केवल पूरे पिक्सेल को बदलने के लिए आवश्यक परिवर्तन (प्रति चैनल के बजाय) Flatten @ xको Flatten[x, 1]:) में बदलना होगा

ClearAll @ f;

f @ x_ := 
  With[
    {r = SeedRandom[Times @@ Dimensions @ x], f = Flatten @ x},
    ArrayReshape[
      Permute[f, Cycles @ Partition[RandomSample @ Range @ Length @ f, 2]],
      Dimensions @ x]]

व्याख्या

एक फ़ंक्शन को परिभाषित करता fहै जो 2-आयामी सरणी लेता है x। फ़ंक्शन एक यादृच्छिक बीज के रूप में छवि के आयामों के उत्पाद का उपयोग करता है, और फिर सरणी को 1-आयामी सूची f(स्थानीय रूप से छाया) में समतल करता है । फिर यह उस फॉर्म की एक सूची बनाता है {1, 2, ... n}जहांn लंबाई होती है f, यादृच्छिक रूप से उस सूची को अनुमति देता है, इसे 2 के खंडों में विभाजित करता है (इसलिए, उदाहरण के लिए {{1, 2}, {3, 4}, ...}अंतिम संख्या को छोड़ना यदि आयाम दोनों विषम हैं), और फिर मानों fको स्वैप करके अनुमति देता है प्रत्येक उपसूची में इंगित पदों को अभी बनाया गया है, और अंत में यह अनुमत सूची को फिर से मूल आयामों में बदल देता है x। यह प्रति चैनल स्क्रैम्बल करता है क्योंकि छवि आयामों को ढहने के अलावा।Flattenकमांड प्रत्येक पिक्सेल में चैनल डेटा को भी ध्वस्त करता है। फ़ंक्शन का अपना व्युत्क्रम होता है क्योंकि चक्रों में प्रत्येक में केवल दो पिक्सेल शामिल होते हैं।

प्रयोग

img1=Import@"http://i.stack.imgur.com/2C2TY.jpg"//ImageData;
img2=Import@"http://i.stack.imgur.com/B5TbK.png"//ImageData;

f @ img1 // Image

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

f @ f @ img1 // Image

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

f @ img2 // Image

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

f @ f @ img2 // Image

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

यहाँ उपयोग कर रहा है Flatten[x, 1]

g@x_ := With[{r = SeedRandom[Times @@ Dimensions @ x], f = Flatten[x, 1]}, 
  ArrayReshape[
   Permute[f, Cycles@Partition[RandomSample@Range@Length@f, 2]], 
   Dimensions@x]]

g@img2 // Image

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


1
मेरा अनुमान है कि यह मानदंडों को पूरा नहीं करता है, क्योंकि यह पिक्सेल पैमाने से छोटे पर स्वैप होता है।
ट्राइकोप्लाक्स

1
मुझे नहीं लगता कि यह एक मान्य उत्तर है, लेकिन मुझे भी यह पसंद है। यह एक आकर्षक मोड़ है, इसलिए वैसे भी +1 ...
ट्राइकोप्लाक्स

1
@githubphagocyte अद्यतन देखें :)
mfvonh

ग्रेट - मैं फिर से +1 के लिए पहुंच गया लेकिन निश्चित रूप से मैं इसे दो बार नहीं कर सकता ...
ट्राइकोप्लाक्स

1
@githubphagocyte ओह ठीक है, मैं भूल गया कि छोटे वाक्यविन्यास विचित्र हो सकते हैं। हाँ। f @ f @ img1 // Imageहै (पूर्ण वाक्य रचना में)Image[f[f[img1]]]
mfvonh

10

मतलाब (+ बोनस)

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

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

इमेजिस

1 2

कोड

img = imread('shuffle_image2.bmp');
s = size(img)
rand('seed',0)
map = zeros(s(1),s(2));
for i = 1:2.1:s(1)*s(2) %can use much time if stepsize is 2 since then every pixel has to be exchanged
    while true %find two unswitched pixels
        a = floor(rand(1,2) .* [s(1),s(2)] + [1,1]);
        b = floor(rand(1,2) .* [s(1),s(2)] + [1,1]);
        if map(a(1),a(2)) == 0 && map(b(1),b(2)) == 0
            break
        end
    end
    %switch
    map(a(1),a(2)) = 1;
    map(b(1),b(2)) = 1;
    t = img(a(1),a(2),:);
    img(a(1),a(2),:) = img(b(1),b(2),:);
    img(b(1),b(2),:) = t;
end
image(img)
imwrite(img,'output2.png')

मुझे पूरी तरह से समझ नहीं आ रहा है, क्या आपका कोड दूसरी बार एन्क्रिप्ट की गई छवि पर लागू होता है?
सोमनियम

2
बिल्कुल सही: हर बार ठीक दो पिक्सेल स्वैप हो जाते हैं, और पूरी प्रक्रिया के दौरान फिर से स्वैप नहीं होंगे। क्योंकि 'रैंडम' नंबर दोनों बार एक समान होते हैं (रैंडम नंबर जनरेटर के रीसेट होने के कारण), पिक्सेल जोड़े वापस स्वाइप हो जाएंगे। (RNG हमेशा अगले उत्पन्न करने के लिए पिछली उत्पन्न संख्या पर निर्भर करता है, मुझे यह स्पष्ट है।)
दोष

1
हा, कि था वास्तव में मेरे प्रारंभिक विचार है, लेकिन फिर मुझे यकीन प्रत्येक पिक्सेल ठीक एक बार बदली है बनाने के लिए परेशान नहीं किया जा सकता क्योंकि मैं काम करने के लिए पाने के लिए था। : डी +1!
मार्टिन एंडर

3
@ user2992539 ऑक्टेव की जाँच करें जो कि मैटलैब के लिए एक अच्छा ओपनसोर्स विकल्प है, और आप सीधे ऑक्टेव में 99% मैटलैब कोड चला सकते हैं।
दोष

2
मुझे लगता है कि यदि आप अपने चित्रों में वास्तव में कठिन हैं तो आप अभी भी इनपुट से कुछ संरचना देख सकते हैं (जो सभी पिक्सेल को स्थानांतरित नहीं करने के कारण है)। मुझे लगता है कि यदि आपने O (,) के बजाय O (1) में चलने के लिए अपने चयन एल्गोरिदम को बदल दिया, तो आप इसे ठीक कर सकते हैं। ;)
मार्टिन एंडर

10

Mathematica- स्क्रैम्बल करने के लिए एक क्रमपरिवर्तन का उपयोग करें और इसके व्युत्क्रम को अनचाहे करने के लिए।

एक jpg चित्र {r,g,b}पिक्सेल रंगों का त्रि-आयामी सरणी है । (3 आयाम पंक्ति, स्तंभ और रंग द्वारा पिक्सेल के सेट की संरचना करते हैं)। इसे {r,g,b}त्रिक की सूची में समतल किया जा सकता है , फिर "ज्ञात" चक्र सूची के अनुसार अनुमति दी जाती है, और अंत में मूल आयामों की एक सरणी में फिर से इकट्ठा किया जाता है। परिणाम एक तले हुए चित्र है।

असंस्क्रमित रूप से तले हुए चित्र को लेता है और इसे चक्र सूची के पीछे ले जाता है। यह आउटपुट, हां, मूल छवि।

इसलिए एकल कार्य (वर्तमान मामले में, scramble ) एक छवि में स्क्रैम्बलिंग के साथ-साथ असम्पीडित पिक्सेल के लिए भी कार्य करता है।

एक बीज संख्या के साथ एक छवि इनपुट है (यह सुनिश्चित करने के लिए कि रैंडम नंबर जनरेटर स्क्रैचिंग और अनसक्रिमिंग के लिए एक ही स्थिति में होगा)। जब पैरामीटर, रिवर्स, गलत है, तो फ़ंक्शन स्क्रैम्बल होगा। जब यह सत्य है, तो फ़ंक्शन अनचाहे हो जाएगा।


संघर्ष

पिक्सल समतल होते हैं और चक्रों की एक यादृच्छिक सूची उत्पन्न होती है। अनुमति चपटा सूची में पिक्सल्स की स्थिति को बदलने के लिए चक्रों का उपयोग करती है।

खोलना

एक ही फ़ंक्शन scrambleका उपयोग unscrambling के लिए किया जाता है। हालाँकि चक्र सूची का क्रम उल्टा है।

scramble[img_,s_,reverse_:False,imgSize_:300]:=
  Module[{i=ImageData[img],input,r},input=Flatten[i,1];SeedRandom[s];
  r=RandomSample@Range[Length[input]];Image[ArrayReshape[Permute[input,
  Cycles[{Evaluate@If[reverse,Reverse@r,r]}]],Dimensions[i]],ImageSize->imgSize]]

उदाहरण

एक ही बीज (37) का उपयोग स्क्रैचिंग और अनक्रीमिंग के लिए किया जाता है।

यह पहाड़ की तराशी गई छवि का निर्माण करता है। नीचे दी गई तस्वीर से पता चलता है कि पर्वत के दृश्य की वास्तविक छवि द्वारा चर को तराशा जा सकता है।

scrambledMount=scramble[mountain, 37, True]

mount1


अब हम उलटा चलाते हैं; scrambledMount दर्ज किया गया है और मूल चित्र को पुन: निर्मित किया गया है।

 scramble[scrambledMount, 37, True]

mount2


मंडलियों के लिए समान बात:

circles1


 scramble[scrambledCircles, 37, True]

circles2


मैं नहीं देख सकता कि कैसे एक छवि 3 आयामी सरणी हो सकती है।
edc65

1
@ edc65, Rows x Columns x रंग। पहाड़ की छवि 800 स्तंभों द्वारा 3 रंगों द्वारा 422 पंक्तियों की है। यदि एरे को चपटा किया जाता है, तो यह एक डायनामिक एरे के रूप में, सूची के रूप में 1012800 डेटा का उत्पादन करता है।
डेविड जूल

@ edc65 मुझे यह जोड़ना चाहिए कि रंगों को आरजीबी ट्रिपल्स के रूप में पुनर्व्यवस्थित करने के लिए परमिट का उपयोग किया गया था। मैंने यह नहीं समझा कि किसी भी पिक्सेल के रंगों की सूची में कोई भी बदलाव करने में मेरी दिलचस्पी नहीं है। यदि आप एक तत्व के रूप में आरजीबी जानकारी, {आर, जी, बी} पर विचार करते हैं, तो हम एक 2 डी सरणी के बारे में बात कर रहे हैं। इस तरह से देखने पर, यह सवाल उठाने का पूरा मतलब है (एक छवि 3 आयामी सरणी कैसे हो सकती है?) जिसे आपने उठाया था। वास्तव में, एक छवि को 2 डी सरणी के रूप में मानना ​​सामान्य हो सकता है, इस तथ्य की उपेक्षा करते हुए कि आरजीबी तत्व एक और आयाम जोड़ते हैं।
डेविड जूल

10

अजगर

मुझे यह पहेली पसंद है, वह दिलचस्प लग रहा था और मैं छवि पर लागू करने के लिए एक लिपटा और मूवमेंट फ़ंक्शन के साथ आया था।

wraped

मैंने चित्र को एक पाठ (बाएं से दाएं, ऊपर और नीचे) के रूप में पढ़ा और इसे घोंघा खोल के रूप में लिखा।

यह फ़ंक्शन चक्रीय है: उदाहरण के लिए 4 * 2, f (f (f (x))) = x के लिए N, f ^ (n) (x) = x में एक है।

आंदोलन

मैं एक यादृच्छिक संख्या लेता हूं और प्रत्येक कॉलम को आगे बढ़ाता हूं और इससे लिग्नेट करता हूं

कोड

# Opening and creating pictures
img = Image.open("/home/faquarl/Bureau/unnamed.png")
PM1 = img.load()
(w,h) = img.size
img2 = Image.new( 'RGBA', (w,h), "black") 
PM2 = img2.load()
img3 = Image.new( 'RGBA', (w,h), "black") 
PM3 = img3.load()

# Rotation
k = 0
_i=w-1
_j=h-1
_currentColMin = 0
_currentColMax = w-1
_currentLigMin = 0
_currentLigMax = h-1
_etat = 0
for i in range(w):
    for j in range(h):
        PM2[_i,_j]=PM1[i,j]
        if _etat==0:
            if _currentColMax == _currentColMin:
                _j -= 1
                _etat = 2
            else:
                _etat = 1
                _i -= 1
        elif _etat==1:
            _i -= 1
            if _j == _currentLigMax and _i == _currentColMin:
                _etat = 2
        elif _etat==2:
            _j -= 1
            _currentLigMax -= 1
            if _j == _currentLigMin and _i == _currentColMin:
                _etat = 5
            else:
                _etat = 3
        elif _etat==3:
            _j -= 1
            if _j == _currentLigMin and _i == _currentColMin:
                _etat = 4
        elif _etat==4:
            _i += 1
            _currentColMin += 1
            if _j == _currentLigMin and _i == _currentColMax:
                _etat = 7
            else:
                _etat = 5
        elif _etat==5:
            _i += 1
            if _j == _currentLigMin and _i == _currentColMax:
                _etat = 6
        elif _etat==6:
            _j += 1
            _currentLigMin += 1
            if _j == _currentLigMax and _i == _currentColMax:
                _etat = 1
            else:
                _etat = 7
        elif _etat==7:
            _j += 1
            if _j == _currentLigMax and _i == _currentColMax:
                _etat = 8
        elif _etat==8:
            _i -= 1
            _currentColMax -= 1
            if _j == _currentLigMax and _i == _currentColMin:
                _etat = 3
            else:
                _etat = 1
        k += 1
        if k == w * h:
            i = w
            j = h
# Movement
if w>h:z=w
else:z=h
rand.seed(z)
a=rand.randint(0,h)
for i in range(w):
  for j in range(h):
  if i%2==0:
    PM3[(i+a)%w,(j+a)%h]=PM2[i,j]
  else:
    PM3[(i-a)%w,(j-a)%h]=PM2[i,j]
# Rotate Again

चित्रों

पहला रोटेशन: यहाँ छवि विवरण दर्ज करें

फिर क्रमपरिवर्तन: यहाँ छवि विवरण दर्ज करें

और अंतिम रोटेटियन के साथ: यहाँ छवि विवरण दर्ज करें

अन्य उदाहरण के लिए: यहाँ छवि विवरण दर्ज करें


2
आप मूल छवि को कैसे पुनर्स्थापित करते हैं?
ट्राइकोप्लाक्स

यदि यह सिर्फ रोटेशन है, तो मैं इसे एक निश्चित समय (आकार पर निर्भर करता है) कर सकता हूं। हालाँकि, अगर मुझे इसकी अनुमति थी तो मुझे यकीन नहीं है कि यह चक्रीय है इसलिए मेरा अभी दूसरा कार्य है जो केवल परिवर्तन है जो कि PM2 [_i, _j] = PM1 [i, j] PM2 [i, j] = PM1 हो गया है _i, _j] और PM3 [(i + a)% w, (j + a)% h] = PM2 [i, j] PM3 [(ia)% w, (ja)% h] = PM2 [I] जे]। मैं इन दो पंक्तियों के बिना यह करने के लिए एक रास्ता खोज रहा हूँ
Faquarl

8

VB.NET (+ बोनस)

यह त्रुटिपूर्ण विचार का उपयोग करता है, उसके लिए धन्यवाद, हालांकि यह अलग-अलग स्वैपिंग और एल्गोरिथ्म की जांच करता है। प्रोग्राम एन्कोड और उसी तरह से डीकोड करता है।

Imports System

Module Module1

    Sub swap(ByVal b As Drawing.Bitmap, ByVal i As Integer, ByVal j As Integer)
        Dim c1 As Drawing.Color = b.GetPixel(i Mod b.Width, i \ b.Width)
        Dim c2 As Drawing.Color = b.GetPixel(j Mod b.Width, j \ b.Width)
        b.SetPixel(i Mod b.Width, i \ b.Width, c2)
        b.SetPixel(j Mod b.Width, j \ b.Width, c1)
    End Sub

    Sub Main(ByVal args() As String)
        For Each a In args
            Dim f As New IO.FileStream(a, IO.FileMode.Open)
            Dim b As New Drawing.Bitmap(f)
            f.Close()
            Dim sz As Integer = b.Width * b.Height - 1
            Dim w(sz) As Boolean
            Dim r As New Random(666)
            Dim u As Integer, j As Integer = 0
            Do While j < sz
                Do
                    u = r.Next(0, sz)
                Loop While w(u)
                ' swap
                swap(b, j, u)
                w(j) = True
                w(u) = True
                Do
                    j += 1
                Loop While j < sz AndAlso w(j)
            Loop
            b.Save(IO.Path.ChangeExtension(a, "png"), Drawing.Imaging.ImageFormat.Png)
            Console.WriteLine("Done!")
        Next
    End Sub

End Module

आउटपुट चित्र:


8

यह याद दिलाने के बाद कि यह पिक्सल स्वैप करना है और उन्हें बदलना नहीं है, इसके लिए यहां मेरा समाधान है:

तले हुए: यहाँ छवि विवरण दर्ज करें

पुनर्स्थापित किया गया: यहाँ छवि विवरण दर्ज करें

यह पिक्सेल ऑर्डर को यादृच्छिक बनाने के द्वारा किया जाता है, लेकिन इसे पुनर्स्थापित करने में सक्षम होने के लिए, यादृच्छिककरण तय हो गया है। यह एक निर्धारित बीज के साथ एक छद्म यादृच्छिक का उपयोग करके किया जाता है और उन सूचकों की एक सूची उत्पन्न करता है जो वर्णन करते हैं कि कौन सा पिक्सेल स्वैप करना है। जैसे ही स्वैप होगा, उसी सूची में मूल छवि को पुनर्स्थापित किया जाएगा।

public class ImageScramble {

  public static void main(String[] args) throws IOException {
    if (args.length < 2) {
      System.err.println("Usage: ImageScramble <fileInput> <fileOutput>");
    } else {
      // load image
      final String extension = args[0].substring(args[0].lastIndexOf('.') + 1);
      final BufferedImage image = ImageIO.read(new File(args[0]));
      final int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());

      // create randomized swap list
      final ArrayList<Integer> indexes = IntStream.iterate(0, i -> i + 1).limit(pixels.length).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
      Collections.shuffle(indexes, new Random(1337));

      // swap all pixels at index n with pixel at index n+1
      int tmp;
      for (int i = 0; i < indexes.size(); i += 2) {
        tmp = pixels[indexes.get(i)];
        pixels[indexes.get(i)] = pixels[indexes.get(i + 1)];
        pixels[indexes.get(i + 1)] = tmp;
      }

      // write image to disk
      final BufferedImage imageScrambled = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
      imageScrambled.setRGB(0, 0, imageScrambled.getWidth(), imageScrambled.getHeight(), pixels, 0, imageScrambled.getWidth());
      ImageIO.write(imageScrambled, extension, new File(args[1]));
    }
  }
}

ध्यान दें कि एक हानिकारक संपीड़न प्रारूप पर इस एल्गोरिथ्म का उपयोग करने से परिणाम समान नहीं होगा, क्योंकि छवि प्रारूप डेटा को बदल देगा। यह PNG जैसे किसी भी नुकसान-कम कोडेक के साथ ठीक काम करना चाहिए।


8

मेथेमेटिका

हम एक सहायक फ़ंक्शन hऔर स्क्रैचिंग फ़ंक्शन scrambleको इस प्रकार परिभाषित करते हैं :

h[l_List, n_Integer, k_Integer: 1] := 
  With[{ m = Partition[l, n, n, 1, 0] }, 
    Flatten[
      Riffle[
        RotateLeft[ m[[ ;; , {1} ]] , k ],
        m[[ ;; , 2;; ]]
      ], 1
    ] [[ ;; Length[l] ]]
  ];

scramble[img_Image, k_Integer] :=
  Module[{ list , cNum = 5 },
    Which[
      k > 0,    list = Prime@Range[cNum],
      k < 0,    list = Reverse@Prime@Range[cNum],
      True,     list = {}
    ];
    Image[
      Transpose[
        Fold[ h[ #1, #2, k ] &, #, list ] & /@
        Transpose[
          Fold[ h[#1, #2, k] &, #, list ] & /@ ImageData[img]
        ]
      ]
    ]
  ];

छवि लोड करने के बाद, आप छवि को खंगालने के लिए किसी भी पूर्णांक को scramble[img, k]कहां कॉल कर सकते हैं k। के साथ फिर से कॉल -kकरना असाध्य होगा। (यदि kहै 0, तो कोई बदलाव नहीं किया गया है।) आमतौर पर kकुछ ऐसा चुना जाना चाहिए 100, जो एक बहुत ही सुंदर छवि देता है:

उदाहरण आउटपुट 1

उदाहरण आउटपुट 2


7

मतलाब: पंक्ति और स्तंभ योग पर आधारित पंक्ति और स्तंभ स्क्रैबिंग

यह एक मजेदार पहेली की तरह लग रहा था, इसलिए मैंने इसके बारे में सोचा था और निम्नलिखित समारोह के साथ आया था। यह परिपत्र शिफ्टिंग के दौरान पंक्ति और कॉलम पिक्सेल-वैल्यू रकम के व्युत्क्रम पर आधारित है: यह प्रत्येक पंक्ति को बदलता है, फिर प्रत्येक कॉलम पंक्ति / कॉलम के पिक्सेल मानों के कुल योग द्वारा (शिफ्ट-वेरिएबल में पूरे नंबर के लिए एक uint8 मानकर) )। इसके बाद विपरीत दिशा में उनके योग-मूल्य द्वारा प्रत्येक स्तंभ को पंक्तिबद्ध करके उलटा किया जा सकता है।

यह दूसरों की तरह सुंदर नहीं है, लेकिन मुझे यह पसंद है कि यह गैर-यादृच्छिक है और पूरी तरह से छवि द्वारा निर्दिष्ट है - कोई चुनने वाला पैरामीटर नहीं।

मैंने मूल रूप से प्रत्येक रंग चैनल को अलग से स्थानांतरित करने के लिए इसे डिज़ाइन किया था, लेकिन फिर मैंने केवल पूर्ण पिक्सेल स्थानांतरित करने के लिए विनिर्देश पर ध्यान दिया।

function pic_scramble(input_filename)
i1=imread(input_filename);
figure;
subplot(1,3,1);imagesc(i1);title('Original','fontsize',20);

i2=i1;
for v=1:size(i1,1)
    i2(v,:,:)=circshift(i2(v,:,:),sum(sum(i2(v,:,:))),2);
end
for w=1:size(i2,2)
    i2(:,w,:)=circshift(i2(:,w,:),sum(sum(i2(:,w,:))),1);
end
subplot(1,3,2);imagesc(i2);title('Scrambled','fontsize',20);

i3=i2;
for w=1:size(i3,2)
    i3(:,w,:)=circshift(i3(:,w,:),-1*sum(sum(i3(:,w,:))),1);
end
for v=1:size(i3,1)
    i3(v,:,:)=circshift(i3(v,:,:),-1*sum(sum(i3(v,:,:))),2);
end
subplot(1,3,3);imagesc(i3);title('Recovered','fontsize',20);

पहले परीक्षण छवि सुरक्षित परीक्षण छवि


6

जावा

यह प्रोग्राम बेतरतीब ढंग से पिक्सेल स्वैप करता है (पिक्सेल पिक्सेल को पिक्सेल मैपिंग बनाता है), लेकिन यादृच्छिक फ़ंक्शन के बजाय यह Math.sin () (पूर्णांक x) का उपयोग करता है। यह पूरी तरह से प्रतिवर्ती है। परीक्षण छवियों के साथ यह कुछ पैटर्न बनाता है।

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

1 पास: यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें

100 पास (इसे करने में कुछ मिनट लगते हैं): यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें

कोड:

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

public class Test{

public static void main(String... args) {
    String in = "image.png";
    String out = in;
    int passes = 0;
    if (args.length < 1) {
        System.out.println("no paramem encryptimg, 1 pass, reading and saving image.png");
        System.out.println("Usage: pass a number. Negative - n passes of decryption, positive - n passes of encryption, 0 - do nothing");
    } else {
        passes = Integer.parseInt(args[0]);
        if (args.length > 1) {
            in = args[1];
        }
        if(args.length > 2){
            out = args[2];
        }
    }
    boolean encrypt = passes > 0;
    passes = Math.abs(passes);
    for (int a = 0; a < passes; a++) {
        BufferedImage img = null;
        try {
            img = ImageIO.read(new File(a == 0 ? in : out));
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        int pixels[][] = new int[img.getWidth()][img.getHeight()];
        int[][] newPixels = new int[img.getWidth()][img.getHeight()];
        for (int x = 0; x < pixels.length; x++) {
            for (int y = 0; y < pixels[x].length; y++) {
                pixels[x][y] = img.getRGB(x, y);
            }
        }
        int amount = img.getWidth() * img.getHeight();
        int[] list = new int[amount];
        for (int i = 0; i < amount; i++) {
            list[i] = i;
        }
        int[] mapping = new int[amount];
        for (int i = amount - 1; i >= 0; i--) {
            int num = (Math.abs((int) (Math.sin(i) * amount))) % (i + 1);
            mapping[i] = list[num];
            list[num] = list[i];
        }
        for (int xz = 0; xz < amount; xz++) {
            int x = xz % img.getWidth();
            int z = xz / img.getWidth();
            int xzMap = mapping[xz];
            int newX = xzMap % img.getWidth();
            int newZ = xzMap / img.getWidth();
            if (encrypt) {
                newPixels[x][z] = pixels[newX][newZ];
            } else {
                newPixels[newX][newZ] = pixels[x][z];
            }
        }
        BufferedImage newImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < pixels.length; x++) {
            for (int y = 0; y < pixels[x].length; y++) {
                newImg.setRGB(x, y, newPixels[x][y]);
            }
        }

        try {
            String[] s = out.split("\\.");
            ImageIO.write(newImg, s[s.length - 1],
                    new File(out));
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
    }
}
}

6

पीआईएल के साथ पायथन 2.7

पार्टी में थोड़ी देर हो गई, लेकिन मुझे लगा कि छवियों को प्लेड (और निश्चित रूप से) में बदलना मजेदार होगा। पहले हम कॉलम संख्या (यहां तक ​​कि कॉलम नीचे, विषम कॉलम ऊपर) से स्तंभों को ऊपर या नीचे स्थानांतरित करते हैं। फिर, हम पंक्तियों को बाईं ओर या दाईं ओर पंक्ति संख्या (यहां तक ​​कि बाएं स्तंभ, विषम कॉलम दाएं) द्वारा स्थानांतरित करते हैं।

परिणाम काफी तीखा है।

रिवर्स करने के लिए, हम इनको विपरीत क्रम में करते हैं और विपरीत राशि से शिफ्ट करते हैं।

कोड

from PIL import Image

def slideColumn (pix, tpix, x, offset, height):
  for y in range(height):
    tpix[x,(offset+y)%height] = pix[x,y]

def slideRow (pix, tpix, y, offset, width):
  for x in range(width):
    tpix[(offset+x)%width,y] = pix[x,y]

def copyPixels (source, destination, width, height):
  for x in range(width):
    for y in range(height):
      destination[x,y]=source[x,y]

def shuffleHorizontal (img, tmpimg, factor, encoding):
  xsize,ysize = img.size
  pix = img.load()
  tpix = tmpimg.load()
  for y in range(ysize):
    offset = y*factor
    if y%2==0:
      offset = xsize-offset
    offset = (xsize + offset) % xsize
    if encoding:
      slideRow(pix,tpix,y,offset,xsize)
    else:
      slideRow(pix,tpix,y,-offset,xsize)
  copyPixels(tpix,pix,xsize,ysize)

def shuffleVertical (img, tmpimg, factor, encoding):
  xsize,ysize = img.size
  pix = img.load()
  tpix = tmpimg.load()
  for x in range(xsize):
    offset = x*factor
    if x%2==0:
      offset = ysize-offset
    offset = (ysize + offset) % ysize
    if encoding:
      slideColumn(pix,tpix,x,offset,ysize)
    else:
      slideColumn(pix,tpix,x,-offset,ysize)
  copyPixels(tpix,pix,xsize,ysize)


def plaidify (img):
  tmpimg = Image.new("RGB",img.size)
  shuffleVertical(img,tmpimg,4,True)
  shuffleHorizontal(img,tmpimg,4,True)

def deplaidify (img):
  tmpimg = Image.new("RGB",img.size)
  shuffleHorizontal(img,tmpimg,4,False)
  shuffleVertical(img,tmpimg,4,False)

परिणाम

छवि 1 से प्लेड:

प्लेजाइज्ड 1.jpg

प्लेड फॉर्म छवि 2:

प्लेड २.पंग


2
बहुत अच्छा! क्या 45 ° कोण के साथ विकर्ण प्राप्त करना संभव है?
टॉड लेहमैन

2
यह ऑफसेट लाइनों को बदलकर संभव है: offset = x*xsize/ysize और offset = y*ysize/xsize लेकिन, यह वास्तव में छवि को छिपाना नहीं है, दुर्भाग्य से।
jrrl

5

पायथन (+ बोनस) - पिक्सेल का क्रमचय

इस पद्धति में, प्रत्येक पिक्सेल को दूसरी स्थिति पर रखा जाएगा, इस बाधा के साथ कि दूसरे पिक्सेल को पहले स्थान पर रखा जाएगा। गणितीय रूप से, यह चक्र की लंबाई के साथ एक क्रमपरिवर्तन है 2. जैसा कि, विधि यह स्वयं का व्युत्क्रम है।

रेट्रोस्पेक्ट में, यह mfvonh के समान है, लेकिन यह सबमिशन पायथन में है और मुझे खुद उस परफॉर्मेशन का निर्माण करना था।

def scramble(I):
    result = np.zeros_like(I)
    size = I.shape[0:2]
    nb_pixels = size[0]*size[1]
    #Build permutation
    np.random.seed(0)
    random_indices = np.random.permutation( range(nb_pixels) )
    random_indices1 = random_indices[0:int(nb_pixels/2)]
    random_indices2 = random_indices[-1:-1-int(nb_pixels/2):-1]
    for c in range(3):
        Ic = I[:,:,c].flatten()
        Ic[ random_indices2 ] = Ic[random_indices1]
        Ic[ random_indices1 ] = I[:,:,c].flatten()[random_indices2]
        result[:,:,c] = Ic.reshape(size)
    return result

पहली परीक्षण छवि: पहले परीक्षण छवि दूसरी परीक्षण छवि: दूसरी परीक्षण छवि


5

पायथन 2.7 + पीआईएल, स्लाइडिंग पज़ल्स से प्रेरणा

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

परिणाम:

मूल

मूल

दानेदारता १६

16

दानेदारता १३

13

दानेदारता १०

10

दानेदारता ३

3

दानेदारता २

2

ग्रैन्युलैरिटी 1

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

मूल

मूल

दानेदारता १६

16

दानेदारता १३

13

दानेदारता १०

10

दानेदारता ३

3

दानेदारता २

2

ग्रैन्युलैरिटी 1

1

कोड:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PIL import Image
import random

def scramble_blocks(im,granularity,password,nshuffle):
    set_seed(password)
    width=im.size[0]
    height=im.size[1]

    block_width=find_block_dim(granularity,width)       #find the possible block dimensions
    block_height=find_block_dim(granularity,height)

    grid_width_dim=width/block_width                #dimension of the grid
    grid_height_dim=height/block_height

    nblocks=grid_width_dim*grid_height_dim          #number of blocks

    print "nblocks: ",nblocks," block width: ",block_width," block height: ",block_height
    print "image width: ",width," image height: ",height
    print "getting all the blocks ..."
    blocks=[]
    for n in xrange(nblocks): #get all the image blocks
        blocks+=[get_block(im,n,block_width,block_height)]

    print "shuffling ..."
    #shuffle the order of the blocks
    new_order=range(nblocks)
    for n in xrange(nshuffle):
        random.shuffle(new_order)

    print "building final image ..."
    new_image=im.copy()
    for n in xrange(nblocks):
        #define the target box where to paste the new block
        i=(n%grid_width_dim)*block_width                #i,j -> upper left point of the target image
        j=(n/grid_width_dim)*block_height
        box = (i,j,i+block_width,j+block_height)    

        #paste it   
        new_image.paste(blocks[new_order[n]],box)

    return new_image



#find the dimension(height or width) according to the desired granularity (a lower granularity small blocks)
def find_block_dim(granularity,dim):
    assert(granularity>0)
    candidate=0
    block_dim=1
    counter=0
    while counter!=granularity:         #while we dont achive the desired granularity
        candidate+=1
        while((dim%candidate)!=0):      
            candidate+=1
            if candidate>dim:
                counter=granularity-1
                break

        if candidate<=dim:
            block_dim=candidate         #save the current feasible lenght

        counter+=1

    assert(dim%block_dim==0 and block_dim<=dim)
    return block_dim

def unscramble_blocks(im,granularity,password,nshuffle):
    set_seed(password)
    width=im.size[0]
    height=im.size[1]

    block_width=find_block_dim(granularity,width)       #find the possible block dimensions
    block_height=find_block_dim(granularity,height)

    grid_width_dim=width/block_width                #dimension of the grid
    grid_height_dim=height/block_height

    nblocks=grid_width_dim*grid_height_dim          #number of blocks

    print "nblocks: ",nblocks," block width: ",block_width," block height: ",block_height
    print "getting all the blocks ..."
    blocks=[]
    for n in xrange(nblocks): #get all the image blocks
        blocks+=[get_block(im,n,block_width,block_height)]

    print "shuffling ..."
    #shuffle the order of the blocks
    new_order=range(nblocks)
    for n in xrange(nshuffle):
        random.shuffle(new_order)

    print "building final image ..."
    new_image=im.copy()
    for n in xrange(nblocks):
        #define the target box where to paste the new block
        i=(new_order[n]%grid_width_dim)*block_width             #i,j -> upper left point of the target image
        j=(new_order[n]/grid_width_dim)*block_height
        box = (i,j,i+block_width,j+block_height)    

        #paste it   
        new_image.paste(blocks[n],box)

    return new_image

#get a block of the image
def get_block(im,n,block_width,block_height):

    width=im.size[0]

    grid_width_dim=width/block_width                        #dimension of the grid

    i=(n%grid_width_dim)*block_width                        #i,j -> upper left point of the target block
    j=(n/grid_width_dim)*block_height

    box = (i,j,i+block_width,j+block_height)
    block_im = im.crop(box)
    return block_im

#set random seed based on the given password
def set_seed(password):
    passValue=0
    for ch in password:                 
        passValue=passValue+ord(ch)
    random.seed(passValue)


if __name__ == '__main__':

    filename="0RT8s.jpg"
    # filename="B5TbK.png"
    password="yOs0ZaKpiS"
    nshuffle=1
    granularity=1

    im=Image.open(filename)

    new_image=scramble_blocks(im,granularity,password,nshuffle)
    new_image.show()
    new_image.save(filename.split(".")[0]+"_puzzled.png")

    new_image=unscramble_blocks(new_image,granularity,password,nshuffle)
    new_image.save(filename.split(".")[0]+"_unpuzzled.png")
    new_image.show()

5

47

94 लाइनें। एन्कोडिंग के लिए 47, डिकोडिंग के लिए 47।

require 'chunky_png'
require_relative 'codegolf-35005_ref.rb'


REF = {:png => ref, :w => 1280, :h => 720}
REF[:pix] = REF[:png].to_rgb_stream.unpack('C*').each_slice(3).to_a
SEVENTH_PRIME = 4*7 - 4-7 - (4&7)
FORTY_SEVEN   = 4*7 + 4+7 + (4&7) + (4^7) + 7/4
THRESHOLD     = FORTY_SEVEN * SEVENTH_PRIME


class RNG
    @@m = 2**32
    @@r = 0.5*(Math.sqrt(5.0) - 1.0)
    def initialize(n=0)
        @cur = FORTY_SEVEN + n
    end
    def hash(seed)
        (@@m*((seed*@@r)%1)).floor
    end
    def _next(max)
        hash(@cur+=1) % max
    end
    def _prev(max)
        hash(@cur-=1) % max
    end        
    def advance(n)
        @cur += n
    end
    def state
        @cur
    end
    alias_method :rand, :_next
end


def load_png(file, resample_w = nil, resample_h = nil)
    png  = ChunkyPNG::Image.from_file(file)
    w    = resample_w || png.width
    h    = resample_h || png.height
    png.resample_nearest_neighbor!(w,h) if resample_w || resample_h
    pix  = png.to_rgb_stream.unpack('C*').each_slice(3).to_a
    return {:png => png, :w => w, :h => h, :pix => pix}
end


def make_png(img)
    rgb_stream = img[:pix].flatten.pack('C*')
    img[:png] = ChunkyPNG::Canvas.from_rgb_stream(img[:w],img[:h],rgb_stream)
    return img
end


def difference(pix_a,pix_b)
    (pix_a[0]+pix_a[1]+pix_a[2]-pix_b[0]-pix_b[1]-pix_b[2]).abs
end


def code(img, img_ref, mode)
    img_in  = load_png(img)
    pix_in  = img_in[:pix]
    pix_ref = img_ref[:pix]
    s = img_in[:w] * img_in[:h] 
    rng = RNG.new(mode==:enc ? 0 : FORTY_SEVEN*s+1)
    rand = mode == :enc ? rng.method(:_next) : rng.method(:_prev)
    s.times do
        FORTY_SEVEN.times do
            j = rand.call(s)
            i = rng.state % s
            diff_val = difference(pix_ref[i],pix_ref[j])
            if diff_val > THRESHOLD
               pix_in[i], pix_in[j] = pix_in[j], pix_in[i]
            end
        end
    end
    make_png(img_in)
end


case ARGV.shift
when 'enc'
    org, cod = ARGV
    encoded_image = code(org,REF,:enc)
    encoded_image[:png].save(cod)
when 'dec'
    org, cod = ARGV
    decoded_image = code(cod,REF,:dec)
    decoded_image[:png].save(org)
else
    puts '<original> <coded>'
    puts 'specify either <enc> or <dec>'
    puts "ruby #{$0} enc codegolf-35005_inp.png codegolf-35005_enc.png"
end

codegolf-35005_ref.rb

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

(jpg में परिवर्तित)

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

(मूल घटा)

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


3
कुछ मूल पैटर्न उस लाइनों के माध्यम से दिखाई दे रहे हैं। हालाँकि यह तब दिखता है जब आप धुंधली खिड़की पर उंगली से खींचते हैं)।
सोमनियम

2
... + 184426 बाइट्स फॉर कोडगॉल्फ -35005_ref.rb?
edc65

5

समूह सिद्धांत (+ बोनस) की एक चुटकी के साथ मतलूब

इस दृष्टिकोण में हम मान लेते हैं कि हमारे पास कुल पिक्सेल की एक समान संख्या है। (यदि नहीं, तो हम सिर्फ एक पिक्सेल को नजरअंदाज करते हैं) इसलिए हमें दूसरे आधे के साथ स्वैप करने के लिए आधे पिक्सेल का चयन करना होगा। इसके लिए हम सभी पिक्सल को इंडेक्स करते हैं02N-1 सूचकांकों को करते हैं और इन सूचकांकों को एक चक्रीय समूह के रूप में मानते हैं

उन अपराधों के बीच हम एक ऐसे नंबर की खोज करते हैं जो pबहुत छोटा नहीं है और बहुत बड़ा नहीं है, और यह 2Nहमारे समूह के आदेश का मुकाबला है । इसका मतलब है कीg हमारा समूह या उत्पन्न करता है{k*g mod 2N | k=0,1,...,2N-1} = {0,1,...,2N-1}

तो हम पहले Nगुणकों का चयन करते हैंg एक सेट रूप , और बाकी के सभी इंडोल को अन्य सेट के रूप में , और बस पिक्सल के संबंधित सेट को स्वैप करते हैं।

अगर p सही तरीके से चुना जाता है, तो पहला सेट पूरी छवि पर समान रूप से वितरित किया जाता है।

दो परीक्षण मामले:

विषय से थोड़ा हटकर लेकिन दिलचस्प:

परीक्षण के दौरान मैंने देखा, कि अगर आप इसे (हानिपूर्ण संपीड़ित) jpg (दोषरहित संपीड़ित png के बजाय) में सहेजते हैं और परिवर्तन को आगे और पीछे लागू करते हैं, तो आप बहुत जल्दी संपीडन की कलाकृतियों को देखते हैं, यह लगातार दो व्यवस्थाओं के परिणामों को दर्शाता है :

जैसा कि आप देख सकते हैं, jpg संपीड़न परिणाम को लगभग काला और सफेद दिखता है!

clc;clear;
inputname = 'codegolf_rearrange_pixels2.png';
inputname = 'codegolf_rearrange_pixels2_swapped.png';
outputname = 'codegolf_rearrange_pixels2_swapped.png';

%read image
src = imread(inputname);

%separate into channels
red = src(:,:,1);
green = src(:,:,2);
blue = src(:,:,3);

Ntotal = numel(red(:));  %number of pixels
Nswap = floor(Ntotal/2); %how many pairs we can swap

%find big enough generator
factors = unique(factor(Ntotal));
possible_gen = primes(max(size(red)));
eliminated = setdiff(possible_gen,factors);
if mod(numel(eliminated),2)==0 %make length odd for median
    eliminated = [1,eliminated];
end
generator = median(eliminated);

%set up the swapping vectors
swapindices1 = 1+mod((1:Nswap)*generator, Ntotal);
swapindices2 = setdiff(1:Ntotal,swapindices1);
swapindices2 = swapindices2(1:numel(swapindices1)); %make sure both have the same length

%swap the pixels
red([swapindices1,swapindices2]) = red([swapindices2,swapindices1]);
green([swapindices1,swapindices2]) = green([swapindices2,swapindices1]);
blue([swapindices1,swapindices2]) = blue([swapindices2,swapindices1]);

%write and display
output = cat(3,red,green,blue);
imwrite(output,outputname);
subplot(2,1,1);
imshow(src)
subplot(2,1,2);
imshow(output);

4

जावास्क्रिप्ट (+ बोनस) - पिक्सेल विभाजन स्वैप रिपीटर

फ़ंक्शन एक छवि तत्व लेता है और

  1. पिक्सल को 8 से विभाजित करता है।
  2. पिक्सेल समूहों का एक प्रतिवर्ती स्वैप करता है।
  3. यदि पिक्सेल समूह> = 8 की अदला-बदली होती है।
function E(el){
    var V=document.createElement('canvas')
    var W=V.width=el.width,H=V.height=el.height,C=V.getContext('2d')
    C.drawImage(el,0,0)
    var id=C.getImageData(0,0,W,H),D=id.data,L=D.length,i=L/4,A=[]
    for(;--i;)A[i]=i
    function S(A){
        var L=A.length,x=L>>3,y,t,i=0,s=[]
        if(L<8)return A
        for(;i<L;i+=x)s[i/x]=S(A.slice(i,i+x))
        for(i=4;--i;)y=[6,4,7,5,1,3,0,2][i],t=s[i],s[i]=s[y],s[y]=t
        s=[].concat.apply([],s)
        return s
    }
    var N=C.createImageData(W,H),d=N.data,A=S(A)
    for(var i=0;i<L;i++)d[i]=D[(A[i>>2]*4)+(i%4)]
    C.putImageData(N,0,0)
    el.src=C.canvas.toDataURL()
}

पहाड़ों मंडलियां


4

पायथन 2.7 + पीआईएल, कॉलम / रो स्क्रैम्बलर

यह विधि बस छवि की पंक्तियों और स्तंभों को खंगालती है। केवल एक या दोनों आयामों को खंगालना संभव है। इसके अलावा, नई स्क्रैम्ड रो / कॉलम का क्रम एक पासवर्ड पर आधारित है। इसके अलावा, एक और संभावना आयामों पर विचार किए बिना पूरे छवि सरणी को रगड़ रही है।

परिणाम:

संपूर्ण छवि को स्‍क्रब करना:

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

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

स्तंभों को खंगालना:

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

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

पंक्तियों को खंगालना:

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

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

दोनों स्तंभों और पंक्तियों को रगड़ना:

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

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

मैंने भी छवि पर कई रन लगाने की कोशिश की, लेकिन अंतिम परिणाम बहुत अलग नहीं थे, केवल इसे डिक्रिप्ट करने की कठिनाई।

कोड:

from PIL import Image
import random,copy

def scramble(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns*rows)        
    random.shuffle(newOrder)            #shuffle

    newpixels=copy.deepcopy(pixels)
    for i in xrange(len(pixels)):
        newpixels[i]=pixels[newOrder[i]]

    im.putdata(newpixels)

def unscramble(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns*rows)        
    random.shuffle(newOrder)            #unshuffle

    newpixels=copy.deepcopy(pixels)
    for i in xrange(len(pixels)):
        newpixels[newOrder[i]]=pixels[i]

    im.putdata(newpixels)

def scramble_columns(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns)     
    random.shuffle(newOrder)            #shuffle

    newpixels=[]
    for i in xrange(rows):
        for j in xrange(columns):
            newpixels+=[pixels[i*columns+newOrder[j]]]

    im.putdata(newpixels)

def unscramble_columns(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(columns)     
    random.shuffle(newOrder)            #shuffle

    newpixels=copy.deepcopy(pixels)
    for i in xrange(rows):
        for j in xrange(columns):
            newpixels[i*columns+newOrder[j]]=pixels[i*columns+j]

    im.putdata(newpixels)

def scramble_rows(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(rows)        
    random.shuffle(newOrder)            #shuffle the order of pixels

    newpixels=copy.deepcopy(pixels)
    for j in xrange(columns):
        for i in xrange(rows):
            newpixels[i*columns+j]=pixels[columns*newOrder[i]+j]

    im.putdata(newpixels)

def unscramble_rows(im,columns,rows):
    pixels =list(im.getdata())

    newOrder=range(rows)        
    random.shuffle(newOrder)            #shuffle the order of pixels

    newpixels=copy.deepcopy(pixels)
    for j in xrange(columns):
        for i in xrange(rows):
            newpixels[columns*newOrder[i]+j]=pixels[i*columns+j]

    im.putdata(newpixels)


#set random seed based on the given password
def set_seed(password):
    passValue=0
    for ch in password:                 
        passValue=passValue+ord(ch)
    random.seed(passValue)

def encrypt(im,columns,rows,password):
    set_seed(password)
    # scramble(im,columns,rows)
    scramble_columns(im,columns,rows)
    scramble_rows(im,columns,rows)

def decrypt(im,columns,rows,password):
    set_seed(password)
    # unscramble(im,columns,rows)
    unscramble_columns(im,columns,rows)
    unscramble_rows(im,columns,rows)

if __name__ == '__main__':
    passwords=["yOs0ZaKpiS","NA7N3v57og","Nwu2T802mZ","6B2ec75nwu","FP78XHYGmn"]
    iterations=1
    filename="0RT8s.jpg"
    im=Image.open(filename)
    size=im.size
    columns=size[0]
    rows=size[1]

    for i in range(iterations):
        encrypt(im,columns,rows,passwords[i])
    im.save(filename.split(".")[0]+"_encrypted.jpg")

    for i in range(iterations):
        decrypt(im,columns,rows,passwords[iterations-i-1])
    im.save(filename.split(".")[0]+"_decrypted.jpg")

3

C # विजेता

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

चित्र 2: यहाँ छवि विवरण दर्ज करें

सोर्स कोड:

class Program
{
    public static void codec(String src, String trg, bool enc)
    {
        Bitmap bmp = new Bitmap(src);
        Bitmap dst = new Bitmap(bmp.Width, bmp.Height);

        List<Point> points = new List<Point>();
        for (int y = 0; y < bmp.Height; y++)
            for (int x = 0; x < bmp.Width; x++)
                points.Add(new Point(x, y));

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                int py = Convert.ToInt32(y + 45 * Math.Sin(2.0 * Math.PI * x / 128.0));
                int px = Convert.ToInt32(x + 45 * Math.Sin(2.0 * Math.PI * y / 128.0));

                px = px < 0 ? 0 : px;
                py = py < 0 ? 0 : py;
                px = px >= bmp.Width ? bmp.Width - 1 : px;
                py = py >= bmp.Height ? bmp.Height - 1 : py;

                int srcIndex = x + y * bmp.Width;
                int dstIndex = px + py * bmp.Width;

                Point temp = points[srcIndex];
                points[srcIndex] = points[dstIndex];
                points[dstIndex] = temp;
            }
        }

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                Point p = points[x + y * bmp.Width];
                if (enc)
                    dst.SetPixel(x, y, bmp.GetPixel(p.X, p.Y));
                else
                    dst.SetPixel(p.X, p.Y, bmp.GetPixel(x, y));
            }
        }

        dst.Save(trg);
    }


    static void Main(string[] args)
    {
        // encode
        codec(@"c:\shared\test.png", @"c:\shared\test_enc.png", true);

        // decode
        codec(@"c:\shared\test_enc.png", @"c:\shared\test_dec.png", false);
    }
}

1

अजगर 3.6 + pypng

राइफल / मास्टर फेरबदल

#!/usr/bin/env python3.6

import argparse
import itertools

import png

def read_image(filename):
    img = png.Reader(filename)
    w, h, data, meta = img.asRGB8()
    return w, h, list(itertools.chain.from_iterable(
        [
            (row[i], row[i+1], row[i+2])
            for i in range(0, len(row), 3)
        ]
        for row in data
    ))

def riffle(img, n=2):
    l = len(img)
    base_size = l // n
    big_groups = l % n
    base_indices = [0]
    for i in range(1, n):
        base_indices.append(base_indices[-1] + base_size + int(i <= big_groups))
    result = []
    for i in range(0, base_size):
        for b in base_indices:
            result.append(img[b + i])
    for i in range(big_groups):
        result.append(img[base_indices[i] + base_size])
    return result

def master(img, n=2):
    parts = [[] for _ in range(n)]
    for i, pixel in enumerate(img):
        parts[i % n].append(pixel)
    return list(itertools.chain.from_iterable(parts))

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('infile')
    parser.add_argument('outfile')
    parser.add_argument('-r', '--reverse', action='store_true')
    parser.add_argument('-i', '--iterations', type=int, default=1)
    parser.add_argument('-n', '--groupsize', type=int, default=2)
    parser.add_argument('-c', '--complex', nargs='+', type=int)

    args = parser.parse_args()

    w, h, img = read_image(args.infile)

    if args.complex:
        if any(-1 <= n <= 1 for n in args.complex):
            parser.error("Complex keys must use group sizes of at least 2")
        if args.reverse:
            args.complex = [
                -n for n in reversed(args.complex)
            ]
        for n in args.complex:
            if n > 1:
                img = riffle(img, n)
            elif n < -1:
                img = master(img, -n)
    elif args.reverse:
        for _ in range(args.iterations):
            img = master(img, args.groupsize)
    else:
        for _ in range(args.iterations):
            img = riffle(img, args.groupsize)

    writer = png.Writer(w, h)
    with open(args.outfile, 'wb') as f:
        writer.write_array(f, list(itertools.chain.from_iterable(img)))


if __name__ == '__main__':
    main()

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

मैंने कुंजी [3, -5, 2, 13, -7] के साथ परिदृश्य को बदल दिया:

लैंडस्केप 3 -5 2 13 -7

दिलचस्प रूप से पर्याप्त है, कुछ दिलचस्प चीजें [3, -5] से होती हैं, जहां मूल छवि से कुछ कलाकृतियों को छोड़ दिया जाता है:

लैंडस्केप 3 -5

यहां सार पैटर्न को कुंजी [2, 3, 5, 7, -11, 13, -17] के साथ बदल दिया गया है:

वृत्त २ ३ ५ les 11 -११ १३ -१ 7

यदि कुंजी में सिर्फ एक पैरामीटर गलत है, तो अनशफल छवि को बहाल नहीं करेगा:

बुरा अनसुना

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