当前位置: 首页 > news >正文

象棋图片转FEN字符串详细教程

如把下图

a1

转换成:3ak4/7R1/3aCcN2/p7p/6r2/9/Pr1p1n2P/4B1p2/9/2BAKA1R1

模型21K,Intel N100上训练时间0.969秒,识别时间0.957秒。识别率好像是100%

一、安装软件包

apt install python3-scipy python3-pil

二、建目录data, data\0 a A b B c C k K n N p P r R

识别就是分类。每个目录对应一类,存放属于该类的所有图片。

三、收集和预处理数据

百度搜相似图片。运行prepare.py: 

#!/usr/bin/python
from common import *
from pathlib import Pathfn = sys.argv[1]
a = slice(fn)
fn = Path(fn).stem
for i in range(len(a)):cv.imwrite(f'data/{fn}-{i}.png', a[i])exit()from PIL import Image, ImageDraw
img = Image.open(sys.argv[1])
id = ImageDraw.Draw(img)
sz = img.size; S,L,T = size(sz[0], sz[1])
for yy in range(10):for xx in range(9):y = T + yy * Sx = L + xx * Sid.rectangle((x,y,x+S,y+S), outline=(0,255,0,255), width=1)
img.show()
View Code

如何知道square的大小?图片查看器Gwenview和IfranView显示选择区的大小。或者用OpenCV的演示程序squares.py来高射炮打蚊子。

人工标注数据。文件管理器里按图标查看,把比如红车的改名为首字母为R。按大小排序,改名时列表不会来回乱变。

#!/usr/bin/python
from glob import glob
from shutil import moves = 'rnbakcp'; s += s.upper() + '0'for c in s:for p in [c + '*.png', c + '*.jpg']:for f in glob(p): move(f, c)
View Code

四、训练,运行train.py

from common import *
from sklearn.svm import SVC
import pickledata_dir = "data"
features = []; labels = []
for label in os.listdir(data_dir):label_dir = os.path.join(data_dir, label)if not os.path.isdir(label_dir): continuefor img_file in os.listdir(label_dir):img_path = os.path.join(label_dir, img_file)img = cv.imread(img_path)if img is None: continuefeature = extract_features(img)if feature is None: continuefeatures.append(feature)labels.append(label)model = SVC(kernel='rbf', C=10, gamma=0.1)
model.fit(features, labels)
with open("model.pkl", "wb") as f: pickle.dump(model, f)
View Code

五,识别

#!/usr/bin/python
from common import *
import pickleb = [[' '] * 9 for i in range(10)]with open('model.pkl', 'rb') as f: model = pickle.load(f)
a = slice(sys.argv[1])
for i in range(len(a)):f = extract_features(a[i])b[i // 9][i % 9] = model.predict([f])[0]def brd2fen (b):f = ''for y in range(10):n = 0for x in range(9):c = b[y][x]if c == '0': n += 1else:if n: f += str(n)f += c; n = 0if n: f += str(n)if y != 9: f += '/'return fprint(brd2fen(b))
for i in range(10): print(b[i])

鄙人的brd2fen是最长的。:-)

五 common.py

import numpy as np
import cv2 as cv
import pickle
import os
import sysdef size (W, H):S = 68 if W == 640 else 86 # sizeL = (W - 9 * S) // 2 # leftT = (H - 10 * S) // 2 # topreturn S,L,Tdef slice (fn):all = []img = cv.imread(fn); H,W = img.shape[:2]S,L,T = size(W, H)mask = np.zeros((S, S), dtype=bool)HS = S // 2; R = HS - 4 # half S & radiusfor y in range(S):for x in range(S):# 圆形mask. hypotenuse: 斜边if np.hypot(x - HS, y - HS) > R: mask[y, x] = Truefor yy in range(10):for xx in range(9):x = L + xx * S; y = T + yy * Sx2 = min(W, x + S); y2 = min(H, y + S)sl = img[y:y2, x:x2]; sl[mask] = 0all.append(sl)return alldef extract_features (img):gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)_, bin = cv.threshold(gray, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)contours, _ = cv.findContours(bin, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)if len(contours) == 0: return Nonecontour = max(contours, key=cv.contourArea)moments = cv.moments(contour)hu_moments = cv.HuMoments(moments).flatten()# 在阴影或强光条件下,RGB会整体变化,而HSV的色调H和饱和度S相对稳定,更适合颜色识别任务。V是亮度。hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)color_features = np.concatenate([cv.mean(hsv)[:3],cv.meanStdDev(hsv)[1].flatten()])return np.concatenate([hu_moments, color_features])
View Code

 

六 其它

circles.py没有用到,但我辛苦地调了参数,愚蠢地用直径去设置min/max raidus,一并附上。

#!/usr/bin/python
import numpy as np
import cv2 as cv
import sys
import osfn = sys.argv[1]
img = cv.imread(fn); height, width = img.shape[:2]
fn = os.path.basename(fn)circles = cv.HoughCircles(cv.cvtColor(img, cv.COLOR_BGR2GRAY), # 只支持灰度cv.HOUGH_GRADIENT, # 梯度,not 渐变1, # 改成2影响很大60, # Minimum distance between the centers of the detected circlesparam1=150, # 减小可增加检测到的圆数量param2=35, # The smaller it is, the more false circles may be detected.minRadius=30,maxRadius=48
) # 返回shape为(1,n,3)的ndarray
if circles is None: exit()
circles = np.around(circles).astype(int)mask = np.zeros((96,96), dtype=bool)
for y in range(96):for x in range(96):# 以(48,48)为圆心,40为半径的mask. hypotenuse 斜边if np.hypot(x - 48, y - 48) > 40: mask[y, x] = Truefor x,y,r in circles[0]:cv.circle(img, (x, y), r, (0, 255, 0), 2)x1 = max(0, x - r); x2 = min(width, x + r)y1 = max(0, y - r); y2 = min(height, y + r)ps = cv.resize(img[y1:y2, x1:x2], (96,96))ps[mask] = 255#cv.imwrite(f'tmp/{fn}-{x},{y}.png', ps)from PIL import Image
img = Image.fromarray(cv.cvtColor(img, cv.COLOR_BGR2RGB))
img.show()print(f'{circles.shape[1]} pieces')
View Code

 

http://www.hskmm.com/?act=detail&tid=28579

相关文章:

  • 面向对象抽象,接口多态综合-动物模拟系统
  • MinGW-即时入门-全-
  • 自然语言处理在风险识别中的应用
  • cat
  • qt everywhere souce code编译 - 实践
  • 2023 CCPC final G
  • 2025 年高可靠性测试设备/HALT/HASS/Halt/Hass/厂家制造商推荐榜:聚焦高效质量解决方案,助力企业产品升级
  • 八字手链人物传记计划——旭
  • 20232309 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • 亚马逊发布基于Linux的Vega OS电视系统,禁止侧载应用
  • .net9.0 JWT AUTH2.0 添加身份认证授权
  • 扣子系列教程
  • 解决vscode中用npm报错
  • MATLAB复杂曲线曲面造型及导函数实现
  • 2025 年最新月嫂培训机构推荐榜单:短期 / 精英 / 金牌 / 高端月嫂培训及就业推荐,精选优质机构
  • OOP-实验一
  • 达梦使用jemalloc内存分配器
  • 2025 年深圳/龙岗/龙华/罗湖/南山/旧房翻新/出租房/二手房/老房/装修公司推荐:聚焦品质与服务,助您轻松焕新家
  • 2025 年中频炉厂商最新推荐排行榜权威发布,深度剖析应达电气等优质企业核心优势及选购要点节能/智能/自动化成套/高效率/智能感应加热中频炉厂家推荐
  • 2025 年气体/实验室/调压/气路/减压阀厂家推荐榜:聚焦安全与专业,助力各行业精准选品
  • 摸鱼混子回归 - ZERO
  • vue3实现抓拍并上传
  • 2025 年国内润滑油厂商最新推荐榜:聚焦优质品牌实力,助力企业精准选品润滑油净化/过滤/回用/液压油润滑油过滤厂商推荐
  • 纯前端实现项目过期
  • 基于形态学的权重自适应图像去噪的MATLAB实现
  • 2025 年油水分离器 / 气液分离器 / 液固分离器 / 水分离器 / 油分离器厂家推荐:西安同大技术沉淀与流体净化解决方案解析
  • 2025 年过滤器厂家最新推荐排行榜:聚焦烛式 / 金属 / 非金属 / 化工 / 精密过滤器等多类型设备,精选优质品牌助企业高效选型液固/高效/气固/催化剂过滤器厂家推荐
  • OOP-实验1
  • 2025 年立式/立式全钢板/青黄储/液压打包机厂家推荐榜:聚焦实用需求,精选高适配设备助力企业降本增效
  • DNS服务