第十六届全国大学生信息安全竞赛创新实践能力赛 初赛 国粹 解析(基于opencv图像识别的坐标分析)

a.pngk.png的长度是一样的,总共341张牌,牌的类型根据题目.png总共有42种,而题目.png有两层,猜测第一层为Y轴,第二层为X

 于是我们先将每张麻将的图像进行切分,方便进行图像识别的比较

图像切分脚本

import os
from PIL import Image

pic=Image.open('C:\\Users\\Lenovo\\Desktop\\1.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\\Lenovo\\Desktop\\cuted\\{i}.png')
    x+=53

得到切分完毕的文件夹

 于是将a与k图像进行识别匹配,并将坐标保存,绘制为图像

图像识别+绘图脚本

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\\Lenovo\\Desktop\\cuted'):
    for files in filename:
        f=eval(files.split(".")[0])#将.前面文件名单独储存,并化为数字
        images.append(f)#储存文件夹内的图片名称
images.sort()#整理文件名顺序


img_rgb = cv2.imread('C:\\Users\\Lenovo\\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\\Lenovo\\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\\Lenovo\\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\\Lenovo\\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\\Lenovo\\Desktop\\y.jpg", img_rgb)#保存识别后的图片
cv2.waitKey(0)
for i in range(0,343):
    print(f'{x[i]} {y[i]}')
'''with open('C:\\Users\\Lenovo\\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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值