अजगर 3.4
- बोनस 1: स्व उलटा: दोहराता मूल छवि को पुनर्स्थापित करता है।
- वैकल्पिक कुंजी छवि: मूल छवि को केवल उसी कुंजी छवि का उपयोग करके फिर से बहाल किया जा सकता है।
- बोनस 2: आउटपुट में पैटर्न का निर्माण: मुख्य छवि तले हुए पिक्सेल में अनुमानित होती है।
जब एक अतिरिक्त कुंजी छवि का उपयोग करके बोनस 2 प्राप्त किया जाता है, तो बोनस 1 खो नहीं जाता है। यह कार्यक्रम अभी भी उलटा है, बशर्ते इसे फिर से उसी महत्वपूर्ण छवि के साथ चलाया जाए।
मानक उपयोग
टेस्ट छवि 1:
परीक्षण छवि 2:
प्रोग्राम को सिंगल इमेज फाइल के साथ रन करना क्योंकि इसका तर्क पूरी इमेज पर समान रूप से स्क्रैम्ड पिक्सल वाली इमेज फाइल को सेव करता है। तले हुए आउटपुट के साथ इसे फिर से चलाने से एक छवि फ़ाइल को फिर से लागू किए गए स्क्रैबिंग के साथ सहेजा जाता है, जो मूल को पुनर्स्थापित करता है क्योंकि स्क्रैचिंग प्रक्रिया का अपना उलटा होता है।
स्क्रैचिंग प्रक्रिया स्वयं उलटा है क्योंकि सभी पिक्सेल की सूची को 2-चक्रों में विभाजित किया गया है, ताकि प्रत्येक पिक्सेल को एक और केवल एक दूसरे पिक्सेल से स्वैप किया जाए। इसे दूसरी बार चलाने पर हर पिक्सेल को पिक्सेल के साथ स्वैप किया जाता है, जिसके साथ पहली बार स्वैप किया गया था, यह कैसे शुरू हुआ सब कुछ वापस डाल दिया। यदि पिक्सेल की एक विषम संख्या होती है, तो एक ऐसा होगा जो चलता नहीं है।
2-चक्र का सुझाव देने वाले पहले व्यक्ति के रूप में mfvonh के उत्तर के लिए धन्यवाद ।
एक प्रमुख छवि के साथ उपयोग
प्रमुख छवि के रूप में टेस्ट छवि 2 के साथ स्क्रैच टेस्ट छवि 1
मुख्य छवि के रूप में टेस्ट छवि 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 फाइलें बहुत जल्दी संसाधित हो जाती हैं, लेकिन बहुत गर्म चलाने की लागत पर। जब मूल को बहाल किया जाता है, तो यह छवि के बाद जला दिया जाता है:
लेकिन गंभीरता से, एक हानिपूर्ण प्रारूप के परिणामस्वरूप कुछ पिक्सेल रंग थोड़े बदले जाएंगे, जो अपने आप में आउटपुट को अमान्य बनाता है। जब एक मुख्य छवि का उपयोग किया जाता है और पिक्सेल के फेरबदल को क्षेत्रों तक सीमित कर दिया जाता है, तो सभी विकृति उस क्षेत्र के भीतर रखी जाती है जो उस समय हुआ था और फिर उस क्षेत्र में समान रूप से फैल गया जब छवि को बहाल किया जाता है। क्षेत्रों के बीच औसत विरूपण का अंतर उनके बीच एक दृश्य अंतर छोड़ देता है, इसलिए स्क्रैचिंग प्रक्रिया में उपयोग किए गए क्षेत्र अभी भी बहाल छवि में दिखाई देते हैं।
स्क्रैच करने से पहले .png (या किसी भी गैर-हानिपूर्ण प्रारूप) में बदलना यह सुनिश्चित करता है कि अनियंत्रित छवि बिना बर्न या विरूपण के मूल के समान है:
थोड़ा विवरण
- क्षेत्रों पर न्यूनतम 256 पिक्सेल का आकार लगाया जाता है। यदि छवि को उन क्षेत्रों में विभाजित करने की अनुमति दी गई है जो बहुत छोटे हैं, तो मूल छवि अभी भी स्क्रैचिंग के बाद आंशिक रूप से दिखाई देगी।
- यदि विषम संख्या में पिक्सेल के साथ एक से अधिक क्षेत्र हैं तो दूसरे क्षेत्र का एक पिक्सेल पहले पर पुन: असाइन किया गया है, और इसी तरह। इसका मतलब है कि कभी भी केवल एक क्षेत्र में विषम संख्या में पिक्सेल हो सकते हैं, और इसलिए केवल एक पिक्सेल अनियंत्रित रहेगा।
- एक तीसरा वैकल्पिक तर्क है जो क्षेत्रों की संख्या को सीमित करता है। उदाहरण के लिए इसे 2 पर सेट करने से दो टोन तले हुए चित्र मिलेंगे। इसमें शामिल छवियों के आधार पर यह बेहतर या खराब लग सकता है। यदि एक संख्या यहां निर्दिष्ट की गई है, तो छवि को केवल उसी संख्या का उपयोग करके फिर से बहाल किया जा सकता है।
- मूल छवि में अलग-अलग रंगों की संख्या भी क्षेत्रों की संख्या को सीमित करती है। यदि मूल छवि दो टोन है, तो कुंजी छवि या तीसरे तर्क की परवाह किए बिना, केवल अधिकतम 2 क्षेत्र हो सकते हैं।