分类 云笔记 下的文章

“收集其他网站上看到的点滴内容。”

很简单,就是要下载挺久的.

conda create -n yolo11 python=3.11
conda activate yolo11
pip install ultralytics onnx numpy protobuf ncnn

使用示例
https://docs.ultralytics.com/models/yolo11/#usage-examples

# Load a COCO-pretrained YOLO11n model and train it on the COCO8 example dataset for 100 epochs
yolo train model=yolo11n.pt data=coco8.yaml epochs=100 imgsz=640

# Load a COCO-pretrained YOLO11n model and run inference on the 'bus.jpg' image
yolo predict model=yolo11n.pt source=https://github.com/ultralytics/assets/releases/download/v0.0.0/bus.jpg

老版本:

//声明:    
AVBitStreamFilterContext* h264bsfc =  av_bitstream_filter_init("h264_mp4toannexb"); 
//使用
av_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
//释放:
av_bitstream_filter_close(h264bsfc);  

新版本:


//声明  
AVBSFContext *bsf_ctx = nullptr;
const AVBitStreamFilter *pfilter = av_bsf_get_by_name("h264_mp4toannexb");
av_bsf_alloc(pfilter, &bsf_ctx);
//使用:
av_bsf_send_packet(bsf_ctx, &packet);
av_bsf_receive_packet(bsf_ctx, &packet);
//释放:
av_bsf_free(&bsf_ctx);

h264有两种封装,一种是annexb模式,传统模式,有startcode(0x000001或0x0000001)分割NALU,在mpegts流媒体中使用,vlc里打开编码器信息中显示h264;

一种是AVCC模式,一般用mp4、mkv、flv容器封装,以长度信息分割NALU, vlc里打开编码器信息中显示avc1。

很多场景需要进行这两种格式之间的转换,FFmpeg提供了名称为h264_mp4toannexb的Bitstream Filter(bsf)来实现这个功能。

例如将mp4转换成h264可使用如下指令:

mp4->h264:sudo ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 test.h264

bsf的使用方法:

(1)使用查询函数av_bsf_get_by_name 根据名称查找对应的AVBitstreamFilter。

(2)使用av_bsf_alloc为AVBSFContext和他的一些内部变量分配内存。

(3)设置AVBSFContext可能需要使用一些变解码参数和time_base[2].

(4)在设置好参数之后使用av_bsf_init来初始化bsf.

(5)使用av_bsf_send_packet函数输入数据,并使用av_bsf_receive_packet获得处理后的输出数据。

(6)处理结束后,av_bsf_free清理用于上下文和内部缓冲区的内存。

在 Keith Jack’s 的书 “Video Demystified” (ISBN 1-878707-09-4) 给出的公式是这样的。

RGB to YUV

𝑌=0.257𝑅+0.504𝐺+0.098𝐵+16
𝐶𝑟=𝑉=0.439𝑅−0.368𝐺−0.071𝐵+128
𝐶𝑏=𝑈=−0.148𝑅−0.291𝐺+0.439𝐵+128

YUV to RGB

𝐵=1.164(𝑌−16)+2.018(𝑈−128)
𝐺=1.164(𝑌−16)−0.813(𝑉−128)−0.391(𝑈−128)
𝑅=1.164(𝑌−16)+1.596(𝑉−128)

注意在上面的式子中,RGB 的范围是 [0,255],Y 的范围是 [16,235] ,UV 的范围是 [16,239]。 如果计算结果超出这个范围就截断处理。

CCIR 601 定义的转换公式是:

𝑌=0.299𝑅+0.587𝐺+0.114𝐵
𝐶𝑟=𝑉=0.713(𝑅−𝑌)=0.500𝑅−0.419𝐺−0.081𝐵
𝐶𝑏=𝑈=0.564(𝐵−𝑌)=−0.169𝑅−0.331𝐺+0.500𝐵

RGB===Y+1.403VY−0.344U−0.714VY+1.770U
𝑅=𝑌+1.403𝑉
𝐺=𝑌−0.344𝑈−0.714𝑉
𝐵=𝑌+1.770𝑈

这里 RGB 的取值范围是 [0,1]。 Y 的范围是 [0,1], Cr 和 Cb 的范围是 [−0.5,0.5]。

大家仔细看,这两个来源给出的公式系数有些细微的差别,如果将公式中的 YUV 和 RGB 的取值范围统一成相同的,计算出的结果也略有不同,但是差异很小,基本上眼睛看不出区别来。所以大家不用计较这两个公式的区别。

如果把 RGB 和YUV 的范围都放缩到 0,255,那么常用的转换公式是这样的。所以我们可以直接使用下面的公式来转换.

𝑅=𝑌+1.403×(𝑉−128)
𝐺=𝑌–0.343×(𝑈–128)–0.714×(𝑉–128)
𝐵=𝑌+1.770×(𝑈–128)

𝑌=0.299𝑅+0.587𝐺+0.114𝐵
𝐶𝑟=𝑉=0.500𝑅−0.419𝐺−0.081𝐵+128
𝐶𝑏=𝑈=−0.169𝑅−0.331𝐺+0.500𝐵+128

C++转换代码如下:

class RGB
{
public:
    uint8_t R, G, B;
};
class YUV
{
public:
    uint8_t Y, U, V;
};

RGB yuv2rgb(YUV yuv)
{
    int R = round(yuv.Y + 1.403 * (yuv.V - 128));
    int G = round(yuv.Y - 0.343 * (yuv.U - 128) - 0.714 * (yuv.V - 128));
    int B = round(yuv.Y + 1.770 * (yuv.U - 128));

    RGB rgb;
    rgb.R = max(0, min(R, 255));
    rgb.G = max(0, min(G, 255));
    rgb.B = max(0, min(B, 255));
    return rgb;
}

YUV rgb2yuv(RGB rgb)
{
    int Y = round(0.299 * rgb.R + 0.587 * rgb.G + 0.114 * rgb.B);
    int V = round(0.500 * rgb.R - 0.419 * rgb.G - 0.081 * rgb.B + 128);
    int U = round(-0.169 * rgb.R - 0.331 * rgb.G + 0.500 * rgb.B + 128);

    YUV yuv;
    yuv.Y = max(0, min(Y, 255));
    yuv.U = max(0, min(U, 255));
    yuv.V = max(0, min(V, 255));
    return yuv;
}

常见颜色RGB与YUV对应值:

黑色 rgb=[00,00,00],yuv=[00,80,80]
白色 rgb=[ff,ff,ff],yuv=[ff,80,80]
红色 rgb=[ff,00,00],yuv=[4c,55,ff]
青色 rgb=[00,ff,ff],yuv=[b3,ab,01]
蓝色 rgb=[00,00,ff],yuv=[1d,ff,6b]
黄色 rgb=[ff,ff,00],yuv=[e2,01,95]

注意解码时,硬件对图像的宽度和高度存在对齐的要求,在视频解码和图片解码,要求不一致,可以参考官方的功能及约束说明
https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/80RC3alpha001/apiref/appdevgapi/aclpythondevg_01_0337.html
昇腾 310b1 对应 Atlas 200I A2 加速模块
Atlas 200I A2 加速模块集成了昇腾310系列AI处理器,可以实现图像、视频等多种数. 据分析与推理计算,可广泛用于智能监控、机器人、无人机、视频服务器等

宽2对齐

高2对齐

宽Stride为宽16对齐后的值。

如果用户设置的输出图片宽度小于16,则宽Stride最小为32。

高Stride为高2对齐后的值。

内存大小(单位Byte)≥ 宽Stride 高Stride 3/2

cv::Mat ImageDataToMat(const ImageData &imgData)
{

// 确保图像格式是 YUV420SP
if (imgData.format != PIXEL_FORMAT_YUV_SEMIPLANAR_420)
{
    throw std::invalid_argument("Unsupported image format");
}
std::cout << imgData.width << std::endl;
std::cout << imgData.height << std::endl;

// 创建 YUV420SP 的 cv::Mat
cv::Mat yuv420spMat(imgData.height + imgData.height / 2, imgData.width, CV_8UC1, imgData.data.get());

// 将 YUV420SP 转换为 BGR
cv::Mat bgrMat;
cv::cvtColor(yuv420spMat, bgrMat, cv::COLOR_YUV2BGR_NV12);

return bgrMat;

}