看到这道题目的时候我有点茫然,不知道从什么地方开始下手,经过师傅的提示,我们先要做出一个坐标,根据题目.png
总共有42
种,而题目.png
有两层,猜测第一层为Y轴
,第二层为X
轴,所以我们先要对题目.png进行切片,方便我们进行图片识别。
我们先创建一个新的文件夹 ,用来存储切出来的图片。
第三方是pillow,我们需要提前准备好。
如果安装的时候太慢了就可以换一下源,简单的提供了几个
清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:https://mirrors.aliyun.com/pypi/simple/
中国科技大学:https:pypi.mirrors.ustc.edu.cn/simple/
eg:pip install pillow -i +镜像源
import os
from PIL import Image
pic=Image.open('C:\\Users\\86187\\Desktop\\123.png')
x=0
y=0
for i in range(0,42):
#m=Image.new('RGB',(431,73))
n=pic.crop((x,y,x+53,y+73))
n.save(f'C:\\Users\\86187\\Desktop\\cuted\\{i}.png')
x+=53
此时我们就需要知道a和k里面有多少张麻将,刚开始就慢慢去数,之后发现一个比较快的方法,这里我们会发现每张图片的大小都是一样的,看到图片宽的像素值是18073,18073的因式分解为11*31*53,再去看看第一张麻将和第二张麻将,宽度的界限值差不多是五十左右,说明其中的一个因子大概率是53,所以18073除以53是341,所以a和k里面的麻将数量都是341。
再去看看题目.png下面的一排多了一张一万的,后面的是以123的顺序进行排列的,所以第二排的第一张是没有什么用的。
于是将a与k图像进行识别匹配,并将坐标保存,绘制为图像
这里需要用到python的第三方库,opencv2
import cv2
import numpy as np
import os
import turtle as t
import time
images=[]
x=[0 for i in range(343)]
y=[0 for i in range(343)]
for cuedir,dirs,filename in os.walk('C:\\Users\\86187\\Desktop\\cuted'):
for files in filename:
f=eval(files.split(".")[0])#将.前面文件名单独储存,并化为数字
images.append(f)#储存文件夹内的图片名称
images.sort()#整理文件名顺序
img_rgb = cv2.imread('C:\\Users\\86187\\Desktop\\a.png')#识别图
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
#shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度
for i in range(len(images)):
template = cv2.imread(f'C:\\Users\\86187\\Desktop\\cuted\\{images[i]}.png', 0) # 识别模板
h, w = template.shape[:2] # 读取宽高
result = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)#标准相关匹配
threshold = 0.9
# 取匹配程度大于%90的坐标
loc = np.where(result >= threshold)
#print(loc)
# np.where返回的坐标值(x,y)是(h,w),注意h,w的顺序
for pt in zip(*loc[::-1]):
#print(pt)
m=pt[0]//53
x[m]=images[i]
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imwrite("C:\\Users\\Lenovo\\Desktop\\x.jpg", img_rgb)
img_rgb = cv2.imread('C:\\Users\\86187\\Desktop\\k.png')#识别图
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
#shape函数的功能是读取矩阵的长度
for i in range(len(images)):
template = cv2.imread(f'C:\\Users\\86187\\Desktop\\cuted\\{images[i]}.png', 0) # 识别模板
h, w = template.shape[:2] # 读取宽高
result = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)#标准相关匹配
threshold = 0.9
# 取匹配程度大于%90的坐标
loc = np.where(result >= threshold)
#print(loc)
# np.where返回的坐标值(x,y)是(h,w),注意h,w的顺序
for pt in zip(*loc[::-1]):
#print(pt)
m=pt[0]//53
y[m]=images[i]
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imwrite("C:\\Users\\86187\\Desktop\\y.jpg", img_rgb)#保存识别后的图片
cv2.waitKey(0)
for i in range(0,343):
print(f'{x[i]} {y[i]}')
'''with open('C:\\Users\\86187\\Desktop\\gnuplot.txt','w') as gn:
for i in range(0,342):
gn.write(f'{x[i]} {y[i]}\n')#坐标导出为一个txt文件'''
#绘制模块
t.speed(100)
t.pu()
for i in range(0,343):
t.goto(y[i]*5,-x[i]*5)
t.pd()
t.circle(1,360)
t.pu()
time.sleep(1000)#方便截图
最后的结果:flag{202305012359}
我们也可以看看其它师傅的方法
import io
import hashlib
path = "C:\\Users\\HK\\Desktop\\a.png"
im = Image.open(path)
width = im.width
height = im.height
block_width = 53
block_height = 73
md5_list = []
for x in range(0, width, block_width):
tmp = im.crop((x, 0, x + block_width, height))
with io.BytesIO() as output:
tmp.save(output, format="JPEG")
binary_data = output.getvalue()
md5 = hashlib.md5(binary_data).hexdigest()
md5_list.append(md5)
tmp_list = []
for i in range(len(md5_list)):
if md5_list[i] != md5_list[i - 1]:
tmp_list.append(md5_list[i])
alpbet_list = {}
for i in range(len(tmp_list)):
alpbet_list[tmp_list[i]] = str(i)
path_a = "C:\\Users\\HK\\Desktop\\a.png"
im = Image.open(path_a)
width = im.width
out_x = []
for x in range(0, width, block_width):
tmp = im.crop((x, 0, x + block_width, height))
with io.BytesIO() as output:
tmp.save(output, format="JPEG")
binary_data = output.getvalue()
md5 = hashlib.md5(binary_data).hexdigest()
try:
out_x .append(alpbet_list[md5])
except:
pass
path_k = "C:\\Users\\HK\\Desktop\\k.png"
im = Image.open(path_k)
width = im.width
out_y = []
for x in range(0, width, block_width):
tmp = im.crop((x, 0, x + block_width, height))
with io.BytesIO() as output:
tmp.save(output, format="JPEG")
binary_data = output.getvalue()
md5 = hashlib.md5(binary_data).hexdigest()
try:
out_y.append(alpbet_list[md5])
except:
out_y.append("0")
out = Image.new("RGB",(100,50),"white")
for i in range(len(out_x)):
x = int(out_x[i])
y = int(out_y[i])
out.putpixel((x,y),(0,0,0))
out.save("out.png")
师傅的 主要的思路是a是x坐标,k是y坐标
所以这道题主要是要建立起坐标。