命令行

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);

文献:

  1. 雷霄骅 ffmpeg:https://blog.csdn.net/leixiaohua1020/column/info/ffmpeg-devel
  2. FFmpeg从入门到精通_刘歧;赵文杰(著)_机械工业出版社
  3. FFmpeg官网http://ffmpeg.org/
  4. GitHub:https://github.com/FFmpeg/FFmpeg

FFmpeg自学入门笔记相关推荐

  1. openCV自学入门笔记

    opencv-3.4.0编译 (注:确保cuda版本为9.0,确保FFmpeg已安装) #必要的依赖项 sudo apt-get install build-essential sudo apt-ge ...

  2. 十年公务员转行IT,自学AI三年,他淬炼出746页机器学习入门笔记

    整理 | Jane 编辑 | Just 出品 | AI科技大本营(ID:rgznai100) 近期,梁劲传来该笔记重大更新的消息.<机器学习--从入门到放弃>这本笔记的更新没有停止,在基于 ...

  3. 【自学】零基础MATLAB入门笔记

    [自学]零基础MATLAB入门笔记 (一) 第一章 MATLAB的新建工程和基本操作与处理 文章目录 [自学]零基础MATLAB入门笔记 (一) 前言 一.MATLAB简介 二.软件下载 三.新建工程 ...

  4. FFmpeg从入门到精通读书笔记(1)

    笔者才开始学习音视频开发,FFmpeg从入门到精通读书笔记系列主要是基于阅读刘歧.赵文杰编著的<FFmpeg从入门到精通>以及雷霄骅博士博客总结写的入门心得体会. 官方文档资料 FFmpe ...

  5. FDTD Solutions自学整理笔记入门教程(3):监视器Monitors

    FDTD自学整理笔记入门教程之监视器(转载+改动) 3.监视器Monitors:(这个编辑器真的不方便,文字+图片的操作真是太麻烦了,为了方便就简单截图上传)

  6. 《FFmpeg从入门到精通》读书笔记(一)

    写在前面 最近在读<FFmpeg从入门到精通>这本书,结合着雷神的博客,学习音视频的知识- 在学习的过程中,也记录了一些摘要.因为是边看边记的,所以一些要点在看到后面的时候,需要反过来整理 ...

  7. python3入门与进阶笔记_我的Python3萌新入门笔记

    Python3萌新入门笔记是一系列真实的自学笔记. 当然,它也是比较全面的入门教程,共包括54篇笔记. 从第一篇笔记开始,大半年的时间我都是在自学和组织教程内容. 我觉得有必要,把我自己的学习过程和大 ...

  8. python3萌新入门笔记_我的Python3萌新入门笔记

    Python3萌新入门笔记是一系列真实的自学笔记. 当然,它也是比较全面的入门教程,共包括54篇笔记. 从第一篇笔记开始,大半年的时间我都是在自学和组织教程内容. 我觉得有必要,把我自己的学习过程和大 ...

  9. 500多页的机器学习入门笔记,下载超5万次,都讲了些什么?

    导读:今年 4 月,梁劲在百度云盘上传了一份自己整理的学习笔记--<机器学习--从入门到放弃>.这份学习笔记 540 多页,图文并茂,而且全部用英文撰写,如今这份文档的下载量已超过 500 ...

最新文章

  1. 独家 | 手把手教你用PyTorch快速准确地建立神经网络(附4个学习用例)
  2. 华为鸿蒙系统强势来袭,呼之欲出的华为神作——鸿蒙2.0 强势来袭
  3. 以太网口差分电平_以太网接口学习笔记
  4. python:else与循环语句联合用法
  5. Android开发环境配置介绍
  6. android 项目 功能 源码 eclipse的
  7. 华三 h3c 单臂路由配置
  8. Linux正确查看内存占用
  9. RTL8211E应用(一)之芯片功能介绍
  10. sqlmap指定cookie_Sqlmap Cookie注入 教程
  11. 如何建立强有力的人脉关系?
  12. SVG 研究之路 - 再談 defs
  13. 圣诞节马上到了。H5+CSS3+JS制作圣诞帽头像源码送给你们。。。
  14. win7音量图标不见了怎么办
  15. 阻滞增长模型求解_阻滞增长模型研究解读.ppt
  16. 一键封装app--webapp、HybridApp
  17. mysql 自动生成时间戳
  18. Python和PostgreSQL,PostGIS,空间数据管理
  19. mybatis错误:Could not resolve resource location pattern [classpath:com/demon/user/mapper/*.xml]: class
  20. Rust:Structuring and handling errors in 2020学习笔记

热门文章

  1. EPICP安装与测试
  2. Android6.0运行时权限处理
  3. 32位计算机如何升级,32位改64位系统怎么安装 32位怎么升级64位系统
  4. Matlab读取并输出stl文件
  5. Android图片上传的两种方式
  6. 学习半年Java的初次经验分享
  7. Shiro 安全框架
  8. .ts 音频文件转换成 .mp3 文件
  9. BGP选路规则(实验做的有点乱)
  10. CSR867x — CSR8670平台开发调试经验