python自研流星监控系统meteor_monitor(第二篇)

简介: 该文介绍了替代流星监控软件UFOcaptureHD2的新方案,强调了原软件的性能消耗大和收费问题。文中提供了一个GitHub链接以获取最新代码。推荐使用配备Windows 10/11、2.4GHz四核CPU的主机,搭配索尼MX291摄像头进行监控。程序基于ffmpeg,支持不同编码器,如mjpeg、h264_qsv等,具体编码器选择取决于硬件环境。安装涉及创建虚拟环境、安装Python 3.10+及依赖项,并提供了Windows和Linux的详细步骤。此外,程序通过帧差法进行运动检测,然后过滤掉非流星目标,最后使用ffmpeg对原始视频切片并存储。

代码已开源:

https://github.com/xingxinghuo1000/meteor_monitor_scripts.git


本篇为最新代码的方案介绍和使用介绍。第一篇已经过时了,不建议看 。只看这一篇即可。


背景

著名的流星监控软件ufocapturehd2有几个缺陷,不能忍

1、吃性能,我的工控电脑2.4GHz的4核心CPU,发现流星后,录制出来的视频,会严重丢帧

2、收费。还相当的贵。大概700多元? 用破解版当然也可以,这里不推荐


使用方法

推荐硬件

主机:

windows系统,win10 win11. 小主机, cpu 2.4GHz, 4核心.

不推荐Linux系统, 因为显卡驱动不容易安装,需要较高的技术水平.

不推荐树莓派, 原因同Linux系统.



image.png



摄像头的选择

推荐使用 索尼 MX291 摄像头. CMOS底比较大,适合拍摄星空

如果您的摄像头CMOS尺寸太小, 则噪点会比较多. 所以推荐IMX291这款, 如果使用IMX485, 则更好.


image.png




如何使用

建议在windows使用,原因是显卡驱动程序比较容易安装. 在Ubuntu下intel核心显卡驱动安装比较困难,无法使用h264_qsv编码

本程序默认使用mjpeg码流, 如果cpu支持硬件编码h264,则可以尝试使用h264_qsv编码器

如果是windows环境 , 且是 Intel核心显卡, 则可以尝试h264_qsv编码, nvdia显卡尝试 h264_nvenc, amd显卡尝试 h264_amf

如果是Ubuntu环境, 请尝试 mjpeg 编码, 经过我的测试, 2.4GHzCPU 只能达到15fps, 如果需要更高比如30fps,则对CPU要求也会很高.

如果您在Ubuntu环境,安装好了显卡驱动程序, Intel核心显卡可以尝试 h264_qsv 编码, nvdia显卡尝试 h264_nvenc, amd显卡尝试 h264_amf

如果是树莓派, 且编译了带h264_omx编码的ffmpeg, 则编码器使用 h264_omx


安装ffmpeg

本程序依赖ffmpeg命令,

我目前只测试过 4.x.x 版本的ffmpeg, 不能保证 5.x 和 6.x也能正常工作

Windows环境,需要到ffmpeg官网(Download FFmpeg) 下载ffmpeg可执行程序, 下载压缩包,解压缩到某个目录, 并将目录添加到环境变量. 如何验证安装是否成功, 可以打开cmd, 输入 ffmpeg -v 看看是否能正常看到输出的版本号

Linux环境, sudo yum install ffmpeg 或者 sudo apt install ffmpeg, 验证方法, 在shell中输入 ffmpeg -v 看看是否正常显示版本号

如果是树莓派, 则需要手工编译ffmpeg, 启用h264_omx编码, 比较麻烦, 不推荐.


插入usb摄像头

将usb摄像头插入主机的usb口, 执行下面的命令, 检查系统是否能正常识别摄像头

Windows中, 打开cmd 输入 ffmpeg -list_devices true -f dshow -i dummy 看看返回结果

Linux系统中, 在shell中输入 ffmpeg -hide_banner -sources v4l2 看看返回结果

如何修改配置文件.config 参考.config.xx文件,对应你的操作系统, 配置 文件中都有说明

比如win11系统,可以参考.config.win

如果是Ubuntu系统,可以参考.config.linux

如何设置分辨率和fps?

根据自己的硬件性能,逐步调整fps到可用的程度. 如果 ffmpeg 日志中提示丢帧, 则fps设置过大, 需要降低fps, 以保证画面流畅

还要看摄像头支持哪些分辨率.如果设置错误,则无法录制视频



查看摄像头信息

根据ffmpeg显示出来的信息, 查看摄像头支持哪些分辨率和fps. 配置到.config 文件中



配置Python环境

版本: 推荐使用Python 3.10及以上

步骤1

新建virtual env. 在 detect_meteor目录下, 执行如下命令

windows下, python3 -m venv venv

Linux下, python3 -m venv venv


步骤2

安装依赖

windows下, 打开 cmd, 在 detect_meteor 目录下, 执行命令 .\venv\Script\python -m pip install -r requirement.txt

Linux下, 在 detect_meteor目录下, 执行命令 ./venv/bin/python -m pip install -r requirement.txt


步骤3

运行本程序

windows下, 双击 offline_detect_from_mp4.bat

Linux下, 在detect_meteor目录下, 执行 sh run.sh


步骤4

配置开机自动启动,

Windows下, 右键点击 offline_detect_from_mp4.bat, 发送到桌面快捷方式, 将 快捷方式,复制到 开始菜单的 启动 目录

Linux下, crontable中配置 */5 * * * * cd /home/yourname/workspace/meteor_monitor_script/detect_meteor && sh run.sh


步骤5 可选

配置 mask-1280-720.bmp 遮罩图像, 目的是排除掉画面中的一些非天空部分, 这部分可能会引起False Positive, 流星的误报

比如 画面中远处楼宇的灯光变化, 可能会让程序以为是有画面变化

问题: 在哪个目录新建 遮罩图像?

答: 在视频目标输出目录, 在配置文件的 base_output_path 选项, 该路径由您指定

问题: 遮罩图像黑色白色代表什么意思?

答: 黑色表示要遮盖的部分, 白色表示要检测的部分



原理介绍

高效的录制mp4视频

使用ffmpeg, 高效录制视频. 这部分,我没有足够能力使用python实现, 所以借助ffmpeg的能力

ffmpeg 支持多种编码格式, h264支持多种硬件加速, 比如Intel核心显卡, nvdia显卡, AMD显卡

备注: 曾经使用过一个方案 使用windows自带的相机app,进行录像. 这个方案不够稳定, 已被废弃. 该方案使用sikuli进行UI自动化操作, 非常不稳定.



为了帮您理解该项目,下面是一个代码示例片段,演示如何使用 Python 和 FFmpeg 从 USB 摄像头录制视频,并自动获取摄像头的最佳帧率和最大画面尺寸:


import subprocess
import re

def get_camera_info():
    # 使用 ffmpeg 获取摄像头信息
    cmd = ["ffmpeg", "-f", "v4l2", "-list_formats", "all", "-i", "/dev/video0"]
    result = subprocess.run(cmd, stderr=subprocess.PIPE, text=True)

    # 解析输出以获取最佳帧率和最大画面尺寸
    output = result.stderr
    frame_rates = []
    resolutions = []

    for line in output.split("\n"):
        # 获取帧率信息
        frame_rate_match = re.search(r"([0-9]+(\.[0-9]+)?) fps", line)
        if frame_rate_match:
            frame_rates.append(float(frame_rate_match.group(1)))

        # 获取分辨率信息
        resolution_match = re.search(r"([0-9]+)x([0-9]+)", line)
        if resolution_match:
            width = int(resolution_match.group(1))
            height = int(resolution_match.group(2))
            resolutions.append((width, height))

    best_frame_rate = max(frame_rates) if frame_rates else 30  # 如果未找到,默认为30fps
    max_resolution = max(resolutions, key=lambda x: x[0]*x[1]) if resolutions else (640, 480)  # 默认640x480

    return best_frame_rate, max_resolution

def record_video(output_file, duration):
    best_frame_rate, max_resolution = get_camera_info()
    width, height = max_resolution

    # 使用 ffmpeg 录制视频
    cmd = [
        "ffmpeg",
        "-f", "v4l2",
        "-framerate", str(best_frame_rate),
        "-video_size", f"{width}x{height}",
        "-i", "/dev/video0",
        "-t", str(duration),
        "-c:v", "libx264",
        "-preset", "fast",
        "-pix_fmt", "yuv420p",
        output_file
    ]

    subprocess.run(cmd)

# 调用示例
output_video_path = "output_video.mp4"
record_duration = 10  # 录制10秒
record_video(output_video_path, record_duration)


  1. 获取摄像头信息 get_camera_info:
  • 使用 FFmpeg 命令列出摄像头支持的所有格式。
  • 解析 FFmpeg 的输出以获取帧率和分辨率信息。
  • 选择最佳帧率和最大分辨率。
  1. 录制视频 record_video:
  • 使用上面函数获取最佳帧率和最大分辨率。
  • 调用 FFmpeg 命令通过 USB 摄像头录制视频,并使用 H.264 编码。
  1. FFmpeg 命令解释:
  • -f v4l2:指定输入格式为 V4L2(Video for Linux 2)。
  • -framerate:设置帧率。
  • -video_size:设置分辨率。
  • -i /dev/video0:指定输入设备为 USB 摄像头。
  • -t:设置录制时长。
  • -c:v libx264:指定视频编码器为 H.264。
  • -preset fast:设置编码速度,fast 是编码速度和质量之间的平衡。
  • -pix_fmt yuv420p:设置像素格式为 YUV 4:2:0。

请注意:

  • /dev/video0 是 Linux 下的摄像头设备路径。对于 Windows 系统可以使用如 -i video="YOUR_CAMERA_NAME".
  • 在运行代码之前,请确保你的摄像头可以被 FFmpeg 识别,并且你的系统 PATH 中包含了 FFmpeg 程序。

通过上述代码,你可以实现从 USB 摄像头录制视频,并根据摄像头的最佳帧率和最大画面尺寸来设置录制参数



离线分析流星

为什么不做实时分析?

因为硬件性能不够. 我的目的是在低配置的硬件上,运行本程序. 如果您的硬件性能已经很强悍, 则建议直接使用ufohd2



离线分析的原理


步骤1

使用典型的opencv 运动检测算法: 帧差法, 识别画面的变化。为了讲解原理,下面给一个代码示例


功能描述:

  1. 视频文件的读取:
  • 使用 cv2.VideoCapture 打开视频文件。
  • 检查视频是否成功打开。
  1. 帧的读取和预处理:
  • 循环读取视频帧,并将其转换为灰度图像。
  • 使用一个列表 frames 来存储最近的五个灰度帧。
  1. 判断画面变化:
  • 每次读取新帧时,将其添加到 frames 列表中,并移除列表中最早的一帧,以确保列表长度为 5。
  • 当 frames 列表中有五帧时,计算第一个和第五个帧之间的差异。
  • 使用阈值处理和膨胀操作填补孔洞,以便更好地检测轮廓,并忽略小的变化区域。
  • 查找并绘制检测到的运动区域。
  1. 显示结果:
  • 显示当前帧和帧差图像。
  • 每隔 5 帧进行一次判断,因此设置循环间隔为 30 毫秒(可根据需要调整)。
  1. 释放资源:
  • 释放视频捕获对象和关闭所有窗口。


import cv2

def main():
    # 打开视频文件
    cap = cv2.VideoCapture('your_video_file.mp4')  # 替换为你的视频文件路径

    # 检查视频是否成功打开
    if not cap.isOpened():
        print("Error: Could not open video.")
        return

    # 用于存储当前帧和前五帧的列表
    frames = []

    while True:
        ret, frame = cap.read()

        # 如果视频读取结束,退出循环
        if not ret:
            break

        # 转换为灰度图
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 将当前帧添加到帧列表中
        frames.append(gray)

        # 保持帧列表的长度为5
        if len(frames) > 5:
            frames.pop(0)

        # 计算每隔五帧之间的帧差
        if len(frames) == 5:
            frame_diff = cv2.absdiff(frames[0], frames[4])

            # 阈值处理
            _, thresh = cv2.threshold(frame_diff, 25, 255, cv2.THRESH_BINARY)

            # 膨胀操作以填补孔洞
            thresh = cv2.dilate(thresh, None, iterations=2)

            # 查找轮廓
            contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

            # 绘制检测到的运动区域
            for contour in contours:
                if cv2.contourArea(contour) < 500:  # 忽略小的变化区域
                    continue
                (x, y, w, h) = cv2.boundingRect(contour)
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

            # 显示结果
            cv2.imshow('Motion Detection', frame)
            cv2.imshow('Frame Diff', frame_diff)

        # 每隔5帧进行判断,所以这里以5帧为间隔
        if cv2.waitKey(30) & 0xFF == 27:  # 按下ESC键退出
            break

    # 释放资源
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()


通过上述代码,你可以计算每隔五帧之间的差异,并判断画面是否有变动。你可以根据自己的需要调整阈值和帧间隔,以获得更好的检测效果




步骤2

根据一些特征,过滤掉不是流星的东西, 比如蝙蝠, 小飞虫等。该部分逻辑,不具备通用性,请参考最上方源码查看具体原理。



步骤3

使用ffmpeg 将原始视频切片, 切片后单独存储起来。 以下是示例代码



介绍:FFmpeg 是一个强大的多媒体处理工具,可以轻松实现视频的切割、转换等操作。我们可以使用 subprocess 模块来调用 FFmpeg 命令。

首先你需要确保已经安装 FFmpeg,你可以从 FFmpeg 官网 下载并安装它。

下面是一个 Python 函数示例,使用 FFmpeg 来切割视频文件并输出多个视频文件。


功能描述:

  1. 获取视频的帧率 (fps):
  • 使用 ffprobe 命令来获取输入视频的帧率。这个步骤很重要,因为你需要用帧率来将起始帧转化为时间秒数。
  1. 切割视频文件:
  • 循环遍历 start_frames_list,对于每个起始帧,计算其对应的时间秒数。
  • 使用 ffmpeg 命令切割视频。-ss 参数指定起始时间,-t 参数指定切割时长,-c copy 参数表示直接拷贝视频流而不进行重新编码,从而加速处理。
  1. 调用示例:
  • video_path 指定输入视频文件。
  • output_directory 指定输出视频片段存放的目录。
  • start_frames_list 给定起始帧列表,假设我们想从第0帧、第150帧、第300帧开始切割视频。
  • duration_in_seconds 指定每段视频的时长(秒)。


import subprocess
import os

def cut_video(input_file, output_dir, start_frames, duration):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取视频的帧率 (fps)
    cmd = [
        "ffprobe",
        "-v", "error",
        "-select_streams", "v:0",
        "-show_entries", "stream=r_frame_rate",
        "-of", "default=noprint_wrappers=1",
        input_file
    ]
    result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    fps_str = result.stdout.strip().split('=')[1]
    fps = eval(fps_str)
    
    # 切割视频
    for i, start_frame in enumerate(start_frames):
        start_time = start_frame / fps  # 计算起始时间(秒)
        output_file = os.path.join(output_dir, f'output_{i}.mp4')
        cmd = [
            "ffmpeg",
            "-i", input_file,
            "-ss", str(start_time),
            "-t", str(duration),
            "-c", "copy",
            output_file
        ]
        subprocess.run(cmd)

# 示例调用
video_path = 'input_video.mp4'
output_directory = 'output_videos'
start_frames_list = [0, 150, 300]  # 示例起始帧,假设我们想从第0帧、第150帧、第300帧开始切割
duration_in_seconds = 10  # 每段视频的时长为10秒

cut_video(video_path, output_directory, start_frames_list, duration_in_seconds)



总结

本文介绍了如何使用 Python 和 FFmpeg 来替代 ufocapturehd2 进行流星监控录像,并针对其高性能消耗和高价格等缺点提供了优化方案。推荐在 Windows 系统上进行部署,使用索尼 IMX291 或 IMX485 摄像头以获得高质量画面。根据硬件环境的不同,选择适合的编码器以达到性能最佳:如 Intel 核心显卡的 h264_qsv,NVIDIA 显卡的 h264_nvenc 和 AMD 显卡的 h264_amf。在 Ubuntu 和树莓派环境下,编码配置更为复杂,需要特别注意显卡驱动的安装。本方案强调离线分析以适配低性能硬件,通过逐步调整 FPS 设置确保录像的流畅性,确保在低成本的硬件环境下依然能够有效地进行高质量的流星监控录像


相关文章
|
3月前
|
存储 监控 Java
python自研流星监控系统meteor_monitor(第一篇)
本文介绍了作者开发的一个Python流星监控系统,替代了性能不佳且收费的ufocapturehd2软件。系统采用Win10相机应用低耗录制视频,通过SikuliX进行自动化控制,分段录制并存储到本地,然后通过脚本同步到NAS。视频分析使用帧差法检测流星,支持分布式分析。代码已更新,旧文章不再适用,最新内容可见:[用python自行开发的流星监控系统meteor_monitor(第二篇)-CSDN博客](https://github.com/xingxinghuo1000/meteor_monitor_scripts.git)。
|
算法 数据挖掘 API
Sentieon|应用教程:利用Sentieon Python API引擎为自研算法加速
Sentieon|应用教程:利用Sentieon Python API引擎为自研算法加速
146 0
Sentieon|应用教程:利用Sentieon Python API引擎为自研算法加速
|
算法 数据挖掘 API
Sentieon|应用教程:利用Sentieon Python API引擎为自研算法加速
Sentieon|应用教程:利用Sentieon Python API引擎为自研算法加速
82 0
|
1天前
|
存储 人工智能 数据挖掘
Python编程入门:从基础到实战
【9月更文挑战第26天】 在这篇文章中,我们将一起探索Python编程的奇妙世界。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的信息和技巧。我们将从Python的基本语法开始,然后逐步深入到更复杂的主题,如函数、类和模块。最后,我们将通过一个实际的项目来应用我们所学的知识。让我们一起开始这段Python编程之旅吧!
|
2天前
|
数据采集 人工智能 数据挖掘
Python编程入门:从基础到实战的快速指南
【9月更文挑战第25天】本文旨在为初学者提供一个简明扼要的Python编程入门指南。通过介绍Python的基本概念、语法规则以及实际案例分析,帮助读者迅速掌握Python编程的核心技能。文章将避免使用复杂的专业术语,而是采用通俗易懂的语言和直观的例子来阐述概念,确保内容的可读性和实用性。
|
1天前
|
Python
探索Python编程中的装饰器魔法
【9月更文挑战第26天】在Python的世界里,装饰器就像是一把瑞士军刀,小巧而功能强大。它们让代码更简洁、可维护性更强。本文将通过实际示例,带你领略装饰器的魔力,从基础到进阶,一步步揭开它的神秘面纱。
9 2
|
2天前
|
机器学习/深度学习 人工智能 数据挖掘
探索Python编程之美:从基础到进阶
【9月更文挑战第25天】在数字时代的浪潮中,编程已成为一项宝贵的技能。本篇文章将引导你步入Python的奇妙世界,一个既适合初学者又深受资深开发者喜爱的编程语言。我们将一起揭开Python语言的基础面纱,探索它的核心概念,并通过实际示例深入理解其强大功能。无论你是编程新手还是希望提升自己的老手,这篇文章都将为你提供一条清晰的学习路径,助你在编程之旅上更进一步。
|
2天前
|
存储 开发者 Python
从理论到实践:Python中Trie树与Suffix Tree的完美结合,开启编程新篇章!
在编程领域,高效的数据结构对于解决问题至关重要。本文通过一个案例分析,介绍如何在Python中结合使用Trie树(前缀树)和Suffix Tree(后缀树)。案例聚焦于开发具备高效拼写检查和文本相似度检测功能的文本编辑器。首先,通过构建Trie树快速检查单词是否存在;接着,利用Suffix Tree检测文本相似度。尽管Python标准库未直接提供Suffix Tree,但可通过第三方库或自定义实现。本文展示了高级数据结构在实际应用中的强大功能,并强调了理论与实践相结合的重要性。
9 1
|
1天前
|
Python
python编程获取续蜀山剑侠传:从目录名称、网址到内容
python编程获取续蜀山剑侠传:从目录名称、网址到内容
|
1天前
|
移动开发 Python Windows
python编程获取网页标题title的几种方法及效果对比(源代码)
python编程获取网页标题title的几种方法及效果对比(源代码)