ffmpeg提取音频播放器总结

ffmpeg提取音频播放器总结; 
一:简介 
从编写音频播放器代码到完成播放器编写,测试,整整5天的时间,这时间还不算之前对 ffmpeg熟悉的时间,可以说是历经千辛万苦,终于搞出来了,虽然最终效果还不是很理想,但是已经可以很流畅的播放某些歌曲了,说是某些歌曲,是因为还有些歌曲播放效果不是很好,有些许杂音,至于那些歌曲能够顺利播放,那些不能够,我现在也摸不准是什么原因导致的,有待进一步钻研,等啥时候调好了,就用自己的这个播放器听歌曲了,嘿嘿; 
a:插播:) 
/**************/ 
这一部分属于插播内容,就不用看了; 
tv视频播放; 
采用img_convert时,是转换成24RGB快呢,还是32RGB快呢?可能前者快吧;似乎用qimage的话只能转换成32RGB了;因为它只有三种颜色深度1-p, 8-p, 32-p所以,只能选择32-p了; 

下面是AVFrame的结构,具体可以看这里: 
http://cekirdek.pardus.org.tr/~ismail/ffmpeg-docs/avcodec_8h-source.html#l00424 
就是一个宏定义,咳。。。 
/**************/ 
二:音频播放器原理 
音频播放器过程如下所示: 
打开文件--分析文件格式--打开对应解码器--读取一音频帧--解码音频帧--音频数据写入音频设备--循环读取音频帧--再解码。。。如此循环下去; 
整个播放器实现原理详细说明为,采用ffmpeg提供的API函数先用av_open_input_file打开音频文件,分析文件得到格式信息,然后识别格式,并查找对应的解码器,再得到针对此音频文件的解码器之后,用av_read_frame从音频文件中读取一帧,然后对其用 avcodec_decode_audio函数进行解码,在将解码之后的PCM音频数据直接写到audio设备(/dev/dsp)上,根据linux音频设备的原理,此时你就应该听到悦耳的歌声了; 
三:重点要点说明 
在这个过程当中有几处需要特别注意,下面详细说明一下: 
1、不同音频文件格式对音频压缩率不同,导致对于同一个音频包,你解压出来的音频数据大小也是不一样的,这一点无需惊奇,但是对于这些解压出来的音频数据,一定要保证全部写到声卡当中去,这样才能够作为你能听到悦耳歌声的基础,这里留意一下,这只是一个基础,要想完全实现好此播放器,下一点更是不可或缺的;我之前之所以在调试时总是听到声音很杂乱,或者带有金属声,就是因为声音没有全部写到音频设备中去,当然,可能或多或少也有一些写音频数据的太快的原故; 
2、在确认了解码后的数据是完整的之后,可以将数据写入到音频设备当中了(/dev/dsp),这里很关键的一点就是要对音频设备进行设置,否则你也听不到你想听到的声音:( 
对音频设备的设置主要是四个方面,这不代表其他方面不设置哦: 
设置采样率(有关音频采样率,在我blog前面的文章当中有说明,一般有44100hz,48000hz,22050?不记得了,你查看我blog中前面的文章吧,嘿嘿): 
ioctl (fd, SNDCTL_DSP_SPEED, &(pCodecCtx->sample_rate)); 
设置音频声道数(这个很好理解,一般都是立体声了) 
// set channels; 
    i = pCodecCtx->channels; 
    #ifdef AUDIO_DEBUG 
    printf ("pCodecCtx->channels:%d\n", pCodecCtx->channels); 
    #endif 
    if ((ioctl (fd, SNDCTL_DSP_CHANNELS, &i)) == -1) 
    { 
        fprintf (stderr, "Set Audio Channels %d failed:%s\n", i, 
             strerror (errno)); 
        return (-1); 
    } 
这里需要说明的一点是,如果是立体声,则此处i应该等于2,而不是1,网上很多文章这里都说明的不正确,我之前就一直以为立体声为1,单声道为0,总是不出声音,后来一狠心,改为2,尽然ok,faint; 
结论:网上的东西啊,不可全信之。。。。。。。。。。。。。。。。。。。。。。。。。。。 
设置量化位数(这个量化位数是指对声音的振幅进行采样的位数,以前一般是8位,现在以16位居多,更高位数对于普通用户用不着,只能在专业音乐中才有价值) 
i = AFMT_S16_LE;        (16位,小端存储,也即intel的倒序数据存储) 
ioctl (fd, SNDCTL_DSP_SETFMT, &i); 
设置音频驱动级缓存 
i = (0x0004 << 16) + 0x000b;        // four 2kb buffer;你看着对应改就行了(这里是四个2kb缓存) 
ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &i); 
这里也可以不设置,用系统默认自定义也可; 

另外有一个疑问也顺带解决了: 
Q:播放音频和pts有关系么?需要他来调整播放的快慢么?就像视频那样? 
A:基本没有关系,至少我目前没有用到这个咚咚,pts应该实在视频当中采用到的,pts是显示时间戳,dts是解码时间戳;以后搞到视频再详细说明啦;不需要,对于写音频数据,系统,或者更准确的说驱动会自动调整,写得快,他会阻塞你的写,写的慢?你的机器该换了,嘿嘿,玩笑一个。。。增加缓存可以解决慢的问题; 
Q:如何调试音频播放器? 
这里需要注意两点,一点是你要保证解码后的数据确实是PCM数据;第二点是你要确定数据准确无误,全部写入音频文件,否则会出现各种各样的暴音啊之类的事情,不可预测; 
有关这两点你可以分别调试;第一点,可以将解码后的数据写入一个文件当中,然后利用一些音频分析软件(能够分析PCM数据),播放即可,看你解码的数据是否正确,完整,如果没有问题,那这一步就完成了,我在这里没有卡壳,直接过;下一步,我是扔进去很多时间,由于我的指针使用不当,导致总是漏写数据,我在下面也会把我的错误代码贴出来,以做对比,大家也都可以来看看,这一点我想经常和指针打交道的就肯定没问题了的; 

这里向大家推荐windows下的cooledit软件,不用找注册码,反正能试用,没问题,功能绝对够用,而且分析声音频播非常形象,郑重推荐;虽然windows和linux切换麻烦了点,嘿嘿:)不过如果你有两台电脑,另说啦。。。 
下面将这个音频播放器的源代码贴出来,以便大家互相学习; 
我的编译环境是 
os:Neoshine linux (2.6.14-1.1644_dt_5); 
硬件:普通pc机; 
/*************************************************************************** 
*            main.cc 

*  Thu Nov  9 20:47:33 2006 
*  Copyright  2006 
*  Email lsosa.BIT 
*  Author lsosa.BIT 
****************************************************************************/ 

#include <avcodec.h> 
#include <avformat.h> 
#include <avutil.h> 
#include <assert.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <X11/Xlib.h> 
#include <sys/soundcard.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <sys/ioctl.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sched.h> 

#define ALL_DEBUG 

#ifdef ALL_DEBUG 
    #define AV_DEBUG 
    #define AUDIO_DEBUG 
#endif 

//------------------------------------------------------------------------------ 
// manipulations for file 
int open_file (char *file_name, int mode) 

    // open file file_name and return the file descriptor; 
    int fd; 

    if ((fd = open (file_name, mode)) < 0) 
    { 
        fprintf (stderr, " Can't open %s!\n", file_name); 
        exit (-1); 
    } 
    return fd; 


int set_audio (int fd, AVCodecContext * pCodecCtx) 

    // set the properties of audio device with pCodecCtx; 

    int i, err; 
    /* 设置适当的参数,使得声音设备工作正常 */ 
    /* 详细情况请参考Linux关于声卡编程的文档 */ 
   
    i = 0; 
    ioctl (fd, SNDCTL_DSP_RESET, &i); 
    i = 0; 
    ioctl (fd, SNDCTL_DSP_SYNC, &i); 
    i = 1; 
    ioctl (fd, SNDCTL_DSP_NONBLOCK, &i); 
   
    // set sample rate; 
    #ifdef AUDIO_DEBUG 
    printf ("pCodecCtx->sample_rate:%d\n", pCodecCtx->sample_rate); 
    #endif 
    i = pCodecCtx->sample_rate; 
    if (ioctl (fd, SNDCTL_DSP_SPEED, &i) == -1) 
    { 
        fprintf (stderr, "Set speed to %d failed:%s\n", i, 
             strerror (errno)); 
        return (-1); 
    } 
    if (i != pCodecCtx->sample_rate) 
    { 
        fprintf (stderr, "do not support speed %d,supported is %d\n", 
             pCodecCtx->sample_rate, i); 
        return (-1); 
    } 
   
    // set channels; 
    i = pCodecCtx->channels; 
    #ifdef AUDIO_DEBUG 
    printf ("pCodecCtx->channels:%d\n", pCodecCtx->channels); 
    #endif 
    if ((ioctl (fd, SNDCTL_DSP_CHANNELS, &i)) == -1) 
    { 
        fprintf (stderr, "Set Audio Channels %d failed:%s\n", i, 
             strerror (errno)); 
        return (-1); 
    } 
    if (i != pCodecCtx->channels) 
    { 
        fprintf (stderr, "do not support channel %d,supported %d\n", 
            pCodecCtx->channels, i); 
        return (-1); 
    } 
    // set bit format; 
    i = AFMT_S16_LE; 
    if (ioctl (fd, SNDCTL_DSP_SETFMT, &i) == -1) 
    { 
        fprintf (stderr, "Set fmt to bit %d failed:%s\n", i, 
             strerror (errno)); 
        return (-1); 
    } 
    if (i != AFMT_S16_LE) 
    { 
        fprintf (stderr, "do not support bit %d, supported %d\n", 
             AFMT_S16_LE, i); 
        return (-1); 
    } 
   
    // set application buffer size; 
    // i = (0x00032 << 16) + 0x000c;        // 32 4kb buffer; 
    // ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &i); 
    i = 1; 
    ioctl (fd, SNDCTL_DSP_PROFILE, &i); 
   
    return 0; 


void close_file (int fd) 

    // close the file pointed by file descriptor fd; 
    close (fd); 


//------------------------------------------------------------------------------ 
// handle audio; 

void display_AVCodecContext(AVCodecContext *pCodecCtx){ 
    // 
    #define STDOUT stderr 
    fprintf(STDOUT, "pCodecCtx->bit_rate:%d\n", pCodecCtx->bit_rate); 
    fprintf(STDOUT, "pCodecCtx->sample_rate:%d\n", pCodecCtx->sample_rate); 
    fprintf(STDOUT, "pCodecCtx->channels:%d\n", pCodecCtx->channels); 
    fprintf(STDOUT, "pCodecCtx->frame_size:%d\n", pCodecCtx->frame_size); 
    fprintf(STDOUT, "pCodecCtx->frame_number:%d\n", pCodecCtx->frame_number); 
    fprintf(STDOUT, "pCodecCtx->delay:%d\n", pCodecCtx->delay); 
    fprintf(STDOUT, "pCodecCtx->frame_bits:%d\n", pCodecCtx->frame_bits); 


// error if return -1; 
// success if return 0; 
// 这里要用到指向指针的指针,否则传不到值; 
int av_init (char *file_name, AVFormatContext ** pFormatCtx, 
     AVCodecContext ** pCodecCtx, int *p_audioStream) 

    // init the codec and format of input file file_name; 
    int audioStream, i; 
    AVCodec *pCodec; 
    // catch error 
    assert(file_name != NULL); 
    assert(*pFormatCtx != NULL); 
    assert(*pCodecCtx != NULL); 
   
    // Register all formats and codecs 
    av_register_all (); 
   
    // open file 
    if (av_open_input_file (pFormatCtx, file_name, NULL, 0, NULL) != 0){ 
        // Couldn't open file 
        fprintf (stderr, " Can't open %s!\n", file_name); 
        return -1;   
    } 

    // Retrieve stream information 
    if (av_find_stream_info (*pFormatCtx) < 0){ 
        // Couldn't find stream information 
        return -1;   
    } 
   
    #ifdef AV_DEBUG 
    // Dump information about file onto standard error 
    dump_format (*pFormatCtx, 0, file_name, false); 
    #endif 
   
    // Find the first audio and video stream respectively 
    audioStream = -1; 
    for (i = 0; i < (*pFormatCtx)->nb_streams; i++){ 
        if ((*pFormatCtx)->streams->codec->codec_type == 
            CODEC_TYPE_AUDIO) 
        { 
            audioStream = i; 
        } 
    } 
   
    #ifdef AV_DEBUG 
    // dump_stream_info(pFormatCtx); 
    #endif 
   
    // exclude error 
    if (audioStream == -1){ 
        // Didn't find a audio or video stream 
        return -1;   
    } 

    // Get a pointer to the codec context for the audio stream 
    *pCodecCtx = (*pFormatCtx)->streams[audioStream]->codec; 

    // Find the decoder for the audio stream 
    pCodec = avcodec_find_decoder ((*pCodecCtx)->codec_id); 
    if (pCodec == NULL) 
        return -1;    // Codec not found 

    // Open codec 
    if (avcodec_open ((*pCodecCtx), pCodec) < 0){ 
        return -1;    // Could not open codec 
    } 
   
    #ifdef AUDIO_DEBUG 
    // printf ("pCodecCtx->sample_rate:%d, audioStream:%d\n", (*pCodecCtx)->sample_rate, audioStream); 
    // display_AVCodecContext(*pCodecCtx); 
    #endif 
   
    *p_audioStream = audioStream; 
   
    return 0; 


void av_play (AVFormatContext * pFormatCtx, 
     AVCodecContext * pCodecCtx, int audioStream) 

    // which was read from one frame; 
    AVPacket packet; 
    uint32_t len; 
    uint8_t decompressed_audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 
    int decompressed_audio_buf_size; 
    uint8_t * p_decompressed_audio_buf; 
    int fd = -1;    // audio file or test file? 
    char filename[64] = "/dev/dsp"; 
    int mode = O_WRONLY; 
    // 
   
    // open audio file or written file 
    // printf("fd:%d", fd); 
    fd = open_file(filename, mode); 
    // printf("fd:%d", fd); 
    // 
    set_audio(fd, pCodecCtx); 
   
    // 
    printf("(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2=%d\n", (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);
    printf("AVCODEC_MAX_AUDIO_FRAME_SIZE=%d\n", AVCODEC_MAX_AUDIO_FRAME_SIZE); 
   
    // for a test 
    // char test_file[256] = "my_pcm.pcm"; 
    // fd = open_file(test_file, mode); 
   
    #ifdef AV_DEBUG 
    static int size = 0; 
    #endif 
    // 
   
    // set the sched priority 
    // 这是为了提高音频优先级;不晓得起作用没; 
    int policy = SCHED_FIFO; 
    sched_setscheduler(0, policy, NULL); 
   
    int write_buf_size = 4196; 
    int written_size; 
    while (av_read_frame (pFormatCtx, &packet) >= 0) 
    { 
        // Is this a packet from the audio stream? 
        // 判断是否音频帧; 
        if (packet.stream_index == audioStream) 
        { 
            // Decode audio frame 
            // 解码音频数据为pcm数据; 
            len = avcodec_decode_audio (pCodecCtx, 
                            (int16_t *)decompressed_audio_buf, 
                            &decompressed_audio_buf_size,        // it is the decompressed frame in BYTES 解码后的数据大小,字节为单位; 
                            packet.data, 
                            packet.size ); 
            // printf("len:%d, packet.size:%d\n", len, packet.size); 
            if ( len < 0 ){ 
                // if error len = -1 
                printf("+----- error in decoding audio frame\n"); 
                // exit(0); 
            } 
            // test lsosa 
           
           
            // printf("size = %d\n", size); 
            //****************************************************************** 
            // 重点是这一部分,使用oss播放的代码,之前的数据写是否完整的问题就是出在这里,或者是前面的set_audio函数设置不正确; 
            // audio_buf_info info; 
            p_decompressed_audio_buf = decompressed_audio_buf; 
            while ( decompressed_audio_buf_size > 0 ){ 
                // 解码后数据不为零,则播放之,为零,则; 
                written_size = write(fd, p_decompressed_audio_buf, decompressed_audio_buf_size); 
                if ( written_size == -1 ){ 
                    // printf("error:decompressed_audio_buf_size:%d, decompressed_audio_buf_size:%d, %s\n", \ 
                                decompressed_audio_buf_size, decompressed_audio_buf_size,strerror(errno)); 
                    // usleep(100); 
                    continue; 
                } 
                // printf("decompressed_audio_buf_size:%d, written_size:%d\n", \ 
                            decompressed_audio_buf_size, written_size); 
                decompressed_audio_buf_size -= written_size; 
                p_decompressed_audio_buf += written_size; 
               
            }// end while 
            //****************************************************************** 
        } 
        else 
        { 
            printf("+----- this is not audio frame\n"); 
        }// end if 
        // Free the packet that was allocated by av_read_frame 
        av_free_packet (&packet); 
    }// end while of reading one frame; 
       
    close_file(fd); 


void av_close (AVFormatContext * pFormatCtx, AVCodecContext * pCodecCtx) 

    // close the file and codec 

    // Close the codec 
    avcodec_close (pCodecCtx); 

    // Close the video file 
    av_close_input_file (pFormatCtx); 


//------------------------------------------------------------------------------ 

int main (int argc, char **argv){ 
    // 
    AVFormatContext *pFormatCtx; 
    int audioStream = -1; 
    AVCodecContext *pCodecCtx; 
   
    // exclude the error about args; 
    if ( argc != 2 ){ 
        printf("please give a file name\n"); 
        exit(0); 
    } 
   
    // 注意:这里要用到指向指针的指针,是因为这个初始化函数需要对指针的地址进行改动, 
    // 所以,只有这么做,才能达到目的; 
    if ( av_init(argv[1], &pFormatCtx, &pCodecCtx, &audioStream) < 0 ){ 
        // 
        fprintf(stderr, "error when av_init\n"); 
    } 
   
    // play the audio file 
    av_play(pFormatCtx, pCodecCtx, audioStream); 
   
    // close all the opend files 
    av_close(pFormatCtx, pCodecCtx); 
   


http://weiyuhu.iteye.com/blog/576610


ffmpeg提取音频播放器总结


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【BZOJ 4103】 [Thu Summer Camp 2015]异或运算 可持久化01Trie

我们观察数据&#xff1a;树套树 PASS 主席树 PASS 一层一个Trie PASS 再看&#xff0c;异或&#xff01;我们就把目光暂时定在01Tire然后我们发现&#xff0c;我们可以带着一堆点在01Trie上行走&#xff0c;因为O(n*q*30m*30)是一个可选复杂度。 我们想一下我们正常的时候…

Docker学习笔记——Java及Tomcat Dockerfile

1、Java Dockerfile创建项目目录java&#xff0c;目录下上传所需java版本压缩包&#xff0c;并创建Dockerfile文件&#xff0c;项目结构如下&#xff1a;java-Dockerfile-jdk-8u111-linux-x64.gzDockerfile内容&#xff1a;# JAVA # Version 1.8.0_111 # SOURCE_IMAGE FROM cen…

rabbitmq接口异常函数方法_RabbitMQ监控(三):监控队列状态

#RabbitMQ 监控(三)验证RabbitMQ健康运行只是确保消息通信架构可靠性的一部分&#xff0c;同时&#xff0c;你也需要确保消息通信结构配置没有遭受意外修改&#xff0c;从而避免应用消息丢失。RabbitMQ Management HTTP API提供了一个方法允许你查看任何vhost上的任何队列&…

FFMpeg语法参数中文参考手册

要查看你的ff mpeg支持哪些 格式&#xff0c;可以用如下命令&#xff1a;$ ffmpeg -formats | less还可以把 视频文件导出成jpg序列帧&#xff1a;$ ffmpeg -i bc-cinematic-en.avi example.%d.jpgdebian下安装ffmpeg很简单&#xff1a;&#xff03;apt-get install ffmpegffmp…

Java类集框架 —— LinkedHashMap源码分析

前言 我们知道HashMap底层是采用数组单向线性链表/红黑树来实现的&#xff0c;HashMap在扩容或者链表与红黑树转换过程时可能会改变元素的位置和顺序。如果需要保存元素存入或访问的先后顺序&#xff0c;那就需要采用LinkedHashMap了。 LinkedHashMap结构 LinkedHashMap继承自H…

apache 支持.htaccess重写url

1. httpd.conf 添加&#xff1a; <Directory />Options Indexes FollowSymLinks MultiviewsAllowOverride allRequire all grantedRewriteEngine On</Directory> 开启&#xff1a; 在phpinfo里找到&#xff1a; 说明开启成功。 2.httpd-vhosts.conf &#xff08;开…

oom 如何避免 高并发_【高并发】高并发环境下如何防止Tomcat内存溢出?看完我懂了!!...

【高并发】高并发环境下如何防止Tomcat内存溢出&#xff1f;看完我懂了&#xff01;&#xff01;发布时间&#xff1a;2020-04-19 00:47,浏览次数&#xff1a;126, 标签&#xff1a;Tomcat写在前面随着系统并发量越来越高&#xff0c;Tomcat所占用的内存就会越来越大&#xff0…

[JSOI2008]最小生成树计数

OJ题号&#xff1a;  BZOJ1016 题目大意&#xff1a;   给定一个无向带权图&#xff0c;求最小生成树的个数。 思路&#xff1a;   先跑一遍最小生成树&#xff0c;统计相同权值的边出现的个数。   易证不同的最小生成树&#xff0c;它们不同的那一部分边的权值实际上是…

vuex webpack 配置_vue+webpack切换环境和打包之后服务器配置

import axios from ‘axios‘import store from ‘../store/index‘const rootUrl process.env.API_ROOT//创建axios实例const service axios.create({timeout:30000 //超时时间})//添加request拦截器service.interceptors.request.use(config >{if (Object.keys(config.hea…

redis基本用法学习(C#调用FreeRedis操作redis)

FreeRedis属于常用的基于.net的redis客户端&#xff0c;EasyCaching中也提供适配FreeRedis的包。根据参考文献4中的说法&#xff0c;FreeRedis和CsRedis算是近亲&#xff08;都是GitHub中账号为2881099下的开源项目&#xff09;&#xff0c;因此其用法特别相似。FreeRedis的主要…

opencv:图像的基本变换

0.概述 图像变换的基本原理都是找到原图和目标图的像素位置的映射关系&#xff0c;这个可以用坐标系来思考&#xff0c;在opencv中&#xff0c; 图像的坐标系是从左上角开始(0,0)&#xff0c;向右是x增加方向(cols)&#xff0c;向下时y增加方向(rows)。 普通坐标关系&#xff1…

FFMpeg在Windows环境下的编译

1&#xff0e;安装MinGW &#xff08;1&#xff09;下载文件&#xff1a;MinGW-5.1.4.exe&#xff0c; &#xff08;2&#xff09;安装时选择下列组件&#xff1a; binutils-2.19.1-mingw32-bin.tar.gz gcc-core-3.4.5-20060117-3.tar.gz gcc-g-3.4.5-20060117-3.tar.gz …

中通知设置响铃_主动切断干扰源——手机“通知”精细化管理

上周去参加我福福幼儿园的母亲节活动&#xff0c;内容是孩子和家长一起穿手链。期间我发现和我同桌的一个家长的手机不停在响&#xff0c;当然伴随着注意力被打断。不仅是这位家长自己&#xff0c;连我也受到了干扰。于是职业病又犯了&#xff0c;我悄悄的看了一眼这位家长的手…

OCM_第十九天课程:Section9 —》Data Guard _ DATA GUARD 原理/DATA GUARD 应用/DATA GUARD 搭建...

注&#xff1a;本文为原著&#xff08;其内容来自 腾科教育培训课堂&#xff09;。阅读本文注意事项如下&#xff1a;1&#xff1a;所有文章的转载请标注本文出处。2&#xff1a;本文非本人不得用于商业用途。违者将承当相应法律责任。3&#xff1a;该系列文章目录列表&#xf…

python安装各种插件

http://www.lfd.uci.edu/~gohlke/pythonlibs/#pip 感受&#xff1a;如果编辑pip真的一直出问题&#xff0c;考虑降成32位的进行安装。毕竟合理搭配比木桶突出有用。转载于:https://www.cnblogs.com/osmondwang/p/7307678.html

编写数学公式的好工具

2019独角兽企业重金招聘Python工程师标准>>> http://private.codecogs.com/latex/eqneditor.php 转载于:https://my.oschina.net/yizhichao/blog/1542153

dev gridview 打印列数过多_R语言:如何将多张统计图绘制在一张上面

在使用R语言进行数据可视化的时候&#xff0c;常常需要将多张统计图表绘制在同一张图上面&#xff0c;从而更高效地传递信息&#xff0c;下面我们就来一起看看具体如何实现。一、使用R语言自带的函数绘制的图像R语言本身就已经内置了许多绘图函数&#xff0c;能够满足较为基本的…

264分析两大利器 和 视频系列下载:264VISA和Elecard StreamEye Tools

学了264有将近3个月有余&#xff0c;好多时候都在学习老毕的书和反复看JM86的代码&#xff0c;最近才找到264分析两大利器&#xff1a;264VISA和Elecard StreamEye Tools。不由得感叹&#xff0c;恨不逢同时。 简单的说下这两个软件&#xff1a; 264visa 强力的h264实时分析工具…

[转]vue全面介绍--全家桶、项目实例

慢慢了解vue及其全家桶的过程 原文http://blog.csdn.net/zhenghao35791/article/details/67639415 简介 “简单却不失优雅&#xff0c;小巧而不乏大匠”。 2016年最火的前端框架当属Vue.js了&#xff0c;很多使用过vue的程序员这样评价它&#xff0c;“vue.js兼具angular.js和R…

opencv 星空_opencv如何将大于5000像素点的轮廓绘制出来?

contourArea函数的运用。具体例子可以看下面的。《如何获得物体的主要方向&#xff1f;》代码略解&#xff1a;1、读入图片&#xff0c;寻找轮廓&#xff1b;//读入图像&#xff0c;转换为灰度Mat img imread("e:/sandbox/pca1.jpg");Mat bw;cvtColor(img, bw, COLO…