From 6652fbf8af115e49e79e5e6322f1d29aa60cdf9a Mon Sep 17 00:00:00 2001 From: march3 Date: Mon, 3 Jul 2023 14:21:42 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sim_scenes/science/speed_of_light_3d.py | 12 +- tools/sim_video_cap.py | 148 ++++++++++++++++++++++++ tools/video_cap.bat | 25 ++++ 3 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 tools/sim_video_cap.py create mode 100644 tools/video_cap.bat diff --git a/sim_scenes/science/speed_of_light_3d.py b/sim_scenes/science/speed_of_light_3d.py index ce6d89b..7881516 100644 --- a/sim_scenes/science/speed_of_light_3d.py +++ b/sim_scenes/science/speed_of_light_3d.py @@ -6,6 +6,7 @@ # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== +import sys from common.consts import AU from sim_scenes.func import ursina_run, create_solar_system_bodies, create_light_ship from common.consts import LIGHT_SPEED @@ -25,8 +26,13 @@ init = SpeedOfLightInit(camera_follow_light) # 创建太阳系天体(忽略质量,引力无效,初速度全部为0) bodies = create_solar_system_bodies(ignore_mass=True, init_velocity=[0, 0, 0]) -camera_pos = "left" -camera_pos = "right" +if len(sys.argv) > 1: + camera_pos = sys.argv[1].replace("_", "") +else: + camera_pos = "left" + camera_pos = "right" + +print("camera_pos:", camera_pos) camera_l2r = 0.1 * AU if camera_pos == "right": # 摄像机右眼 @@ -58,7 +64,6 @@ def on_reset(): init.arrived_info = "距离[太阳中心]:${distance}\n\n光速飞船速度:${speed}\n\n" - def on_timer_changed(time_data: TimeData): init.text_panel.parent.enabled = False velocity, _ = get_value_direction_vectors(light_ship.velocity) @@ -91,6 +96,7 @@ def body_arrived(body): exit(0) # print(body) + # def body_arrived(body): # # 到达每个行星都会触发,对光速飞船进行加速,超光速前进(使用未来曲率引擎技术) # if body.name == "火星": # 到达火星,加速前进,并进行攀升 diff --git a/tools/sim_video_cap.py b/tools/sim_video_cap.py new file mode 100644 index 0000000..fa25833 --- /dev/null +++ b/tools/sim_video_cap.py @@ -0,0 +1,148 @@ +import cv2 +from PIL import ImageGrab, Image +import numpy as np +import argparse +import time +import os +import win32gui +import win32ui +import win32con +import win32api + + +def get_window_handle(window_name="universe_sim"): + """ + 获取模拟器窗口句柄 + @param window_name: + @return: + """ + handle = win32gui.FindWindow(None, window_name) + return handle + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--fps', type=int, default=30, help='frame per second') + parser.add_argument('--total_time', type=int, default=10000000, help='video total time') + parser.add_argument('--save_name', type=str, default='video.mp4', help='save file name') + # parser.add_argument('--screen_type', default=0, type=int, choices=[0, 1], help='1: full screen, 0: region screen') + args = parser.parse_args() + print("total_time:", args.total_time) + print("fps:", args.fps) + print("save_name:", args.save_name) + return args + + +def screen_shot(window_img_dc): + width, height = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN), \ + win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) + # 创建一个内存设备描述表 + mem_dc = window_img_dc.CreateCompatibleDC() + # 创建位图对象 + screenshot = win32ui.CreateBitmap() + screenshot.CreateCompatibleBitmap(window_img_dc, width, height) + mem_dc.SelectObject(screenshot) + # 截图至内存设备描述表 + mem_dc.BitBlt((0, 0), (width, height), window_img_dc, (0, 0), win32con.SRCCOPY) + # 将截图保存到文件中 + # screenshot.SaveBitmapFile(mem_dc, 'screenshot.bmp') + signedIntsArray = screenshot.GetBitmapBits(True) + # 下面3个语句都能实现转换,推荐第1个 + img = np.fromstring(signedIntsArray, dtype='uint8') + img.shape = (height, width, 4) + # 内存释放 + mem_dc.DeleteDC() + win32gui.DeleteObject(screenshot.GetHandle()) + img = img[:, :, 0:3] # 去掉透明数据 + return img + + +# def is_blank_screen(img_arr): +# for x in range(500, 600): +# for y in range(10, 20): +# pix = img_arr[x, y, ] +# # 检查标题栏,此时标题栏的颜色为白色 +# if pix.sum() > 600: +# return True +# return False + + +def sim_window_screen_shot(wait_ses=-1): + times = wait_ses * 100 + while True: + handle = get_window_handle() + if handle > 0: + desktop_dc = win32gui.GetWindowDC(handle) + img_dc = win32ui.CreateDCFromHandle(desktop_dc) + try: + img = screen_shot(img_dc) + except Exception as e: + print("ERROR:", str(e)) + return None + return img + if wait_ses < 0: + return None + time.sleep(0.01) + times -= 1 + if times <= 0: + return None + + +def create_video(args, height, width): + fourcc = cv2.VideoWriter_fourcc(*'mp4v') + video = cv2.VideoWriter(args.save_name, fourcc, args.fps, (width, height)) + return video + + +# def show_image(img): +# from PIL import Image +# image = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) +# image = Image.fromarray(image) +# print(type(image)) # 结果为 +# print(image.size) # 结果为(822,694),这里注意Image输出的结果先显示列数,后显示行数 +# image.show() + + +if __name__ == '__main__': + args = get_args() + handle = get_window_handle() + # print(get_args()) + print("请在10秒内打开模拟器") + img = sim_window_screen_shot(10) + if img is None: + print("没有找到模拟器窗口,录屏失败!") + exit(1) + + # show_image(img) + video = create_video(args, img.shape[0], img.shape[1]) + imageNum = 0 + print("开始录屏") + while True: + img = sim_window_screen_shot() + if img is None: + print("\n模拟器窗口已关闭,退出录屏") + break + + # if is_blank_screen(img): + # if imageNum % args.fps == 0: + # print('x', end='') + # + # continue + + if imageNum % args.fps == 0: + print('.', end='') + # else: + # print(imageNum, end='') + + imageNum += 1 + + # frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) + if imageNum < args.fps * args.total_time: + # show_image(frame) + video.write(img) + + print("视频保存中") + video.release() + cv2.destroyAllWindows() + # crop('video.mp4') + print("视频保存完成") diff --git a/tools/video_cap.bat b/tools/video_cap.bat new file mode 100644 index 0000000..85e8a00 --- /dev/null +++ b/tools/video_cap.bat @@ -0,0 +1,25 @@ +@REM @echo off +@REM 设置环境和参数 +SET Anaconda3=D:/Anaconda3 +SET env=pythoncr +SET DISK=G: +SET SimDir=%DISK%/works/gitcode/universe_sim + +SET SimFileDir=%1 +SET SimFileName=%2 +SET param3=%3 + +SET PYTHONPATH=%SimDir%; +SET SimFilePath=%SimDir%/sim_scenes/%SimFileDir%/ + +CALL %Anaconda3%/Scripts/activate.bat %Anaconda3% +CALL conda activate %env% +%DISK% + +cd %SimFilePath% +start python -m %SimFileName% %3 + +cd %SimDir%\tools +python -m sim_video_cap --save_name=%SimFileName%%param3%.mp4 + + -- GitLab