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

自制带得分和推荐走法的象棋视频

① 到东萍象棋网可以下载许多棋谱。我用程序下载了1万多个推荐的,grep -v (--invert-match)去掉了和棋的,还有6813个。bash+wget干的,python的连不通(要送user-agent?)

pu.txt 6813行,形如:

河北金环建设象棋队-申鹏-胜-山东省棋牌运动管理中心-张瑞峰=694712321927102226250010091972427967706289798070777362817343

用Python按走法长度升序,用了dict,长度做key和sorted(keys),setdefault(k, []).append(...)

② ffmpeg把一系列bmp压缩成mp4,几十步棋才几十到数百KB,KB, KB. /dev/shm是内存,不担心SSD磨损。总之这事可干,就是CPU风扇时不时会响。引擎是从象棋巫师ElephantEye的改来的,在Intel N100上每秒600万节点,中国象棋云库查询是0.98几,单位是G。

ee.py

from subprocess import Popen, PIPEclass EleEye(Popen):BM = 'bestmove'def __init__(m): Popen.__init__(m, 'eemod', stdin=PIPE, stdout=PIPE, text=True)def send(m, s): m.stdin.write(s + '\n'); m.stdin.flush()def recv(m):out = ''while True:s = m.stdout.readline()out += s.replace('info ', '')if s.find(m.BM) != -1: return outdef get_score(m, f):m.send('position fen ' + f + '\ngo')n = -900; fx = fy = tx = ty = -1while True:s = m.stdout.readline()i = s.find('score ')if i != -1:i += 6j = s.find(' ', i)n = int(s[i:j]) # j=-1: oki = s.find(m.BM)if i != -1:if i != 0: break # nobestmove# b0c2fx = ord(s[9]) - ord('a')tx = ord(s[11]) - ord('a')fy = ord('9') - ord(s[10])ty = ord('9') - ord(s[12])breakif n > 900: n = 900elif n < -900: n = -900return n,fx,fy,tx,tyee = EleEye()
View Code

img.py

#! /usr/bin/python3from PIL import Image as I, ImageDraw, ImageFont #, ImageFilterdef get_circle_img(i):img = I.new('RGBA', (144,144), (255,255,255,0)) # no LAd = ImageDraw.Draw(img)f = (255,255,255,255) if i else (0,0,0,255)d.ellipse((0,0,132,132), fill=f, outline=(68,68,68,255), width=8)return img.resize((36,36), I.LANCZOS)#return img.filter(ImageFilter.GaussianBlur(radius=1))

red = get_circle_img(1); hei = get_circle_img(0)FNT = '/usr/local/share/fonts/汉/汉仪旗黑.ttf'
fnt = ImageFont.truetype(FNT, 20)
fnt2 = ImageFont.truetype(FNT, 14)dic = {"r":"", "n":"", "c":"", "b":"", "B":"", "a":"", "A":"", "k":"", "K":"", "p":"", "P":""}
dic['R'] = dic['r']; dic['N'] = dic['n']; dic['C'] = dic['c']jpg = I.open('brd.jpg')def fen2img (f, nm, str=None):if nm.find('bmp') == -1:S = 40; L = 6; T = 4brd = I.new('L', (368,400), 255)bmp = Falseelse:S = 40; L = 6; T = 32brd = I.new('L', (368,432), 255)bmp = Truebrd.paste(jpg, (L,T-4))id = ImageDraw.Draw(brd)#id.rectangle([(0, 408), (432, 800)], fill='blue')def draw(c, x, y):if c.isupper(): img = red; tc=0else: img = hei; tc=255brd.paste(img, (x,y), mask=img.split()[-1])id.text((x+6,y+4), dic[c], font=fnt, fill=tc)f = f.split('/')b = [[' '] * 9 for i in range(10)]for y in range(10):x = 0for i in range(len(f[y])):c = f[y][i]j = ord(c) - ord('0')if j >= 1 and j <= 9: x += jelse:draw(c, L+x*S, T+y*S); b[y][x] = c; x += 1if str != None:bb = fnt2.getbbox(str)id.text(((brd.size[0]-bb[2]+bb[0])/2, 5), str, font=fnt2, fill=0)if not bmp: brd = brd.resize((736,800), I.NEAREST)brd.save(nm, compress_level=9) # smaller than jpegif __name__ == '__main__':import sysif 'cover' in sys.argv:brd = I.new('L', (1920,1080), 255)brd.save('cover.png', compress_level=9)else: fen2img(input().replace(' ', ''), '/t/fen.png')
View Code

pu.py

#! /usr/bin/python3
from ee import *
from img import *def fen2brd ():global ba = f.split('/')for y in range(10):x = 0for i in range(len(a[y])):c = a[y][i]j = ord(c) - ord('0')if j >= 1 and j <= 9: x += jelse: b[y][x] = c; x += 1def brd2fen ():global ff = ''for y in range(10):n = 0for x in range(9):c = b[y][x]if c == ' ': n += 1else:if n: f += str(n)f += c; n = 0if n: f += str(n)if y != 9: f += '/'return fdef mv2str (fx, fy, tx, ty):if fx < 0: return Noned = abs(fy - ty)c = b[fy][fx]; red = c < 'a'm = p[c]x = "九八七六五四三二一" if red else "123456789"m += x[fx]if fy == ty: m += "" + x[tx]else:m += "" if red == (fy > ty) else "退"if   c in "RCPK": m += "零一二三四五六七八九"[d]elif c in "rcpk": m += "0123456789"[d]else: m += x[tx]return mp = {"r":"", "n":"", "c":"", "b":"", "B":"","a":"", "A":"", "k":"", "K":"", "p":"", "P":""}
p['R'] = p['r']; p['N'] = p['n']; p['C'] = p['c']
b = [[' '] * 9 for i in range(10)]
f = 'rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR'; fen2brd()# 开局,go 1500 7分,300 4分,bm都是兵七进一。这个分是假设走了bm.
# 若实际帅五进一呢?应该用黑分如17。红走棋后,考虑黑方的最佳应对。
a = [4]; bms = ['兵七进一']; n = 1
s = input().split('=')[1]
for i in range(0, len(s), 4):# 处理(红)实际走法fx,fy,tx,ty = int(s[i]), int(s[i+1]), int(s[i+2]), int(s[i+3])m = mv2str(fx,fy,tx,ty)b[ty][tx] = b[fy][fx]; b[fy][fx] = ' ' # 不能放在mv2str前# 处理(黑)r,fx,fy,tx,ty = ee.get_score(brd2fen() + (' b' if n % 2 else ' w'))# brd2fen() modifies f
  a.append(r); bms.append(mv2str(fx,fy,tx,ty))##bm = bms[-2]if bm and m != bm: m += '_' + bmif n % 2: print(f'{n // 2 + 1}. {m}', end=' ')else: print(m, flush=True)##fen2img(f, f'/t/{n:02d}.bmp', m + ('' if n % 2 else '') + str(r))n += 1exit()fen2img(f, '/t/t.png')import matplotlib.pyplot as plt
#import numpy as np
plt.figure(figsize=(8, 6), dpi=72)
x = a[::2]
plt.plot(x, color='#FF0000', linewidth=1)
plt.plot(a[1::2], color='#000000', linewidth=1)
plt.xticks(rotation=45)
n = len(x)
plt.xticks(ticks=list(range(n)), labels=list(range(1, n+1)))  # 下标+1作为刻度
#plt.xticks(ticks=np.arange(len(x)), labels=np.arange(1, len(x)+1))
#plt.axis('off')

plt.savefig('/t/score.png', bbox_inches='tight', pil_kwargs={'compress_level':9})
#plt.show()
View Code

pu

# pu.htm里无对手信息; move用3字符编码if [[ $# -lt 1 ]]; then exit; fin=$1 # n=$(expr $1 + 10)
p=`sed -n ${n}p pu.txt`echo $p | xclip -f -selection clipboardif [[ $# -eq 1 ]]; then    exit; fiecho 'Pressing Enter will rm -f /t/*'
read
rm -f /t/*t=/t/t.txt
echo $p >$t
echo $p | pu.py | tee -a $t
echocd /t
v=t.mp4
ffmpeg -framerate 0.5 -i %02d.bmp -r 8 -vf format=gray,format=yuv420p -c:v h264 -b:v 100k -preset fast -loglevel 0 $v
rm -f *.bmp
#ls -lh $v | awk '{print $5}' >>$t
#cp ~/xq/cover.png .
cd - >/dev/null#kwrite $t 2>/dev/null &
View Code

视频

分辨率为368x432,都是16的倍数。除了VLC播放时会截去下面一块,ffplay,手机等都没事。在海信A5这样的墨水屏手机上,视频播放器默认背景也是大白纸,一点都不闪,真是“纸上的东西动起来了”。

0e791cfbd5264a9086da32c0ff943aed~tplv-obj_720_1041

手抖拍糊了。黑边为手机实际边框。

man ffplay, While playing, q/Esc quit; p/Space pause

VLC 3.0.21 Vetinari, debian 6.1.0-18-amd64, Intel N100,播576x432的也截(4:3, 都是16的倍数)。未排除是硬件解码器的问题。

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

相关文章:

  • DP分析黑科技——闫氏DP分析法
  • MUGEN游戏引擎等一系列相关杂谈
  • # 20232313 2025-2026-1 《网络与系统攻防技术》实验一实验报告 - 20232313
  • 一生一芯学习:PA2:输入输出
  • vector使用中的一个小问题
  • OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering() - 指南
  • 2025.10.7——2绿
  • 完整教程:无人机避障——感知部分(Ubuntu 20.04 复现Vins Fusion跑数据集)胎教级教程
  • 我真的博了
  • 2025.10.6——1绿1蓝
  • 深入解析:人工智能-Chain of Thought Prompting(思维链提示,简称CoT)
  • 年龄排序
  • 二分图最大匹配 输出具体方案
  • 我的联想小新潮7000笔记本的优化
  • Go语言之接口与多态 -《Go语言实战指南》 - 指南
  • 地球科学概论
  • 2025多校冲刺CSP模拟赛4 总结
  • 多路归并、败者树、置换-选择排序、最佳归并树
  • 看vue文档记录(未整理)
  • Spring5笔记
  • 50天50个前端项目 - HTML/CSS和JavaScript实战合集
  • [BalticOI 2002] Tennis Club (Day1) 解题报告
  • 党徽
  • ZKEACMS:基于ASP.Net Core开发的开源免费内容管理系统
  • MySQL面试题汇总
  • 穷人的中国象棋打谱程序
  • 文件系统的层次结构
  • oracle 19c学习笔记2
  • 文件保护
  • 一些数数杂题