puzzle

点击此处获得更好的阅读体验


WriteUp来源

https://mp.weixin.qq.com/s/AzUrC5JD-bVb8mDL0JB4bQ

题目描述

拼图的好处: 1、动手又动脑,开发智力,增加几何空间感 2、你可以在拼好后的作品上发挥想象,绘上与众不同的色彩,这样,你的作品就成了独一无二的艺术品了。 3、与家人或朋友一起拼装,增加了交流,增进感情与亲情 这么多的益处,所以赶紧来玩吧~ 附件下载 提取码(GAME)

题目考点

  • 拼图

解题思路

官方WP

首先题目附件得到一张demo图片和1125张切割后的图片。

根据题目名称和附件猜测拼图题目。 开始尝试利用CV2库的图像匹配算法(2020DDCTF)的方法,计算匹配度去拼图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import cv2
from PIL import Image
import numpy as np
import os
import shutil
import threading
# 读取目标图片
source = cv2.imread(r"D:\chunqiuganme\demo.jpg")
# 拼接结果
target = Image.fromarray(np.zeros(source.shape, np.uint8))
# 图库目录
dirs_path = r"D:\
"
# 差异图片存放目录
dst_path = r"D:\chunqiuganme\difference"
def match(temp_file):
# 读取模板图片
template = cv2.imread(temp_file)
# 获得模板图片的高宽尺寸
theight, twidth = template.shape[:2]
# 执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED
result = cv2.matchTemplate(source, template, cv2.TM_SQDIFF_NORMED)
# 归一化处理
cv2.normalize(result, result, 0, 1, cv2.NORM_MINMAX, -1)
# 寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
target.paste(Image.fromarray(template), min_loc)
return abs(min_val)
class MThread(threading.Thread):
def __init__(self, file_name):
threading.Thread.__init__(self)
self.file_name = file_name
def run(self):
real_path = os.path.join(dirs_path, k)
rect = match(real_path)
if rect > 6e-10:
print(rect)
shutil.copy(real_path, dst_path)
count = 0
dirs = os.listdir(dirs_path)
threads = []
for k in dirs:
if k.endswith('jpg'):
count += 1
print("processing on pic" + str(count))
mt = MThread(k)
mt.start()
threads.append(mt)
else:
continue
for t in threads:
t.join()
target.show()
target.save(r"d:\chunqiuganme\flag.jpg")

但是得到的结果是:

demo.jpg:

差距很大。仔细发现每张图片都被椒盐噪声污染过。

科普:椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。盐和胡椒噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。

接下来就对每张切割后的图片去噪声了,对已经被椒盐噪声污染的图片进行中值滤波,平滑图片。

科普:在一连串数字{1,4,6,8,9}中,数字6就是这串数字的中值。由此我们可以应用到图像处理中。依然我们在图像中去3*3的矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import cv2
from PIL import Image
import numpy as np
import os
import cv2
import numpy as np
def median_filter(img, K_size=3):
H, W, C = img.shape
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2, C), dtype=np.float)
out[pad:pad+H, pad:pad+W] = img.copy().astype(np.float)
tmp = out.copy()
for y in range(H):
for x in range(W):
for c in range(C):
out[pad+y, pad+x, c] = np.median(tmp[y:y+K_size, x:x+K_size, c])
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
return out
#被噪声污染图片文件夹
dirs_path="./"
count = 0
dirs = os.listdir(dirs_path)
threads = []
for k in dirs:
if k.endswith('JPG'):
count += 1
print("processing on pic" + str(count))
img = cv2.imread(k)
out1 = median_filter(img, K_size=3)
cv2.imwrite("./output/"+coun+".jpg", out1)
cv2.waitKey(0)
cv2.destroyAllWindows()

被污染图片文件下创建output命名的文件夹,在当前目录下运行EXP。(k_size代表孔径的线性尺寸,可以提高,虽然椒盐噪声没了,但是图像也变的模糊,因为ksize太大了,把有用的信息也用中值代替了,误差就逐渐显现出来)

去噪前:

去噪后:

明显好多了。接下来重新使用python中CV2库的图像匹配算法进行匹配。

大佬WP by 魔法少女雪殇

简单拼图题,丢入ps直接拼

Flag

1
flag{w9w45my6x8kk4e8gp9nqm6j2c154wad49}