ffmpeg&opencv
音视频编解码,ffmpeg,OpenCV
- python开发指南(索引合集)
- python restful API服务器fastAPI
- 项目集成paddleocr功能
- 使用ffmpeg命令行工具
- ffmpeg SDK使用指南
- 开源直播服务器OSSRS
- 将ffmpeg编译为dll供外部调用
- yolov8图像识别
- liunx安装python3&&制作python镜像
- cuda安装
python开发指南(索引合集)
安装python 多版本环境
由于python有各种不同版本,且各版本不能完全兼容,anaconda 工具包可以完美解决该问题。
下载地址: https://repo.anaconda.com/archive/
或者同项目发布的 miniconda,二者的区别在于内置的常用包的多少
下载地址:https://repo.anaconda.com/miniconda/
如果一路enter下来安装,可能出现找不到命令的提示,需要进行初始化配置
# 进入安装目录执行 conda init bash
/root/anaconda3/bin/conda init bash
# bash参数为你的 shell 环境,可以使用 echo $SHELL 查看
# 也可以使用参数 --all 全部设置
/root/anaconda3/bin/conda init --all
# 此时,还可以出现找不到命令情况,需要重新加载shell
source /root/.bashrc
# 查看所有已经安装的模块
pip list
# 将所有的模块输出到 文件
pip freeze > modules.txt
# 卸载所有的模块
pip uninstall -r modules.txt -y
# 查看当前python版本
python --version
# 查看安装了哪些包
conda list
# 查看环境列表
conda env list
# 查看环境列表
conda info -e
# 创建环境,后面为使用的python版本
conda create -n your_env_name python=x.x
conda create -n cvyolo python=3.12
# 切换环境
conda activate cvyolo
# 删除环境
conda remove --name myenv --all
使用清华源加速安装
pip install pyinstaller==6.5.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
vscode相关插件
格式化:https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter vscode扩展:https://marketplace.visualstudio.com/items?itemName=ms-python.python 调试扩展:https://marketplace.visualstudio.com/items?itemName=ms-python.debugpy
将py打包为exe
# 安装打包工具,注意,
# 截止至2024年6月3日,其他版本打包出来的exe报毒
pip install pyinstaller==6.5.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
# 打包为单文件,需要很久时间
pyinstaller --onefile main.py
# 直接打包
pyinstaller main.py
# 高级设置
pyinstaller --onefile \
--windowed \
--icon=./assets/icon.ico \
--name=fff \
main.py
python restful API服务器fastAPI
组件
- fastAPI : https://fastapi.tiangolo.com/
- uvicorn: https://www.uvicorn.org/
快速开始
# 安装fastAPI
pip install fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装web容器
pip install "uvicorn[standard]" -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装from参数表单
pip install python-multipart -i https://pypi.tuna.tsinghua.edu.cn/simple
编写代码
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
# 运行
uvicorn main:app --reload
# 也可以用代码实现
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
# main:app <module:attribe>
项目集成paddleocr功能
示例代码下载
参考网站
- https://www.paddlepaddle.org.cn/
- https://github.com/PaddlePaddle/PaddleOCR
- https://fastapi.tiangolo.com/
安装paddle和paddle ocr环境
# 安装paddlepaddle
# https://www.paddlepaddle.org.cn/
pip install paddlepaddle==2.6.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装paddleocr
# 提示,截止至2024年5月2日,需要的python版本为3.11.更高版本会出现安装不上的情况
# 提示,截止至2024年5月2日,paddleocr==2.7.5有bug
# 需要修改的地方
# C:\Python311\Lib\site-packages\paddleocr\paddleocr.py
# 第54行之后
# from ppstructure import predict_system
pip install paddleocr==2.7.5 -i https://mirror.baidu.com/pypi/simple
# 可能出现其他安装失败情况,请使用清华源安装,更新pip工具
pip install --upgrade pip wheel setuptools
安装fast api服务框架
# 安装fastAPI
pip install fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装web容器
pip install "uvicorn[standard]" -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装from参数表单
pip install python-multipart -i https://pypi.tuna.tsinghua.edu.cn/simple
编写后台代码
import paddle as paddle
from paddleocr import PaddleOCR, draw_ocr
from PIL import Image
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
import time
import uvicorn
# 打印paddle版本
print(paddle.__version__)
app = FastAPI()
def get_image_ocr(img_path: str):
# 创建一个OCR实例
ocr = PaddleOCR(
use_angle_cls=True, lang="ch"
) # need to run only once to download and load model into memory
# img_path = "./images/test.png"
# 使用PaddleOCR进行文字检测和识别
ocr_result = ocr.ocr(img_path, cls=True)
# 显示结果
for line in ocr_result:
print(line)
# 对现实结果在原图进行标注
result = ocr_result[0]
image = Image.open(img_path).convert("RGB")
boxes = [elements[0] for elements in result]
# pairs = [elements[1] for elements in ocr_result]
# txts = [pair[0] for pair in pairs]
# scores = [pair[1] for pair in pairs]
im_show = draw_ocr(image, boxes)
im_show = Image.fromarray(im_show)
im_show.save(f"{img_path}")
# im_show.save("./images/result.jpg")
return {"image": img_path, "result": result}
app.mount("/static", StaticFiles(directory="./static"), name="static")
@app.get("/")
def read_root():
html_content = """
<html>
<head>
<title>OCR</title>
</head>
<body>
<h1>OCR</h1>
<p>Upload an image to extract text from it.</p>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
sequence_counter = 1
@app.post("/ocr/")
async def ocr_image(file: UploadFile | None = File(None)):
# 判断文件是否存在
if file is None:
return {"code": 400, "message": "No file found", data: None}
# 生成时间戳保存上传图片以免被覆盖
current_time = int(time.time() * 10000)
unique_sequnce = current_time + sequence_counter
new_fileName = f"./static/{unique_sequnce}--{file.filename}.jpg"
# 将文件写入磁盘
with open(f"{new_fileName}", "wb+") as fsio:
fsio.write(await file.read())
pass
# 调用OCR方法
ocr_result = get_image_ocr(new_fileName)
return {"code": 200, "message": "ok", "data": ocr_result}
# 启动服务
uvicorn.run(app, host="0.0.0.0", port=8000)
使用ffmpeg命令行工具
- 下载地址:https://ffmpeg.org/download.html
- 官方文档:https://ffmpeg.org/documentation.html
- 编译好的二进制:https://github.com/GyanD/codexffmpeg/releases
使用命令行
# 命令行基本用法
# ffmpeg <全局参数> <输入参数> -i <输入文件> <输出参数> <输出文件>
# 自动推导视频播放URL
ffmpeg -v debug -re -i $(curl -L -s http://10.10.56.18:30088/video/common/videoApi?cid=557254322 | jq -r .data) -vcodec libx264 -vf scale=1280:-1 -r 20 -an -f flv rtmp://ossrs:1935/csud/live/557254322
# 获取网络文件
ffmpeg -v debug -re -i https://qq829.cn/uploads/20221204/1.mp4 -vcodec libx264 -vf "scale=1280:-1" -r 20 -an -f flv rtmp:/ossrs:1935/csud/live/557254322
# 获取网络文件
ffmpeg -v debug -re -i https://qq829.cn/uploads/20221204/1.mp4 -vcodec libx264 -f flv rtmp://ossrs:1935/live/557254322
# 屏幕截图
ffmpeg -r 8 -f "gdigrab" -i "desktop" -vcodec libx264 -f flv rtmp://ossrs:1935/live/557254322
# -stream_loop -1 循环播放
# -v debug 打开调试信息
# -re 实时读取,既按原视频的帧率读取,否则会以最快的速度读取
# -i 输入文件
# -vcodec libx264 视频编码器
# -vf "scale=1280:-1"视频画面大小调整
# -r 20 输出帧率
# -an 静音
# -f flv 输出 格式
# 视频截图
ffmpeg -i https://qq829.cn/uploads/20221204/1.mp4 -ss 20 -vframes 1 -vf scale=800:-1 -qscale:v 2 -y 2.jpg
# -ss 视频开始位置
# -vframes 输出视频的帧目数
# -vf scale 视频滤镜,-1标示根据前一个参数自动计算
# -qscale:v 2 视频质量,取值为2-10之间
播放器
# 使用ffplay播放
ffplay 1.mp4
使用VLC播放:
https://srs.qq829.cn/csud/live/557254322.flv
https://srs.qq829.cn/csud/live/557254322.m3u8
# 使用bilibili开源的播放器
# https://github.com/xqq/mpegts.js
视频信息查看
# 显示媒体格式信息
ffprobe -show_format d:/1.mp4
# 显示每天流信息
ffprobe -show_streams d:/1.mp4
ffmpeg SDK使用指南
ffmpeg编解码
// 注册输入和输出设备
avdevice_register_all();
// 初始化网络库
avformat_network_init();
//----------------打开输入设备----------------------//
// 确定输入格式
av_find_input_format("gdigrab");
// 打开输入文件
avformat_open_input();
// 查找输入流
avformat_find_stream_info();
// 选择流
in_stream = input_fmt_ctx->streams[i];
// 输入流的编解码器
AVCodec *in_codec = avcodec_find_decoder(in_stream->codecpar->codec_id);
// 解密上下文
in_codec_ctx = avcodec_alloc_context3(in_codec);
// 解码参数复制
avcodec_parameters_to_context();
// 打开解码器
avcodec_open2();
//----------------打开输处设备----------------------//
// 确定输出格式
av_guess_format()
// 构建输出上下文
avformat_alloc_output_context2();
// 添加输出流
AVStream *out_stream = avformat_new_stream(output_fmt_ctx, NULL);
// 设置流的参数
out_stream->codecpar->codec_id = AV_CODEC_ID_H264;
// 输出流编解码
AVCodec *out_codec = avcodec_find_encoder(out_stream->codecpar->codec_id);
// 输出流编码器上下文
AVCodecContext *out_codec_ctx = avcodec_alloc_context3(out_codec);
// 编码器参数复制
avcodec_parameters_to_context(out_codec_ctx, out_stream->codecpar);
// 打开编码器
avcodec_open2();
// 写入SPS和PPS信息
out_stream->codecpar->extradata = out_codec_ctx->extradata;
out_stream->codecpar->extradata_size = out_codec_ctx->extradata_size;
// 打开输出IO
avio_open();
// 写入文件头信息
avformat_write_header();
//----------------解密和转换----------------------//
while (1){
// 从输入设备读取数据包
ret = av_read_frame(input_fmt_ctx, &packet);
// 解码数据包为帧
ret = avcodec_send_packet(in_codec_ctx, &packet);
// 从解码器中获取帧
ret = avcodec_receive_frame(in_codec_ctx, frame);
// 格式转换
ret = sws_scale(sws_ctx, (const uint8_t *const *)frame->data, frame->linesize,
0, frame->height,
enc_frame->data, enc_frame->linesize);
// 设置帧的时间戳
enc_frame->pts = av_rescale_q_rnd((frame->pts - start_pts), in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
enc_frame->pkt_dts = enc_frame->pts;
// 将帧发送到编码器
ret = avcodec_send_frame(out_codec_ctx, enc_frame);
// 从编码器中获取数据包
while (avcodec_receive_packet(out_codec_ctx, &enc_packet) == 0)
{
// 写入数据包
ret = av_interleaved_write_frame(output_fmt_ctx, &enc_packet);
if (ret < 0)
{
printf("7:Error while writing output packet:%s\n", av_err2str(ret));
break;
}
}
// 释放编码数据包
av_packet_unref(&enc_packet);
// 释放编码数据包
av_packet_unref(&packet);
}
//----------------后续工作----------------------//
// 写入文件尾
av_write_trailer(output_fmt_ctx);
// 关闭输出文件
avio_close(output_fmt_ctx->pb);
// 释放数据包
av_packet_free(&packet);
av_packet_free(&enc_packet);
// 释放帧
av_frame_free(&frame);
av_frame_free(&enc_frame);
// 释放格式转换器
sws_freeContext(sws_ctx);
// 释放编码器上下文
avcodec_free_context(&in_codec_ctx);
avcodec_free_context(&out_codec_ctx);
// 释放输入和输出设备
avformat_close_input(&input_fmt_ctx);
avformat_free_context(input_fmt_ctx);
// 释放输出设备
avformat_close_input(&output_fmt_ctx);
avformat_free_context(output_fmt_ctx);
// 释放网络库
avformat_network_deinit();
开源直播服务器OSSRS
OSSRS
SRS(Simple Realtime Server)是一个简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT等多种实时流媒体协议。
官方地址:ossrs.ne
docker-compose.yaml
version: '3'
services:
ossrs:
image: registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5
ports:
- 1935:1935 # RTMP推流端口
- 1985:1985 # HTTP API 端口
- 8080:8080 # 内置NGINX端口,可以用于http观看flv
volumes:
- ./conf/docker.conf:/usr/local/srs/conf/docker.conf:ro
command: ./objs/srs -c conf/docker.conf
服务器自动保留录像
# conf/docker.conf
dvr {
enabled on;
dvr_path ./objs/nginx/html/dvr/[app]/[stream].[timestamp].mp4;
dvr_plan segment;
# 按时间段分割,单位为秒
dvr_duration 300;
# 等待关键帧,如果为off可能导致启动播放时花屏
dvr_wait_keyframe on;
}
使用FFMPEG推流
使用ffmpeg命令行: https://qq829.cn/book/books/ffmpegopencv/page/ffmpeg
# 命令行基本用法
# ffmpeg <全局参数> <输入参数> -i <输入文件> <输出参数> <输出文件>
# 从一个源转换到另外一个源
ffmpeg -re -i https://qq829.cn/uploads/20221204/1.mp4 -vcodec libx264 -f flv rtmp://srs-push.qq829.cn:31935/live/557254322
# 桌面截图
ffmpeg -r 8 -f "gdigrab" -i "desktop" -vcodec libx264 -f flv rtmp://srs-push.qq829.cn:31935/live/557254322
使用vlc播放
# 播放地址
https://srs.qq829.cn/live/557254322.flv
将ffmpeg编译为dll供外部调用
将ffmpeg 编译为dll供外部调用
创建qt应用程序,设置项目为lib
// ffmpeg-dll.pro
#TEMPLATE = app
#CONFIG += console
TEMPLATE = lib
增加dll函数导出
// main.c
__declspec(dllexport) int __cdecl ffmain(int argc, char const *argv[]){
return main(argc,argv);
}
处理命令行参数
既ffmpeg的传入参数并不是以传入的为准,而是内部使用操作系统API又进行了替换,如果在某些系统出现兼容性问题,需要再次修改源代码
// cmdutils.c
// split_commandline
// 注释掉 785 行
// prepare_app_arguments(&argc, &argv);
使用python 调用
import ctypes as ctypes
import time as time
def ffmpeg():
dll = ctypes.windll.LoadLibrary(
"D:/cpp-sdk/FFmpeg-n7.0/ffmpeg-exe-dll/Release/release/ffmpeg-dll.dll"
)
ffmpeg_main = dll.ffmain
ffmpeg_main.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)]
ffmpeg_main.restype = ctypes.c_int
argv = (ctypes.c_char_p * 10)()
argv[0] = bytes("ffmpeg", "utf-8")
argv[1] = bytes("-f", "utf-8")
argv[2] = bytes("gdigrab", "utf-8")
argv[3] = bytes("-i", "utf-8")
argv[4] = bytes("desktop", "utf-8")
argv[5] = bytes("-vcodec", "utf-8")
argv[6] = bytes("libx264", "utf-8")
argv[7] = bytes("-f", "utf-8")
argv[8] = bytes("flv", "utf-8")
argv[9] = bytes("rtmp://srs-push.qq829.cn:31935/live/557254322", "utf-8")
ret = ffmpeg_main(10, argv)
ctypes.windll.kernel32.FreeLibrary.argtypes = [ctypes.c_void_p]
ctypes.windll.kernel32.FreeLibrary.restype = ctypes.c_int
ctypes.windll.kernel32.FreeLibrary(dll._handle)
return ret
while ffmpeg() < 0:
print("ffmpeg error")
time.sleep(5)
yolov8图像识别
官方网址
https://docs.ultralytics.com/
安装
# 使用清华大学源加速
https://pypi.tuna.tsinghua.edu.cn/simple/
# 查看已经安装的模块
pip list
# 卸载模块
pip uninstall <package-Name>
# 安装opencv
pip install python-opencv -i https://pypi.tuna.tsinghua.edu.cn/simple/
# 安装opencv 扩展
pip install opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple/
# 安装pytorch
# https://pytorch.org/get-started/locally/
pip install torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simple/
# 安装yolov8
# https://docs.ultralytics.com/quickstart/
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple/
使用命令行
# 命令行格式
yolo TASK MODE ARGS
# TASK:[detect : 侦测], [segment :分割], [classify :分类], [pose :姿态]
# MODE :[train:训练], [val:验证], [predict:预测/测试], [export:导出], [track:跟踪]
# 使用yolov8n.pt 预测图片
yolo detect predict model="./yolo/yolov8n.pt" source="./images/1.jpg"
# 使用yolov8n-seg.pt 分割图片
yolo segment predict model="./yolo/yolov8n-seg.pt" source="./images/1.jpg"
训练模型
# 使用coco128数据集进行模型训练
yolo detect train data=./yolo/coco128.yaml model=./yolo/yolov8n.pt epochs=100 imgsz=640
# 数据集实际上一个yaml配置文件
# 文件示例:https://github.com/ultralytics/ultralytics/tree/main/ultralytics/cfg/datasets
# coco128数据集
path: ../datasets/coco128 # dataset root dir
train: images/train2017 # train images (relative to 'path') 128 images
val: images/train2017 # val images (relative to 'path') 128 images
test: # test images (optional)
# Classes
names:
0: person
1: bicycle
download: https://ultralytics.com/assets/coco128.zip
python代码
from ultralytics import YOLO
model = YOLO('./yolo/yolov8n.pt') # load a pretrained model (recommended for training)
results = model.train(data='./images/coco128.yaml', epochs=100, imgsz=640)
liunx安装python3&&制作python镜像
制作python3 docker镜像
FROM alpine
RUN apk update && \
apk add --no-cache mysql-client \
bash \
curl \
build-base \
libffi-dev \
openssl-dev \
zlib-dev \
bzip2-dev \
readline-dev \
sqlite-dev
RUN wget https://www.python.org/ftp/python/3.10.14/Python-3.10.14.tgz && \
tar -xvzf Python-3.10.14.tgz && \
cd Python-3.10.14 && \
./configure --prefix=/usr/local --enable-optimizations && \
make -j ${nproc} && \
make install && \
rm -rf /Python-3.10.14 && \
rm -rf /Python-3.10.14.tgz
linux安装
apk update
apk add --no-cache mysql-client bash curl build-base libffi-dev openssl-dev zlib-dev bzip2-dev readline-dev sqlite-dev
wget https://www.python.org/ftp/python/3.10.14/Python-3.10.14.tgz && \
tar -xvzf Python-3.10.14.tgz
cd Python-3.10.14
./configure --prefix=/usr/local --enable-optimizations
make -j ${nproc}
make install
rm -rf /Python-3.10.14
rm -rf /Python-3.10.14.tgz
cuda安装
安装cuda
CUDA Toolkit Archive:https://developer.nvidia.com/cuda-toolkit-archive
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm
sudo rpm -i cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm
sudo yum -y install nvidia-driver-latest-dkms
sudo yum -y install cuda
sudo yum clean all
# 查看板卡信息
lspci | grep -i nvidia
# 查看驱动程序是否安装
nvidia-smi
# 查看nvcc版本
nvcc --version
# 此时可能nvcc已经安装,但是没有配置环境变量
查看GPU加速CUDA是否生效
# 单次查看
nvidia-smi
# 监视查看
watch -n 10 nvidia-smi
docker支持nvidia gpu
# 主机安装docker
# 主机安装nvidia-container-toolkit
curl -s -L https://nvidia.github.io/libnvidia-container/centos7/libnvidia-container.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
yum install -y nvidia-container-toolkit
# 配置docker运行时支持gpu
nvidia-ctk runtime configure --runtime=docker
# 命令行运行使容器支持gpu
docker run -itd --gpus all python:3.10.14