FFmpeg自学入门笔记
命令行
PS:我自己使用过的命令行,便于自己查阅和使用FFmpeg。
1.转格式
ffmpeg -i input.mp4 output.avi
2.转分辨率
ffmpeg -i in.mp4 -vf scale=640:480 -qscale 9 out.mp4
注:-qscale
参数表示图像质量,1是最高质量。
《FFmpeg》
FFmpeg是一种完整的跨平台解决方案,用于录制,转换和流式传输音频和视频。
FFMPEG分为3个版本:Static,Shared,Dev。
前两个版本可以直接在命令行中使用,他们的区别在于:Static里面只有3个应用程序:ffmpeg.exe,ffplay.exe,ffprobe.exe,每个exe的体积都很大,相关的Dll已经被编译到exe里面去了。Shared里面除了3个应用程序:ffmpeg.exe,ffplay.exe,ffprobe.exe之外,还有一些Dll,比如说avcodec-54.dll之类的。Shared里面的exe体积很小,他们在运行的时候,到相应的Dll中调用功能。
Dev版本是用于开发的,里面包含了库文件xxx.lib以及头文件xxx.h,这个版本不包含exe文件。
打开系统命令行接面,切换到ffmpeg所在的目录,就可以使用这3个应用程序了。
ffmpeg是用于转码的应用程序。(ffmpeg详细的使用说明(英文):http://ffmpeg.org/ffmpeg.html)
具体的使用方法可以参考:雷霄骅 ffmpeg参数中文详细解释(https://blog.csdn.net/leixiaohua1020/article/details/12751349)
ffplay是用于播放的应用程序。(详细的使用说明(英文):http://ffmpeg.org/ffplay.html)
ffprobe是用于查看文件格式的应用程序。(详细的使用说明(英文):http://ffmpeg.org/ffprobe.html)
FFmpeg为开发人员提供的库:
libavutil是一个包含简化编程功能的库,包括随机数生成器,数据结构,数学例程,核心多媒体实用程序等等。
libavcodec是一个包含用于音频/视频编解码器的解码器和编码器的库。
libavformat是一个包含多媒体容器格式的解复用器和复用器的库。
libavdevice是一个包含输入和输出设备的库,用于从许多常见的多媒体输入/输出软件框架中获取和呈现,包括Video4Linux,Video4Linux2,VfW和ALSA。
libavfilter是一个包含媒体过滤器的库。
libswscale是一个执行高度优化的图像缩放和色彩空间/像素格式转换操作的库。
libswresample是一个执行高度优化的音频重采样,重新矩阵化和样本格式转换操作的库。
一、视频编码基础
视音频基础知识:(自行百度)
1.视频播放器原理
2.封装格式(MP4,RMVB,TS,FLV,AVI)
这里补充一下mp4封装学习记录:
3.视频编码数据(H.264,MPEG2,VC-1)
4.音频编码数据(AAC,MP3,AC-3)
5.视频像素数据(YUV420P,RGB)
6.音频采样数据(PCM)
二、FFmpeg_4.1编译安装
依赖项:
$ sudo apt-get install libgtk2.0-dev libjpeg.dev libjasper-dev yasm
#依赖:mfx_dispatch,需要源码编译
$ git clone https://github.com/lu-zero/mfx_dispatch.git
$ cd mfx_dispatch/
$ mkdir build
$ cd build/
$ cmake -D__ARCH:STRING=intel64 ..
$ make -j12
$ sudo make install
#接下来要修改:/usr/lib/pkgconfig/libmfx.pc
$ gedit /usr/lib/pkgconfig/libmfx.pc
#原:
Name: libmfx
Description: Intel(R) Media SDK Dispatcher by Toson
Version: 1.27
prefix=/opt/intel/mediasdk
libdir=/opt/intel/mediasdk/lib
includedir=/opt/intel/mediasdk/include
Libs: -L${libdir} -lmfx -lstdc++ -ldl -lrt -lva -lva-drm
Cflags: -I${includedir}
#修改为:
Name: libmfx
Description: Intel(R) Media SDK Dispatcher by Toson
Version: 1.27
prefix=/usr/local
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Libs: -L${libdir} -lmfx -ldispatch_shared -lva -lva-drm -lsupc++ -lstdc++
-ldl
Cflags: -I${includedir}
FFmpeg编译:
$ mkdir build
$ cd build
# 配置
$ ../configure --enable-shared --disable-static
# 如果想要在 FFMPEG 中编译 QSV 硬件编码器,则需要使用下面命令进行配置:
$ ../configure --enable-libmfx --enable-encoder=h264_qsv --enable-decoder=h264_qsv --enable-shared --disable-static
# 编译
$ make -j12
# 安装
$ sudo make install
验证:
# 如果开启了QSV,则可以使用此命令验证:
$ ffmpeg -codecs | grep qsv
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developersbuilt with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609configuration: --enable-libmfx --enable-encoder=h264_qsv --enable-decoder=h264_qsv --enable-shared --disable-staticlibavutil 56. 22.100 / 56. 22.100libavcodec 58. 35.100 / 58. 35.100libavformat 58. 20.100 / 58. 20.100libavdevice 58. 5.100 / 58. 5.100libavfilter 7. 40.101 / 7. 40.101libswscale 5. 3.100 / 5. 3.100libswresample 3. 3.100 / 3. 3.100DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_v4l2m2m h264_qsv ) (encoders: h264_qsv h264_v4l2m2m h264_vaapi )DEV.L. hevc H.265 / HEVC (High Efficiency Video Coding) (decoders: hevc hevc_qsv ) (encoders: hevc_qsv hevc_vaapi )DEVIL. mjpeg Motion JPEG (encoders: mjpeg mjpeg_qsv mjpeg_vaapi )DEV.L. mpeg2video MPEG-2 video (decoders: mpeg2video mpegvideo mpeg2_v4l2m2m mpeg2_qsv ) (encoders: mpeg2video mpeg2_qsv mpeg2_vaapi )D.V.L. vc1 SMPTE VC-1 (decoders: vc1 vc1_qsv vc1_v4l2m2m )DEV.L. vp8 On2 VP8 (decoders: vp8 vp8_v4l2m2m vp8_qsv ) (encoders: vp8_v4l2m2m vp8_vaapi )
三、FFmpeg命令行
ffmpeg工具:
$ ffmpeg -i input.mp4 output.avi
#ffmpeg转存网络视频流到本地
$ ffmpeg -i http://....7b_sd.mp4 -acodec copy -b 1680 out_1_1.mp4
#将视频文件转换成h264的1920x1080的文件
$ ffmpeg -i 输入文件名 -s 1920x1080 -vcodec h264 -i 输出文件名
# 提取音频流
$ ffmpeg -i 你的视频文件名 -f wav 你要保存的文件名.wav -y
ffplay工具:
$ ffplay output.avi
ffmpeg-修改分辨率:
# 法一:(缺点:如果分辨率的比例跟原视频的比例不一样,会导致视屏变形)
$ ffmpeg -i 1.mp4 -strict -2 -s 640x480 4.mp4
# 法二:(-1表示按照比例缩放,可保证视屏不会变形)
$ ffmpeg -i 1.mp4 -strict -2 -vf scale=-1:480 4.mp4
# 我自己使用的简单的转换
$ ffmpeg -i in.mp4 -vf scale=640:480 out.mp4
要将输出文件的视频比特率设置为64 kbit / s:
$ ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi
要强制输出文件的帧速率为24 fps:
$ ffmpeg -i input.avi -r 24 output.avi
要强制输入文件的帧速率(仅对原始格式有效)为1 fps,输出文件的帧速率为24 fps:
$ ffmpeg -r 1 -i input.m2v -r 24 output.avi
ffmpeg每个输出的转码过程可以通过下图描述:
_______ ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |v_________| || decoded || frames ||_________|________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|
ffmpeg调用libavformat库来读取输入文件并从中获取包含编码数据的数据包,然后将编码的数据包传递给解码器,解码器产生未压缩的帧(原始视频/ PCM音频/ …),可以通过过滤进一步处理。在过滤之后,帧被传递到编码器,编码器对它们进行编码并输出编码的分组。最后,这些传递给复用器,复用器将编码的数据包写入输出文件。
四、FFmpeg代码-部分函数
FFmpeg 解码流程所需要调用的 API 依次为:
av_register_all();
avformat_open_input(); //打开视频输入
av_find_stream_info(); //判断有无stream通道
av_find_best_stream(); //穷举所有的流,查找其中种类为CODEC_TYPE_VIDEO
avcodec_find_decoder(); //获取解码器
avcodec_alloc_context3(); //解码器内存分配
avcodec_parameters_to_context(); //填充解码参数
avcodec_open2(); //打开解码器
av_image_get_buffer_size(); //?
av_image_fill_arrays(); //?
while(av_read_frame()) {avcodec_send_packet(); //送入解码器,数据包解码avcodec_receive_frame(); //提取解码后的数据sws_getCachedContext(); //图像格式转换,涉及到图像缩放和格式转换算法。 //可取代sws_getContext(),因为sws_getCachedContext()会先判断是否需要再申请上下文内存空间。sws_scale(); //开始转换(sws_scale库可以在一个函数里面同时实现:1.图像色彩空间转换;2.分辨率缩放;3.前后图像滤波处理。)
}
H264视频流不解码,直接输出到另存文件的流程:
avcodec_register_all();
av_register_all();
avformat_network_init();
avformat_open_input(); //打开视频输入
av_find_stream_info(); //判断有无stream通道
avformat_alloc_output_context2(); //初始化用于输出的AVFormatContext结构体
avformat_new_stream(); //在输出对象中开启一路视频流通道
avcodec_parameters_copy(); //拷贝输入参数到输出参数中
avio_open(); //打开输出文件
av_dict_set(); //设置输出配置,可省略
avformat_write_header(); //写文件头
av_init_packet();
while() {av_read_frame(); //取出一帧av_interleaved_write_frame(); //写视频帧到文件
}
avformat_close_input(&i_fmt_ctx);
av_write_trailer(o_fmt_ctx); //写文件尾
avcodec_close(o_fmt_ctx->streams[0]->codec);
av_freep(&o_fmt_ctx->streams[0]->codec);
av_freep(&o_fmt_ctx->streams[0]);
avio_close(o_fmt_ctx->pb);
av_free(o_fmt_ctx);
av_packet_alloc()
使用av_packet_alloc来创建一个AVPacket的实例,但该函数并不会为数据分配空间,其指向数据域的指针为NULL。
通常调用av_read_frame将流中的数据读取到AVPacket中。
所以在每次循环的结束不能忘记调用av_packet_unref减少数据域的引用技术,当引用技术减为0时,会自动释放数据域所占用的空间。在循环结束后,调用av_packet_free来释放AVPacket本身所占用的空间。
av_packet_free()
首先将AVPacket指向的数据域的引用技术减1(数据域的引用技术减为0时会自动释放)
接着,释放为AVPacket分配的空间。
av_packet_free替代已被废弃的av_free_packet。
av_packet_unref()
void av_packet_unref(AVPacket *pkt)
{av_packet_free_side_data(pkt);av_buffer_unref(&pkt->buf);av_init_packet(pkt);pkt->data = NULL;pkt->size = 0;
}
av_init_packet()
void av_init_packet(AVPacket *pkt)
{pkt->pts = AV_NOPTS_VALUE;pkt->dts = AV_NOPTS_VALUE;pkt->pos = -1;pkt->duration = 0;
#if FF_API_CONVERGENCE_DURATION
FF_DISABLE_DEPRECATION_WARNINGSpkt->convergence_duration = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endifpkt->flags = 0;pkt->stream_index = 0;pkt->buf = NULL;pkt->side_data = NULL;pkt->side_data_elems = 0;
}
FFmpeg的libswscale的示例
参考:雷霄骅:https://blog.csdn.net/leixiaohua1020/article/details/42134965
FFmpeg支持多种像素拉伸的方式,定义位于libswscale\swscale.h中。
#define SWS_FAST_BILINEAR 1 //性能和速度之间有一个比好好的平衡
#define SWS_BILINEAR 2 //(Bilinear interpolation,双线性插值):4个点确定插值的点。
#define SWS_BICUBIC 4 //(Bicubic interpolation,双三次插值)性能比较好:16个点确定插值的点。
#define SWS_X 8
#define SWS_POINT 0x10 //(邻域插值)效果比较差:根据距离它最近的样点的值取得自己的值。
#define SWS_AREA 0x20
#define SWS_BICUBLIN 0x40
#define SWS_GAUSS 0x80
#define SWS_SINC 0x100
#define SWS_LANCZOS 0x200
#define SWS_SPLINE 0x400
五、测试代码
ffmpeg保存rtsp视频流小视频:
//
// Created by toson on 19-4-22.
//
#ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef __cplusplus
}
#endif
#include "unistd.h"
#include <iostream>
#include "thread"
#include "istream"
#include "chrono"
using std::chrono::seconds;
using std::chrono::milliseconds;
using std::chrono::steady_clock;
using std::chrono::duration_cast;
using namespace std;
bool bStop = false;
static signed rtsp2mp4()
{int err = 0;
AVFormatContext *i_fmt_ctx = nullptr;AVStream *i_video_stream = nullptr;
AVFormatContext *o_fmt_ctx = nullptr;AVStream *o_video_stream = nullptr;
avcodec_register_all();av_register_all();avformat_network_init();
// should set to NULL so that avformat_open_input() allocate a new onei_fmt_ctx = nullptr;//avformat_alloc_context();char rtspUrl[] = "rtsp://admin:admin123@192.168.1.102:554/cam/realmonitor?channel=1&subtype=0";const char* filename = "/home/toson/ffmpeg_test_videos/ffmpeg_t1_o8.mp4";
AVDictionary *dict = nullptr;
// av_dict_set(&dict, "rtsp_transport", "tcp", 0);
// av_dict_set(&dict, "stimeout", "3000000", 0); //设置超时时间3s,否则网络不通时会阻塞
// av_dict_set(&dict, "buffer_size", "1024000", 0);
// av_dict_set(&dict, "max_delay", "50000", 0);
if (avformat_open_input(&i_fmt_ctx, rtspUrl, nullptr, nullptr)!=0){fprintf(stderr, "could not open input file\n");return -1;}
if (avformat_find_stream_info(i_fmt_ctx, nullptr)<0){fprintf(stderr, "could not find stream info\n");return -1;}
//av_dump_format(i_fmt_ctx, 0, argv[1], 0);
// find first video streamfor (unsigned i=0; i<i_fmt_ctx->nb_streams; i++){if (i_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){i_video_stream = i_fmt_ctx->streams[i];break;}}if (i_video_stream == nullptr){fprintf(stderr, "didn't find any video stream\n");return -1;}
// 初始化一个用于输出的AVFormatContext结构体err = avformat_alloc_output_context2(&o_fmt_ctx, nullptr, nullptr, filename);std::cout << err << " = avformat_alloc_output_context2" << std::endl;
// since all input files are supposed to be identical (framerate, dimension, color format, ...)// we can safely set output codec values from first input fileo_video_stream = avformat_new_stream(o_fmt_ctx, nullptr);o_video_stream->id = 0;o_video_stream->codecpar->codec_tag = 0;avcodec_parameters_copy(o_video_stream->codecpar, (*(i_fmt_ctx->streams))->codecpar);// 或者使用下面方式
// AVCodecContext *c = o_video_stream->codec;
// c->bit_rate = 400000;
// c->codec_id = i_video_stream->codec->codec_id;
// c->codec_type = i_video_stream->codec->codec_type;
// c->time_base.num = i_video_stream->time_base.num;
// c->time_base.den = i_video_stream->time_base.den;
// fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);
// c->width = i_video_stream->codec->width;
// c->height = i_video_stream->codec->height;
// c->pix_fmt = i_video_stream->codec->pix_fmt;
// printf("%d %d %d", c->width, c->height, c->pix_fmt);
// c->flags = i_video_stream->codec->flags;
// c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
// c->me_range = i_video_stream->codec->me_range;
// c->max_qdiff = i_video_stream->codec->max_qdiff;
// c->qmin = i_video_stream->codec->qmin;
// c->qmax = i_video_stream->codec->qmax;
// c->qcompress = i_video_stream->codec->qcompress;avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE);av_dict_set(&dict, "movflags", "faststart", 0);// 设置 moov 前置err = avformat_write_header(o_fmt_ctx, &dict);if(err) {fprintf(stderr, "%d = avformat_write_header\n", err);}
AVPacket i_pkt;av_init_packet(&i_pkt);bool first = true;
// 警告:Application provided invalid, non monotonically increasing dts to muxer in stream 0: 52200 >= 43200// 百度查到的说法是:发现源文件的Video的duration 和Audio的duration不同,所以声音和图像无法同步。// 我丢弃了这些帧:av_read_frame(i_fmt_ctx, &i_pkt);
int count = 0;while (!bStop){steady_clock::time_point idtime = steady_clock::now();av_init_packet(&i_pkt);av_packet_unref(&i_pkt);
if (av_read_frame(i_fmt_ctx, &i_pkt) <0 )break;std::cout << "av_read_frame cost: "<< duration_cast<chrono::milliseconds>(steady_clock::now() - idtime).count()<< "ms" << std::endl;
// 判断是否关键帧。(首帧务必要从关键帧开始。)if (first){if (i_pkt.flags & AV_PKT_FLAG_KEY) {o_video_stream->start_time = 0;o_video_stream->duration = 0;o_video_stream->first_dts = i_pkt.dts;o_video_stream->cur_dts = 0;o_video_stream->last_IP_pts = 0;} else {continue;}}first = false;
// pts and dts should increase monotonically// pts should be >= dtsi_pkt.pts -= o_video_stream->first_dts;i_pkt.dts -= o_video_stream->first_dts;
static int num = 1;printf("frame %d\n", num++);av_interleaved_write_frame(o_fmt_ctx, &i_pkt); //写入文件,并释放对象
// av_write_frame(o_fmt_ctx, &i_pkt); //写入文件//av_free_packet(&i_pkt);//av_init_packet(&i_pkt);usleep(3000);count++;if(count>=100) { //只保存了100帧,10sbreak;}}
avformat_close_input(&i_fmt_ctx);
av_write_trailer(o_fmt_ctx);
avcodec_close(o_fmt_ctx->streams[0]->codec);av_freep(&o_fmt_ctx->streams[0]->codec);av_freep(&o_fmt_ctx->streams[0]);
avio_close(o_fmt_ctx->pb);av_free(o_fmt_ctx);
printf("按任意键停止\n");return 0;
}
int main(int argc, char **argv)
{bStop = false;
std::thread t(rtsp2mp4);
printf("按任意键停止录像\n");getchar();bStop = true;printf("按任意键退出\n");getchar();t.join();
return 0;
}
ffmpeg读取视频帧率:
//读取视频帧率int frame_rate = 0;if(i_fmt_ctx->streams[0]->r_frame_rate.den > 0){ //注:r_frame_rate是流的实际基本帧速率。这是可以准确表示所有时间戳的最低帧速率(它是流中所有帧速率中最不常见的倍数)。注意,这个值只是一个猜测!//我测试后发现,r_frame_rate并不是我们需要的视频帧率。//frame_rate = i_fmt_ctx->streams[0]->r_frame_rate.num/i_fmt_ctx->streams[0]->r_frame_rate.den;fprintf(stderr, "r_frame_rate.num: %d .den: %d --- ",i_fmt_ctx->streams[0]->r_frame_rate.num,i_fmt_ctx->streams[0]->r_frame_rate.den);}if(i_fmt_ctx->streams[0]->avg_frame_rate.den > 0){ //注:avg_frame_rate是平均帧速率。//经测试,avg_frame_rate才是我们需要的视频帧率。frame_rate = i_fmt_ctx->streams[0]->avg_frame_rate.num/i_fmt_ctx->streams[0]->avg_frame_rate.den;fprintf(stderr, "avg_frame_rate.num: %d .den: %d --- ",i_fmt_ctx->streams[0]->avg_frame_rate.num,i_fmt_ctx->streams[0]->avg_frame_rate.den);}if(i_fmt_ctx->streams[0]->codec->framerate.den > 0){ //注:ffmpeg官方解释该变量是:// *-解码:对于在压缩比特流中存储帧速率值的编解码器,解码器可以将其导出到此处。0,1未知时。// *-编码:可用于向编码器发送CFR内容的帧速率信号。//经测试,该值=avg_frame_rate,所以可忽视。//frame_rate = i_fmt_ctx->streams[0]->codec->framerate.num/i_fmt_ctx->streams[0]->codec->framerate.den;fprintf(stderr, "codec->framerate.num: %d .den: %d --- ",i_fmt_ctx->streams[0]->codec->framerate.num,i_fmt_ctx->streams[0]->codec->framerate.den);}fprintf(stderr, "frame_rate: %d \n", frame_rate);
文献:
- 雷霄骅 ffmpeg:https://blog.csdn.net/leixiaohua1020/column/info/ffmpeg-devel
- FFmpeg从入门到精通_刘歧;赵文杰(著)_机械工业出版社
- FFmpeg官网http://ffmpeg.org/
- GitHub:https://github.com/FFmpeg/FFmpeg
FFmpeg自学入门笔记相关推荐
- openCV自学入门笔记
opencv-3.4.0编译 (注:确保cuda版本为9.0,确保FFmpeg已安装) #必要的依赖项 sudo apt-get install build-essential sudo apt-ge ...
- 十年公务员转行IT,自学AI三年,他淬炼出746页机器学习入门笔记
整理 | Jane 编辑 | Just 出品 | AI科技大本营(ID:rgznai100) 近期,梁劲传来该笔记重大更新的消息.<机器学习--从入门到放弃>这本笔记的更新没有停止,在基于 ...
- 【自学】零基础MATLAB入门笔记
[自学]零基础MATLAB入门笔记 (一) 第一章 MATLAB的新建工程和基本操作与处理 文章目录 [自学]零基础MATLAB入门笔记 (一) 前言 一.MATLAB简介 二.软件下载 三.新建工程 ...
- FFmpeg从入门到精通读书笔记(1)
笔者才开始学习音视频开发,FFmpeg从入门到精通读书笔记系列主要是基于阅读刘歧.赵文杰编著的<FFmpeg从入门到精通>以及雷霄骅博士博客总结写的入门心得体会. 官方文档资料 FFmpe ...
- FDTD Solutions自学整理笔记入门教程(3):监视器Monitors
FDTD自学整理笔记入门教程之监视器(转载+改动) 3.监视器Monitors:(这个编辑器真的不方便,文字+图片的操作真是太麻烦了,为了方便就简单截图上传)
- 《FFmpeg从入门到精通》读书笔记(一)
写在前面 最近在读<FFmpeg从入门到精通>这本书,结合着雷神的博客,学习音视频的知识- 在学习的过程中,也记录了一些摘要.因为是边看边记的,所以一些要点在看到后面的时候,需要反过来整理 ...
- python3入门与进阶笔记_我的Python3萌新入门笔记
Python3萌新入门笔记是一系列真实的自学笔记. 当然,它也是比较全面的入门教程,共包括54篇笔记. 从第一篇笔记开始,大半年的时间我都是在自学和组织教程内容. 我觉得有必要,把我自己的学习过程和大 ...
- python3萌新入门笔记_我的Python3萌新入门笔记
Python3萌新入门笔记是一系列真实的自学笔记. 当然,它也是比较全面的入门教程,共包括54篇笔记. 从第一篇笔记开始,大半年的时间我都是在自学和组织教程内容. 我觉得有必要,把我自己的学习过程和大 ...
- 500多页的机器学习入门笔记,下载超5万次,都讲了些什么?
导读:今年 4 月,梁劲在百度云盘上传了一份自己整理的学习笔记--<机器学习--从入门到放弃>.这份学习笔记 540 多页,图文并茂,而且全部用英文撰写,如今这份文档的下载量已超过 500 ...
最新文章
- 独家 | 手把手教你用PyTorch快速准确地建立神经网络(附4个学习用例)
- 华为鸿蒙系统强势来袭,呼之欲出的华为神作——鸿蒙2.0 强势来袭
- 以太网口差分电平_以太网接口学习笔记
- python:else与循环语句联合用法
- Android开发环境配置介绍
- android 项目 功能 源码 eclipse的
- 华三 h3c 单臂路由配置
- Linux正确查看内存占用
- RTL8211E应用(一)之芯片功能介绍
- sqlmap指定cookie_Sqlmap Cookie注入 教程
- 如何建立强有力的人脉关系?
- SVG 研究之路 - 再談 defs
- 圣诞节马上到了。H5+CSS3+JS制作圣诞帽头像源码送给你们。。。
- win7音量图标不见了怎么办
- 阻滞增长模型求解_阻滞增长模型研究解读.ppt
- 一键封装app--webapp、HybridApp
- mysql 自动生成时间戳
- Python和PostgreSQL,PostGIS,空间数据管理
- mybatis错误:Could not resolve resource location pattern [classpath:com/demon/user/mapper/*.xml]: class
- Rust:Structuring and handling errors in 2020学习笔记