端午整个烂活。
龙舟争渡2025
旗帜颜色的识别方法选了个最笨的,直接截取那块,然后矩阵相减求F范数(二模),匹配差距最小的那个即可,因此需要提前把所有情况的截图准备好,完整的图片材料和演示视频在https://github.com/caoyang-sufe/LongZhouZhengDu2025
目前速度不是特别快,但也基本够用了。如果间隔取太小容易出错,因为截屏速度跟不上。
# -*- coding: utf-8 -*-
# @author: caoyang
# @email: [email protected]
import cv2
import time
import numpy
import pyautogui
from PIL import Image
from numpy.linalg import norm
from pynput.keyboard import Key, Controller as KeyController
from pynput.mouse import Button, Controller as MouseController
import numpy as np
Y1, Y2, X1, X2 = 200, 400, 830, 1090 # 这组参数适配1920×1080尺寸的屏幕j
color_to_key = {'y': 'd', 'r': 'f', 'b': 'j', 'g': 'k'}
def easy_show(image: numpy.ndarray, window_title: str="image") -> None:
"""
Show a image in a new window.
"""
cv2.imshow(window_title,image)
cv2.waitKey(0)
cv2.destroyAllWindows()
def get_screenshot():
image = pyautogui.screenshot()
image = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)
return image
def load_labels():
labels = dict()
for color in "yrbg":
for n in "12":
image = Image.open(f"./temp/{color}{n}.png")
image = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)
clipped_image = image[Y1: Y2, X1: X2, :]
labels[f"{color}{n}"] = clipped_image
return labels
# 判断旗帜颜色及点击次数
def classify_label(screenshot, labels):
clipped_image = screenshot[Y1: Y2, X1: X2, :]
diffs = {}
for key, label in labels.items():
diff = norm(label - clipped_image)
diffs[key] = diff
print(diffs)
predicted_label = min(diffs, key = lambda x: diffs[x])
return predicted_label
def run():
keyboard_controller = KeyController()
while True:
screenshot = get_screenshot()
labels = load_labels()
predicted_label = classify_label(screenshot, labels)
color = predicted_label[0]
key_char = color_to_key[color]
n = int(predicted_label[1])
for _ in range(n):
keyboard_controller.press(key_char)
time.sleep(.05)
keyboard_controller.release(key_char)
time.sleep(.05)
time.sleep(.1)
time.sleep(2)
run()
烂活完了顺便延申一点,感觉录屏还是有点问题,cv2.waitKey()
总是捕获不到键位,之前就发现过这个问题,不知道怎么回事,问了一下deepseek,还是得用ffmpeg才行
pyautogui
和 OpenCV
录制屏幕这种方法通过不断截取屏幕画面并将其合成为视频文件来实现录屏。
import pyautogui
import cv2
import numpy as np
# 设置录屏参数
screen_size = pyautogui.size() # 获取屏幕分辨率
fps = 30.0
output_file = "screen_recording.avi"
# 创建视频编码器
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter(output_file, fourcc, fps, screen_size)
# 开始录屏
while True:
img = pyautogui.screenshot() # 截取屏幕
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 转换颜色格式
out.write(frame) # 写入视频文件
# 按下 'q' 键停止录制
if cv2.waitKey(1) == ord('q'):
break
# 释放资源
out.release()
cv2.destroyAllWindows()
优点:简单易用,适合基础录屏需求。
缺点:性能较低,可能在高分辨率或高帧率下卡顿。
mss
库(高效屏幕捕获)mss
是一个高效的跨平台屏幕捕获库,适合高性能录屏。
import mss
import cv2
import numpy as np
def record_screen(output_filename="output.avi", fps=20.0):
with mss.mss() as sct:
monitor = sct.monitors[1] # 获取主屏幕
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter(output_filename, fourcc, fps, (monitor["width"], monitor["height"]))
while True:
img = np.array(sct.grab(monitor)) # 捕获屏幕
frame = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR) # 转换颜色格式
out.write(frame) # 写入视频文件
# 按下 'q' 键停止录制
if cv2.waitKey(1) & 0xFF == ord("q"):
break
out.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
record_screen()
优点:性能较好,支持多显示器。
缺点:需要额外安装 mss
库。
PIL.ImageGrab
录制屏幕PIL.ImageGrab
是 Python 图像处理库的一部分,适合简单的屏幕捕获。
from PIL import ImageGrab
import cv2
import numpy as np
fps = 20
output_file = "recording.avi"
# 获取屏幕尺寸
screen = ImageGrab.grab()
width, height = screen.size
# 创建视频编码器
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter(output_file, fourcc, fps, (width, height))
while True:
img = ImageGrab.grab() # 捕获屏幕
frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) # 转换颜色格式
out.write(frame) # 写入视频文件
# 按下 'q' 键停止录制
if cv2.waitKey(1) == ord('q'):
break
out.release()
cv2.destroyAllWindows()
优点:无需额外安装复杂库。
缺点:性能一般,不适合高帧率录制。
Win11 自带录屏功能:
Win + Shift + S
可调用截图和录屏工具。moviepy
库)。from moviepy.editor import VideoFileClip
def convert_mp4_to_gif(input_path, output_path, fps=10):
clip = VideoFileClip(input_path)
clip.write_gif(output_path, fps=fps)
# 示例
convert_mp4_to_gif("input.mp4", "output.gif")
优点:无需编程,适合简单需求。
缺点:依赖 Windows 自带功能,灵活性较低。
如果需要更友好的界面,可以结合 PyQt5
和 OpenCV
开发一个录屏工具,支持开始/停止录制、选择区域等功能。
方法 | 适用场景 | 性能 | 复杂度 |
---|---|---|---|
pyautogui + OpenCV |
基础录屏 | 较低 | 简单 |
mss + OpenCV |
高性能录屏 | 较高 | 中等 |
PIL.ImageGrab |
简单录屏 | 一般 | 简单 |
Windows 原生录屏 | 快速录制 | 高 | 无需代码 |
GUI 工具开发 | 自定义功能 | 高 | 复杂 |
选择哪种方法取决于你的具体需求(如是否需要高帧率、是否要录制音频等)。如果需要更高级的功能(如音频录制),可以结合 pyaudio
库实现。
在Python中,你可以使用多种方法将AVI格式的视频转换为MP4格式。以下是几种常见且高效的方式:
moviepy
库(推荐)moviepy
是一个强大的视频处理库,适合简单的格式转换。
from moviepy.editor import VideoFileClip
def avi_to_mp4(input_path, output_path):
# 加载AVI视频
video = VideoFileClip(input_path)
# 写入MP4文件(默认使用H.264编码)
video.write_videofile(output_path, codec="libx264", audio_codec="aac")
# 关闭视频对象
video.close()
# 示例
avi_to_mp4("input.avi", "output.mp4")
优点:
安装依赖:
pip install moviepy
OpenCV
+ FFmpeg
如果已安装FFmpeg,可以通过OpenCV调用FFmpeg进行转换。
import cv2
def avi_to_mp4_opencv(input_path, output_path):
# 读取AVI视频
cap = cv2.VideoCapture(input_path)
# 获取视频参数(帧率、分辨率等)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 创建MP4视频写入器(需FFmpeg支持)
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 或 'avc1'
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# 逐帧转换
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
out.write(frame)
# 释放资源
cap.release()
out.release()
# 示例
avi_to_mp4_opencv("input.avi", "output.mp4")
注意:
mp4v
)可能在某些平台兼容性较差,建议优先用moviepy
。FFmpeg
命令行(最高效)如果追求转换速度或处理大文件,直接调用FFmpeg命令行是最佳选择。
import subprocess
def avi_to_mp4_ffmpeg(input_path, output_path):
command = [
'ffmpeg',
'-i', input_path, # 输入文件
'-c:v', 'libx264', # H.264视频编码
'-c:a', 'aac', # AAC音频编码
'-strict', 'experimental',
'-y', # 覆盖输出文件
output_path
]
subprocess.run(command)
# 示例
avi_to_mp4_ffmpeg("input.avi", "output.mp4")
优点:
安装FFmpeg:
brew install ffmpeg
sudo apt install ffmpeg
PyAV
(高级控制)PyAV
是FFmpeg的Python绑定,适合需要精细控制编码参数的场景。
import av
def avi_to_mp4_pyav(input_path, output_path):
input_container = av.open(input_path)
output_container = av.open(output_path, mode='w')
# 配置输出流(复制输入流的参数)
in_stream = input_container.streams.video[0]
out_stream = output_container.add_stream('h264', rate=in_stream.average_rate)
out_stream.width = in_stream.width
out_stream.height = in_stream.height
# 逐帧转码
for frame in input_container.decode(video=0):
packet = out_stream.encode(frame)
output_container.mux(packet)
# 关闭容器
output_container.close()
input_container.close()
# 示例
avi_to_mp4_pyav("input.avi", "output.mp4")
优点:
安装依赖:
pip install av
转换后无声音:
moviepy
或FFmpeg的-c:a aac
)。ffmpeg -i input.avi
查看)。转换速度慢:
-preset fast
参数。-vf scale=1280:720
)。文件体积过大:
-b:v 2000k
)。-crf 23
,数值越小质量越高)。方法 | 适用场景 | 是否需要FFmpeg | 保留音频 |
---|---|---|---|
moviepy |
快速简单转换 | 否 | 是 |
OpenCV + FFmpeg |
需要逐帧处理 | 是 | 可选 |
FFmpeg命令行 | 高性能/批量处理 | 是 | 是 |
PyAV |
高级编码控制 | 是 | 是 |
推荐选择:
moviepy
。