继续挑战
第22题地址copper.html
- 网页标题是
emulate
,题目内容为空,源码里面有一行隐藏内容:<!– or maybe white.gif would be more bright–>
没什么说的,先把white.gif搞下来看看:
from io import BytesIO
import requests
from PIL import Image
with requests.Session() as sess:
sess.auth = ('butter', 'fly')
response = sess.get('http://www.pythonchallenge.com/pc/hex/white.gif').content
img = Image.open(BytesIO(response))
print(img.info)
{'version': b'GIF89a', 'background': 9, 'duration': 10, 'comment': b'Created with The GIMP', 'extension': (b'NETSCAPE2.0', 75), 'loop': 0}
考虑到这是个GIF
动态图片,我们取几帧看看:
import matplotlib.pyplot as plt
from PIL import ImageSequence
%matplotlib inline
imgs = ImageSequence.all_frames(img)
print('frames:', len(imgs))
for i, im in enumerate(imgs[:5]):
plt.subplot(1, 5, i + 1)
plt.imshow(im)
plt.axis('off')
plt.show()
frames: 133
都是一团黑。。。
我们开始读题干吧。需要把图片弄得亮一些,难道除了黑色之外还有别的像素点?结合图片名字white.gif
看应该是的:
from PIL import ImageSequence
for im in ImageSequence.all_frames(img)[:10]:
print(im.getcolors())
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
[(39999, 0), (1, 8)]
是的!!
所有的133图片帧里面,除了39999个像素是黑的以外,还有孤独的1个像素是第8
号颜色:
print(img.getpalette()[8 * 3 : 9 * 3])
[8, 8, 8]
呃,也就是比黑色稍微亮一点点而已。
我们把它弄得明显一点看看:
import numpy as np
from PIL import ImageDraw, ImageSequence
for i, im in enumerate(ImageSequence.all_frames(img)):
if i % 70 == 0:
plt.show()
plt.subplot(7, 10, i % 70 + 1)
brighter = list(im.getdata()).index(8)
bpoint = np.array((brighter % im.width, brighter // im.width))
draw = ImageDraw.Draw(im)
draw.ellipse((tuple(bpoint - 5), tuple(bpoint + 5)), 255)
plt.imshow(im)
plt.axis('off')
plt.show()
貌似这个亮点基本上都位于图片的正中间。我们还是把坐标提取出来吧。
from collections import Counter
from PIL import ImageSequence
bpoints = []
for im in ImageSequence.Iterator(img):
brighter = list(im.getdata()).index(8)
bpoints.append((brighter % im.width, brighter // im.width))
print(Counter(bpoints))
Counter({(100, 102): 31, (102, 100): 28, (98, 100): 25, (100, 98): 14, (102, 102): 10, (102, 98): 9, (98, 102): 6, (100, 100): 5, (98, 98): 5})
总共只有(98, 100, 102)
的两两组合共9种情况。
现在可以结合题目的图片是一个控制杆和标题emulate
仿真来看,这些坐标点像是控制杆的9个不同的位置,而(100, 100)
应该是控制杆的中间位置,其他位置像是在指挥什么东西在移动。
对!我们可以用画笔来进行这个模拟:
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw
num = Counter(bpoints)[(100, 100)]
index = 0
im = None
for point in bpoints:
if point == (100, 100):
index += 1
if im:
plt.imshow(im)
plt.subplot(1, num, index)
plt.axis('off')
im = Image.new('RGB', (50, 50))
draw = ImageDraw.Draw(im)
lpoint = (25, 25)
else:
cpoint = tuple(l + p - 100 for l, p in zip(lpoint, point))
draw.line((lpoint, cpoint), 'white')
lpoint = cpoint
plt.imshow(im)
plt.show()
好了,地址改为bonus.html,来到了下一题。