├── .gitignore ├── LICENSE ├── README.md ├── U#0001-loger └── log.h ├── U#0002-timer └── timer.h ├── U#0003-system_cls └── cls.h ├── U#0004-config_files ├── .bashrc ├── .gitconfig ├── .vimrc ├── build_cmd.md └── pre-commit ├── U#0005-color_picker └── main.cpp ├── U#0006-nms ├── nms.cpp └── softnms.png ├── U#0007-android_jni ├── Android_exe.mk ├── Android_lib.mk └── Application.mk ├── U#0008-git实用命令 └── README.md ├── U#0009-CMake实用模板 ├── CMakeLists.txt ├── include │ └── sdk.h ├── sample │ ├── CMakeLists.txt │ └── main.cpp ├── scripts │ ├── buildLinux.sh │ └── clean.sh └── src │ ├── CMakeLists.txt │ └── sdk.cpp ├── U#0010-scan_cvmat_efficiently ├── build.sh ├── main.cpp └── perf.log ├── U#0011-Anaconda使用经验 └── README.md ├── U#0012-Kaggle-api常用命令 └── README.md ├── U#0013-caffe_merge_bn_ssd └── merge_bn.py ├── U#0014-打印OpenCV版本和编译信息 ├── getOpenCVInfo.cpp └── getOpenCVInfo.py ├── U#0015-Docker使用经验 ├── README.md └── images │ └── commit-changes-to-docker-image.png ├── U#0016-JetsonNano使用经验 └── README.md ├── U#0017-PyTorch_tricks └── README.md ├── U#0018-常见模型参数量、计算量和速度统计 └── README.md ├── U#0019-C++11线程池 ├── build.sh ├── main.cpp ├── thread_pool.cpp └── thread_pool.h └── U#0020-把git_commit_sha1、OpenCV版本和当前编译时间编译到ELF中 ├── CMakeLists.txt └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | a.out 3 | build/ 4 | install/ 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Peng Du 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 我的军火库 2 | 3 | [**Don't Repeat Yourself**](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself),这里收集维护平时写程序时会用到的一些有用的小函数(和配置),这些函数: 4 | 5 | 1. 崇尚小而美的设计,使用方式简洁,尽量少地依赖 6 | 7 | 2. 以支持Linux平台(Ubuntu, CentOS)为主,也尽可能兼顾跨平台 8 | 9 | 欢迎各路朋友提Pull Request,改错别字都欢迎~ 10 | 11 | ## 目录 12 | 13 | [U#0001-loger](https://github.com/Captain1986/utils/blob/master/U%230001-loger/log.h) 14 | 15 | [U#0002-timer](https://github.com/Captain1986/utils/blob/master/U%230002-timer/timer.h) 16 | 17 | [U#0003-system_cls](https://github.com/Captain1986/utils/blob/master/U%230003-system_cls/cls.h) 18 | 19 | [U#0004-config_files](https://github.com/Captain1986/utils/blob/master/U%230004-config_files/) 20 | 21 | [U#0005-color_picker](https://github.com/Captain1986/utils/blob/master/U%230005-color_picker/main.cpp) 22 | 23 | [U#0006-nms](https://github.com/Captain1986/utils/blob/master/U%230006-nms/nms.cpp) 24 | 25 | [U#0007-android_jni](https://github.com/Captain1986/utils/blob/master/U%230007-android_jni/Application.mk) 26 | 27 | [U#0008-git实用命令](https://github.com/Captain1986/utils/blob/master/U%230008-git%E5%AE%9E%E7%94%A8%E5%91%BD%E4%BB%A4/README.md) 28 | 29 | [U#0009-CMake实用模板](https://github.com/Captain1986/utils/tree/master/U%230009-CMake%E5%AE%9E%E7%94%A8%E6%A8%A1%E6%9D%BF) 30 | 31 | [U#0010-scan_cvmat_efficiently](https://github.com/Captain1986/utils/blob/master/U%230010-scan_cvmat_efficiently/main.cpp) 32 | 33 | [U#0011-Anaconda使用经验](https://github.com/Captain1986/utils/blob/master/U%230011-Anaconda%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C/README.md) 34 | 35 | [U#0012-Kaggle-api常用命令](https://github.com/Captain1986/utils/blob/master/U%230012-Kaggle-api%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/README.md) 36 | 37 | [U#0013-caffe_merge_bn_ssd](https://github.com/Captain1986/utils/blob/master/U%230013-caffe_merge_bn_ssd/merge_bn.py) 38 | 39 | [U#0014-打印OpenCV版本和编译信息](https://github.com/Captain1986/utils/tree/master/U%230014-%E6%89%93%E5%8D%B0OpenCV%E7%89%88%E6%9C%AC%E5%92%8C%E7%BC%96%E8%AF%91%E4%BF%A1%E6%81%AF) 40 | 41 | [U#0015-Docker使用经验](https://github.com/Captain1986/utils/blob/master/U%230015-Docker%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C/README.md) 42 | 43 | [U#0016-JetsonNano使用经验](https://github.com/Captain1986/utils/blob/master/U%230016-JetsonNano%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C/README.md) 44 | 45 | [U#0017-PyTorch_tricks](https://github.com/Captain1986/utils/blob/master/U%230017-PyTorch_tricks/README.md) 46 | 47 | [U#0018-常见模型参数量、计算量和速度统计](https://github.com/Captain1986/utils/blob/master/U%230018-%E5%B8%B8%E8%A7%81%E6%A8%A1%E5%9E%8B%E5%8F%82%E6%95%B0%E9%87%8F%E3%80%81%E8%AE%A1%E7%AE%97%E9%87%8F%E5%92%8C%E9%80%9F%E5%BA%A6%E7%BB%9F%E8%AE%A1/README.md) 48 | 49 | [U#0019-C++11线程池](https://github.com/Captain1986/utils/tree/master/U%230019-C%2B%2B11%E7%BA%BF%E7%A8%8B%E6%B1%A0) 50 | 51 | [U#0020-把git_commit_sha1、OpenCV版本和当前编译时间编译到ELF中](https://github.com/Captain1986/utils/blob/master/U%230020-%E6%8A%8Agit_commit_sha1%E3%80%81OpenCV%E7%89%88%E6%9C%AC%E5%92%8C%E5%BD%93%E5%89%8D%E7%BC%96%E8%AF%91%E6%97%B6%E9%97%B4%E7%BC%96%E8%AF%91%E5%88%B0ELF%E4%B8%AD/main.cpp) 52 | 53 | -------------------------------------------------------------------------------- /U#0001-loger/log.h: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * 一个轻量级log工具,打印log到控制台,可使用在Android, Linux上 3 | * 需要在Makefile中打开_DEBUG_宏 4 | * 默认打印在Linux中,如果是Android系统,请打开__ANDROID__宏 5 | * ************************************************************/ 6 | 7 | #ifndef __LOG_H__ 8 | #define __LOG_H__ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifdef _DEBUG_ 15 | #undef LOG_TAG 16 | #define LOG_TAG "Captain" 17 | #ifdef __ANDROID__ 18 | //#include 19 | #include 20 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); 21 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); 22 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); 23 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__); 24 | #else /* !_ANDROID_ */ 25 | #include 26 | #define LOGI(...) \ 27 | do { \ 28 | printf("%s-%s(%d line) ", LOG_TAG, __FILE__, __LINE__); printf(__VA_ARGS__); printf("\n"); \ 29 | } while (0) 30 | 31 | #define LOGW(...) \ 32 | do { \ 33 | printf("%s-%s(%d line) ", LOG_TAG, __FILE__, __LINE__); printf(__VA_ARGS__); printf("\n"); \ 34 | } while (0) 35 | 36 | #define LOGE(...) \ 37 | do { \ 38 | printf("%s-%s(%d line) ", LOG_TAG, __FILE__, __LINE__); printf(__VA_ARGS__); printf("\n"); \ 39 | } while (0) 40 | 41 | #define LOGD(...) \ 42 | do { \ 43 | printf("%s-%s(%d line) ", LOG_TAG, __FILE__, __LINE__); printf(__VA_ARGS__); printf("\n"); \ 44 | } while (0) 45 | #endif /* !_ANDROID_ */ 46 | #else /* !_DEBUG */ 47 | #define LOGI(...) 48 | #define LOGW(...) 49 | #define LOGE(...) 50 | #define LOGD(...) 51 | #endif 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif /* __LOG_H__ */ 58 | 59 | /* EOF */ 60 | 61 | -------------------------------------------------------------------------------- /U#0002-timer/timer.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * C++11 chrono库封装的一个高精度计时器类(使用真实世界挂钟时间,具体时间依赖于系统) 3 | * 使用方式: 4 | * Timer t; // 开始计时 5 | * func(); // 运行待计时的函数 6 | * std::cout << t.elapsed() << std::endl; // 打印计时时间,默认毫秒为单位 7 | * std::cout << t.elapsed_micro() << std::endl; // 微秒 8 | * std::cout << t.elapsed_nano() << std::endl; // 纳秒 9 | *********************************************************/ 10 | 11 | #ifndef _TIMER_ 12 | #define _TIMER_ 13 | 14 | /******************************************************** 15 | // 在Linux上不要C++11支持的gettimeofday() 16 | #include 17 | 18 | struct timeval start, end; 19 | gettimeofday(&start, NULL); 20 | long long tag = (long long)start.tv_sec*1e6 + start.tv_usec; 21 | 22 | func(...); 23 | 24 | gettimeofday(&end, NULL); 25 | unsigned int diff = 1e6 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; 26 | printf("func, [time_tag[%lld]] elapsed is %fms\n", tag % int(1e8), diff/1000.0f); 27 | ********************************************************/ 28 | 29 | #include 30 | using namespace std; 31 | using namespace std::chrono; 32 | 33 | class Timer { 34 | public: 35 | Timer() : m_begin(high_resolution_clock::now()) {} 36 | void reset() { m_begin = high_resolution_clock::now(); } 37 | 38 | // 默认输出毫秒 39 | template 40 | int64_t elapsed() const { 41 | return duration_cast(high_resolution_clock::now() - m_begin).count(); 42 | } 43 | 44 | // 微秒 45 | int64_t elapsed_micro() const { 46 | return elapsed(); 47 | } 48 | 49 | // 纳秒 50 | int64_t elapsed_nano() const { 51 | return elapsed(); 52 | } 53 | 54 | // 秒 55 | int64_t elapsed_seconds() const { 56 | return elapsed(); 57 | } 58 | 59 | // 分 60 | int64_t elapsed_minutes() const { 61 | return elapsed(); 62 | } 63 | 64 | // 时 65 | int64_t elapsed_hours() const { 66 | return elapsed(); 67 | } 68 | 69 | private: 70 | time_point m_begin; 71 | }; 72 | 73 | #endif // !_TIMER_ 74 | 75 | -------------------------------------------------------------------------------- /U#0003-system_cls/cls.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * 参考:https://blog.csdn.net/n5/article/details/70143942 3 | * windows32/64平台_WIN32都会被定义,而_WIN64只在64位windows上定义,因此要先判断_WIN64 4 | * 所有的apple系统都会定义 __APPLE__,包括MacOSX和iOS 5 | * TARGET_IPHONE_SIMULATOR 是 TARGET_OS_IPHONE 的子集, 6 | * TARGET_OS_IPHONE 是 TARGET_OS_MAC的子集。也就是说iOS模拟器上会同时定义这三个宏。因此判断的时候要先判断子集。 7 | * 另外mac上可以用以下命令行获取GCC定义的预编译宏: 8 | * gcc -arch i386 -dM -E - < /dev/null | sort (i386可替换为arm64等) 9 | *********************************************************/ 10 | 11 | #ifdef _WIN32 12 | //define something for Windows (32-bit and 64-bit, this part is common) 13 | #ifdef _WIN64 14 | //define something for Windows (64-bit only) 15 | #else 16 | //define something for Windows (32-bit only) 17 | #endif 18 | #elif __APPLE__ 19 | #include "TargetConditionals.h" 20 | #if TARGET_IPHONE_SIMULATOR 21 | // iOS Simulator 22 | #elif TARGET_OS_IPHONE 23 | // iOS device 24 | #elif TARGET_OS_MAC 25 | // Other kinds of Mac OS 26 | #else 27 | # error "Unknown Apple platform" 28 | #endif 29 | #elif __ANDROID__ 30 | // android 31 | #elif __linux__ 32 | // linux 33 | #elif __unix__ // all unices not caught above 34 | // Unix 35 | #elif defined(_POSIX_VERSION) 36 | // POSIX 37 | #else 38 | # error "Unknown compiler" 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /U#0004-config_files/.bashrc: -------------------------------------------------------------------------------- 1 | # ~/.bashrc: executed by bash(1) for non-login shells. 2 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 3 | # for examples 4 | 5 | # If not running interactively, don't do anything 6 | case $- in 7 | *i*) ;; 8 | *) return;; 9 | esac 10 | 11 | # don't put duplicate lines or lines starting with space in the history. 12 | # See bash(1) for more options 13 | HISTCONTROL=ignoreboth 14 | 15 | # append to the history file, don't overwrite it 16 | shopt -s histappend 17 | 18 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 19 | HISTSIZE=1000 20 | HISTFILESIZE=2000 21 | 22 | # check the window size after each command and, if necessary, 23 | # update the values of LINES and COLUMNS. 24 | shopt -s checkwinsize 25 | 26 | # If set, the pattern "**" used in a pathname expansion context will 27 | # match all files and zero or more directories and subdirectories. 28 | #shopt -s globstar 29 | 30 | # make less more friendly for non-text input files, see lesspipe(1) 31 | [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 32 | 33 | # set variable identifying the chroot you work in (used in the prompt below) 34 | if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then 35 | debian_chroot=$(cat /etc/debian_chroot) 36 | fi 37 | 38 | # set a fancy prompt (non-color, unless we know we "want" color) 39 | case "$TERM" in 40 | xterm-color|*-256color) color_prompt=yes;; 41 | esac 42 | 43 | # uncomment for a colored prompt, if the terminal has the capability; turned 44 | # off by default to not distract the user: the focus in a terminal window 45 | # should be on the output of commands, not on the prompt 46 | #force_color_prompt=yes 47 | 48 | if [ -n "$force_color_prompt" ]; then 49 | if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then 50 | # We have color support; assume it's compliant with Ecma-48 51 | # (ISO/IEC-6429). (Lack of such support is extremely rare, and such 52 | # a case would tend to support setf rather than setaf.) 53 | color_prompt=yes 54 | else 55 | color_prompt= 56 | fi 57 | fi 58 | 59 | if [ "$color_prompt" = yes ]; then 60 | PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 61 | else 62 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 63 | fi 64 | unset color_prompt force_color_prompt 65 | 66 | # If this is an xterm set the title to user@host:dir 67 | case "$TERM" in 68 | xterm*|rxvt*) 69 | PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" 70 | ;; 71 | *) 72 | ;; 73 | esac 74 | 75 | # enable color support of ls and also add handy aliases 76 | if [ -x /usr/bin/dircolors ]; then 77 | test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" 78 | alias ls='ls --color=auto' 79 | #alias dir='dir --color=auto' 80 | #alias vdir='vdir --color=auto' 81 | 82 | alias grep='grep --color=auto' 83 | alias fgrep='fgrep --color=auto' 84 | alias egrep='egrep --color=auto' 85 | fi 86 | 87 | # colored GCC warnings and errors 88 | #export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' 89 | 90 | # some more ls aliases 91 | alias ll='ls -alF' 92 | alias la='ls -A' 93 | alias l='ls -CF' 94 | 95 | # Add an "alert" alias for long running commands. Use like so: 96 | # sleep 10; alert 97 | alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' 98 | 99 | # Alias definitions. 100 | # You may want to put all your additions into a separate file like 101 | # ~/.bash_aliases, instead of adding them here directly. 102 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 103 | 104 | if [ -f ~/.bash_aliases ]; then 105 | . ~/.bash_aliases 106 | fi 107 | 108 | # enable programmable completion features (you don't need to enable 109 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 110 | # sources /etc/bash.bashrc). 111 | if ! shopt -oq posix; then 112 | if [ -f /usr/share/bash-completion/bash_completion ]; then 113 | . /usr/share/bash-completion/bash_completion 114 | elif [ -f /etc/bash_completion ]; then 115 | . /etc/bash_completion 116 | fi 117 | fi 118 | 119 | # virtualenv and virtualenvwrapper 120 | export WORKON_HOME=/home/dup/.virtualenvs 121 | source /usr/local/bin/virtualenvwrapper.sh 122 | 123 | export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH 124 | export LD_LIBRARY_PATH=/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH 125 | 126 | export PATH=/usr/local/cuda-9.0/bin:$PATH 127 | export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATH 128 | 129 | #export PATH=/usr/local/cuda-9.1/bin:$PATH 130 | #export LD_LIBRARY_PATH=/usr/local/cuda-9.1/lib64:$LD_LIBRARY_PATH 131 | 132 | export PATH=/home/dup/Downloads/colorpicker:$PATH 133 | 134 | export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 135 | 136 | export LD_LIBRARY_PATH=~/caffe/.build_release/lib/:$LD_LIBRARY_PATH 137 | -------------------------------------------------------------------------------- /U#0004-config_files/.gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = dupeng 3 | email = dupeng63@163.com 4 | 5 | [alias] 6 | df = diff 7 | st = status -s 8 | co = checkout 9 | ci = commit 10 | br = branch 11 | unstage = reset HEAD 12 | last = log -1 13 | l = log --oneline --decorate -12 --color 14 | ll = log --oneline --decorate --color 15 | lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset ' --abbrev-commit 16 | lc = log --graph --color 17 | ps = push 18 | pl = pull 19 | rb = rebase 20 | dci = dcommit 21 | sbi = submodule init 22 | sbu = submodule update 23 | sbp = submodule foreach git pull 24 | sbc = submodule foreach git co master 25 | 26 | [credential] 27 | helper = store 28 | 29 | [push] 30 | default = simple 31 | 32 | [core] 33 | editor = vim 34 | [color] 35 | ui = true 36 | -------------------------------------------------------------------------------- /U#0004-config_files/.vimrc: -------------------------------------------------------------------------------- 1 | set nu " 显示行号 2 | syntax on " 语法高亮 3 | set nobackup "覆盖文件时不备份 4 | set autoindent "自动缩进 5 | "set noautoindent 6 | set ruler " 显示标尺 7 | set cursorline " 突出显示当前行 8 | set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")} 9 | set laststatus=2 " 启动显示状态行(1),总是显示状态行(2) 10 | set nocompatible "去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限 11 | set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936 12 | set termencoding=utf-8 13 | set encoding=utf-8 14 | set fileencodings=ucs-bom,utf-8,cp936 15 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | ""实用设置 17 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 18 | "自动保存 19 | set autowrite 20 | set magic " 设置魔术 21 | ""set guioptions-=T " 隐藏工具栏 22 | ""set guioptions-=m " 隐藏菜单栏 23 | ""set statusline=\ %<%F[%1*%M%*%n%R%H]%=\ %y\ %0(%{&fileformat}\ %{&encoding}\ %c:%l/%L%)\ 24 | " 设置在状态行显示的信息 25 | set foldcolumn=0 26 | set foldmethod=indent 27 | set foldlevel=10000 28 | set foldenable " 开始折叠 29 | " 不要使用vi的键盘模式,而是vim自己的 30 | set nocompatible 31 | " 语法高亮 32 | set syntax=on 33 | " 在处理未保存或只读文件的时候,弹出确认 34 | set confirm 35 | " Tab键的宽度 36 | set tabstop=4 37 | " 统一缩进为4 38 | set softtabstop=4 39 | set shiftwidth=4 40 | " 历史记录数 41 | set history=1000 42 | "搜索忽略大小写 43 | set ignorecase 44 | "搜索逐字符高亮 45 | set hlsearch 46 | set incsearch 47 | "行内替换 48 | set gdefault 49 | "编码设置 50 | set enc=utf-8 51 | set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936 52 | "语言设置 53 | set langmenu=zh_CN.UTF-8 54 | set helplang=cn 55 | " 我的状态行显示的内容(包括文件类型和解码) 56 | "set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")} 57 | "set statusline=[%F]%y%r%m%*%=[Line:%l/%L,Column:%c][%p%%] 58 | " 总是显示状态行 59 | ""set laststatus=2 60 | " 命令行(在状态行下)的高度,默认为1,这里是2 61 | set cmdheight=1 62 | " 侦测文件类型 63 | filetype on 64 | " 载入文件类型插件 65 | filetype plugin on 66 | " 为特定文件类型载入相关缩进文件 67 | filetype indent on 68 | " 保存全局变量 69 | set viminfo+=! 70 | " 带有如下符号的单词不要被换行分割 71 | set iskeyword+=_,$,@,%,#,- 72 | " 字符间插入的像素行数目 73 | set linespace=0 74 | " 增强模式中的命令行自动完成操作 75 | set wildmenu 76 | " 使回格键(backspace)正常处理indent, eol, start等 77 | set backspace=2 78 | " 允许backspace和光标键跨越行边界 79 | set whichwrap+=<,>,h,l 80 | " 通过使用: commands命令,告诉我们文件的哪一行被改变过 81 | set report=0 82 | " 在被分割的窗口间显示空白,便于阅读 83 | set fillchars=vert:\ ,stl:\ ,stlnc:\ 84 | " 高亮显示匹配的括号 85 | set showmatch 86 | " 匹配括号高亮的时间(单位是十分之一秒) 87 | set matchtime=1 88 | " 光标移动到buffer的顶部和底部时保持3行距离 89 | set scrolloff=3 90 | " 高亮显示普通txt文件(需要txt.vim脚本) 91 | au BufRead,BufNewFile * setfiletype txt 92 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 93 | "其他东东 94 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 95 | "Tony" 96 | hi def LogF_color ctermfg=white guifg=white ctermbg=red guibg=red 97 | hi def LogE_color ctermfg=darkred guifg=darkred 98 | hi def LogW_color ctermfg=brown guifg=brown 99 | hi def LogI_color ctermfg=blue guifg=blue 100 | hi def LogD_color ctermfg=green guifg=green 101 | hi def LogV_color ctermfg=gray guifg=gray 102 | syn match LogF '\(^F[ ]\+\|^F\/\|^[0-9:\.\- ]*[ ]\+F[ ]\+\|^[0-9:\.\- ]*[ ]\+F\/\).*' 103 | syn match LogE '\(^E[ ]\+\|^E\/\|^[0-9:\.\- ]*[ ]\+E[ ]\+\|^[0-9:\.\- ]*[ ]\+E\/\).*' 104 | syn match LogW '\(^W[ ]\+\|^W\/\|^[0-9:\.\- ]*[ ]\+W[ ]\+\|^[0-9:\.\- ]*[ ]\+W\/\).*' 105 | syn match LogI '\(^I[ ]\+\|^I\/\|^[0-9:\.\- ]*[ ]\+I[ ]\+\|^[0-9:\.\- ]*[ ]\+I\/\).*' 106 | syn match LogD '\(^D[ ]\+\|^D\/\|^[0-9:\.\- ]*[ ]\+D[ ]\+\|^[0-9:\.\- ]*[ ]\+D\/\).*' 107 | syn match LogV '\(^V[ ]\+\|^V\/\|^[0-9:\.\- ]*[ ]\+V[ ]\+\|^[0-9:\.\- ]*[ ]\+V\/\).*' 108 | hi def link LogF LogF_color 109 | hi def link LogE LogE_color 110 | hi def link LogW LogW_color 111 | hi def link LogI LogI_color 112 | hi def link LogD LogD_color 113 | hi def link LogV LogV_color 114 | "End of Tony" 115 | ""set statusline=[%F]%y%r%m%*%=[Line:%l/%L,Column:%c][%p%%] 116 | -------------------------------------------------------------------------------- /U#0004-config_files/build_cmd.md: -------------------------------------------------------------------------------- 1 | ### OpenCV: Open Source Computer Vision Library 2 | 3 | CPU version: 4 | cmake -D BUILD_opencv_gpu=OFF -D WITH_EIGEN=ON -D WITH_TBB=ON -D WITH_CUDA=OFF -D WITH_1394=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. 5 | 6 | GPU version: 7 | ... 8 | -------------------------------------------------------------------------------- /U#0004-config_files/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Usage: add this file to your project's .git/hooks directory. Rename it to 4 | # just 'pre-commit'. 5 | # Now, when you change some files in repository and try to commit these 6 | # changes, git will run this script right before commit. Cppcheck will scan 7 | # changed/new files in repository. If it finds some issues, script returns with 8 | # exit code 1, rejecting commit. Otherwise, script returns 0, and you can 9 | # actually commit your changes. 10 | # use `git commit --no-verify` to DISABLE this hook 11 | # 12 | # Example: 13 | # $ cat hello.c 14 | # int main() { 15 | # int *s = malloc(10); 16 | # } 17 | # $ git add hello.c 18 | # $ git commit 19 | # Checking hello.c... 20 | # [hello.c:3]: (error) Memory leak: s 21 | # [hello.c:2]: (error) The allocated size 10 is not a multiple of the underlying type's size. 22 | # 23 | # $ vim hello.c 24 | # $ cat hello.c 25 | # int main() { 26 | # } 27 | # $ git add hello.c 28 | # $ git commit 29 | # Checking hello.c... 30 | # $ 31 | 32 | if git rev-parse --verify HEAD >/dev/null 2>&1 33 | then 34 | against=HEAD 35 | else 36 | # Initial commit: diff against an empty tree object 37 | against=5c935dc642cb6eb9a060e54bf8d69288fbee5a15 38 | fi 39 | 40 | #echo $against 41 | 42 | # We should pass only added or modified C/C++ source files to cppcheck. 43 | # changed_files=$(git diff-index --cached $against | \ 44 | # grep -E '[MA] .*\.(c|cpp|cc|cxx)$' | cut -d' ' -f 2) 45 | changed_files=$(git diff-index --cached $against | grep -E '[MA].*\.(c|cpp|cc|cxx|h|hpp)$' | cut -d' ' -f 5 | cut -f 2) 46 | 47 | #echo $changed_files 48 | 49 | if [ -n "$changed_files" ]; then 50 | cppcheck --error-exitcode=1 $changed_files 51 | exit $? 52 | fi 53 | -------------------------------------------------------------------------------- /U#0005-color_picker/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace cv; 7 | using namespace std; 8 | 9 | Mat img; 10 | 11 | //ofstream outfile("color.txt"); 12 | 13 | void on_mouse(int event, int x, int y, int flags, void* param) 14 | { 15 | switch(event) 16 | { 17 | case CV_EVENT_LBUTTONDOWN: 18 | { 19 | IplImage temp = (IplImage)img; 20 | Scalar color = cvGet2D(&temp, y, x); 21 | printf("Point(%d,%d)--> B[%d], G[%d], R[%d]\n", x, y, (int)color.val[0], (int)color.val[1], (int)color.val[2]); 22 | //outfile<<"cv::"<<"Point2f"<<"("< 2 | #include 3 | #include 4 | 5 | // 坐标系和OpenCV保持一致,左上角为原点,X轴从左到右,Y轴从上到下 6 | float 7 | iou(const std::vector& boxA, const std::vector& boxB) 8 | { 9 | const float x11 = boxA[0];// 第一个box左上角点的X坐标 10 | const float y11 = boxA[1];// 第一个box左上角点的Y坐标 11 | const float x12 = boxA[2];// 第一个box右下角点的X坐标 12 | const float y12 = boxA[3];// 第一个box右下角点的Y坐标 13 | const float Aarea = (y12 - y11 + 1) * (x12 - x11 + 1); 14 | 15 | const float x21 = boxB[0]; 16 | const float y21 = boxB[1]; 17 | const float x22 = boxB[2]; 18 | const float y22 = boxB[3]; 19 | const float Barea = (y22 - y21 + 1) * (x22 - x21 + 1); 20 | 21 | const float interX1 = std::max(x11, x21); 22 | const float interY1 = std::max(y11, y21); 23 | const float interX2 = std::min(x12, x22); 24 | const float interY2 = std::min(y12, y22); 25 | 26 | const float interArea = std::max(0.0f, interY2 - interY1 + 1) * std::max(0.0f, interX2 - interX1 + 1); 27 | 28 | return interArea / (Aarea + Barea - interArea); 29 | } 30 | 31 | /* 32 | * 非极大值抑制NMS(non-maximum suppression)是目标检测中常见的去重方案 33 | * 这里是一种C++实现,需要支持C++11的编译器编译 34 | * 35 | * boxes,输入,原始框信息组成的向量,其中每个元素都是一个原始框的信息, 36 | * 这些信息依次以x_topleft,y_topleft,x_bottomright,ybuttomright,confidence为顺序 37 | * threshold,输入,置信度阈值,仅保留置信度大于它的原始框 38 | * type, 输入,nms类型(暂时只有normal),normal表示用常见的nms,soft表示用soft nms,默认normal 39 | * 输出:nms算法的返回值,是一个向量,向量中的每一个元素表示保留下来的原始框在输入boxes中的下标 40 | * 如果输入boxes空,则返回为空 41 | * 42 | * 参考资料:https://zhuanlan.zhihu.com/p/49481833, https://zhuanlan.zhihu.com/p/50126479,https://zhuanlan.zhihu.com/p/42018282 43 | * */ 44 | 45 | std::vector 46 | nms(const std::vector>& boxes, const float threshold/*, const std::string type*/) 47 | { 48 | if (boxes.empty()) { 49 | return std::vector(); 50 | } 51 | 52 | std::vector list_k(boxes.size()); 53 | int n = 0; 54 | std::generate(std::begin(list_k), std::end(list_k), [&] { return n++; }); 55 | // 以分数由低到高排列 56 | std::sort(list_k.begin(), list_k.end(), 57 | [&](int i1, int i2) { return boxes[i1][4] < boxes[i2][4]; }); 58 | 59 | std::vector keep; 60 | while (!list_k.empty()) { 61 | // 保留本轮最高分的index 62 | const int top_1 = list_k.back(); 63 | keep.push_back(top_1); 64 | 65 | // 删除最高分的index 66 | list_k.pop_back(); 67 | 68 | for(auto it = list_k.begin(); it != list_k.end(); NULL/*在循环内自增*/) { 69 | if(iou(boxes[*it], boxes[top_1]) > threshold) { 70 | it = list_k.erase(it); 71 | } else { 72 | ++it; 73 | } 74 | } 75 | } 76 | 77 | return keep; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /U#0006-nms/softnms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Captain1986/utils/1df307ac16dbe2fc33788a92033dddd7c5c3393a/U#0006-nms/softnms.png -------------------------------------------------------------------------------- /U#0007-android_jni/Android_exe.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_ARM_MODE := arm 6 | 7 | LOCAL_SRC_FILES:= \ 8 | ../sample/main.cpp 9 | 10 | LOCAL_C_INCLUDES += \ 11 | $(LOCAL_PATH)/../3rdparty/opencv/include \ 12 | $(LOCAL_PATH)/../include 13 | 14 | LOCAL_LDLIBS += -llog \ 15 | -lopencv_highgui -lopencv_video -lopencv_imgcodecs -lopencv_calib3d -lopencv_imgproc -lopencv_core \ 16 | -llibwebp -llibtiff -llibpng -lz -llibjpeg-turbo -llibjasper -lIlmImf \ 17 | -ltegra_hal -lcpufeatures -llibprotobuf -ltbb \ 18 | -lFoo 19 | 20 | LOCAL_LDFLAGS += \ 21 | -L$(LOCAL_PATH)/../3rdparty/opencv/armeabi-v7a \ 22 | -L$(LOCAL_PATH)/../3rdparty/opencv/3rdparty/libs/armeabi-v7a \ 23 | -L$(LOCAL_PATH)/.. 24 | 25 | LOCAL_CFLAGS := -Werror 26 | 27 | #LOCAL_SHARED_LIBRARIES += libFoo 28 | 29 | LOCAL_MODULE_TAGS := optional 30 | 31 | LOCAL_MODULE:= EXENAME 32 | 33 | include $(BUILD_EXECUTABLE) 34 | 35 | -------------------------------------------------------------------------------- /U#0007-android_jni/Android_lib.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | TARGET_ARCH := arm 3 | TARGET_PLATFORM := android-21 4 | include $(CLEAR_VARS) 5 | 6 | LOCAL_CFLAGS += -D__linux__ -D__embedded__ -D__android__ -W -Wall 7 | LOCAL_CFLAGS += -O3 -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math 8 | 9 | LOCAL_CPPFLAGS := -O2 -fvisibility-inlines-hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math 10 | 11 | LOCAL_LDFLAGS += -Wl,--gc-sections 12 | 13 | LOCAL_CFLAGS += -fopenmp 14 | LOCAL_CPPFLAGS += -fopenmp 15 | LOCAL_LDFLAGS += -fopenmp 16 | 17 | LOCAL_SRC_FILES := ../src/foo.cpp \ 18 | ../src/bar.cpp 19 | 20 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include \ 21 | $(LOCAL_PATH)/../3rdparty/opencv/include 22 | 23 | LOCAL_LDLIBS += -llog \ 24 | -lopencv_highgui -lopencv_video -lopencv_imgcodecs -lopencv_calib3d -lopencv_imgproc -lopencv_core \ 25 | -ltegra_hal -lcpufeatures -llibprotobuf -ltbb 26 | 27 | LOCAL_LDFLAGS += -L$(SYSROOT)/usr/lib \ 28 | -L$(LOCAL_PATH)/../3rdparty/opencv/armeabi-v7a \ 29 | -L$(LOCAL_PATH)/../3rdparty/opencv/3rdparty/libs/armeabi-v7a 30 | 31 | LOCAL_LDFLAGS += -ljnigraphics -lz 32 | 33 | LOCAL_MODULE := libFoo 34 | 35 | include $(BUILD_SHARED_LIBRARY) 36 | 37 | -------------------------------------------------------------------------------- /U#0007-android_jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_MODULES = EXENAME 2 | 3 | #APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64 4 | 5 | APP_ABI := armeabi-v7a 6 | 7 | APP_PLATFORM := android-21 8 | 9 | #APP_STL := stlport_shared 10 | 11 | APP_STL := c++_shared 12 | 13 | #APP_STL := gnustl_static 14 | 15 | ifeq ($(NDK_DEBUG), 1) 16 | APP_OPTIM = debug 17 | APP_CFLAGS = -g -O0 18 | else 19 | APP_OPTIM = release 20 | APP_CFLAGS = -O3 21 | endif 22 | 23 | APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -std=c++11 24 | 25 | APP_CPPFLAGS += -fexceptions 26 | -------------------------------------------------------------------------------- /U#0008-git实用命令/README.md: -------------------------------------------------------------------------------- 1 | #       git实用命令 2 | 3 | 1. 将工作区和缓冲区的内容**全部清除**,并退到最近的commit内容 4 | 5 | ​ `git reset --hard HEAD^` 6 | 7 | 2. **提交错误** 8 | 9 | + 不小心错误提交一个commit A到GitHub,但是你想提交的是commit B: 10 | 11 | 首先`git reset --hard HEAD^`,本地退回到上一个版本 12 | 13 | 然后修改好commit B,本地提交后,`git push --force`,就可以把GitHub上的commit A删掉,变成commit B。 14 | 15 | 注意:`git push --force`可能需要相应分支的权限,有一定风险性,注意备份. 16 | 17 | + 本地提交了,还没有push到GitHub,需要修改log 18 | 19 | 直接`git commit --amend`,会跳出写log的界面,直接修改即可 20 | 21 | + 本地提交了,也push到GitHub了,需要修改上次提交(例如追加一个漏掉的文件) 22 | 23 | `git commit -m 'initial commit'` 24 | 25 | `git add forgotten_file` 26 | 27 | `git commit --amend` 28 | 29 | `git push --force` 30 | 31 | 3. 你正在某个开发分支工作,但是master分支需要紧急做一个hotfix,可以用git stash**保存当前工作进度**,去master上做完了再切回来继续你的工作 32 | 33 | ​ `git stash` 34 | 35 | ​ `git checkout master` 36 | 37 | ​ *working on master branch* 38 | 39 | ​ `git checkout dev` 40 | 41 | ​ `git stash pop` 42 | 43 | 4. 删除远程分支 44 | 45 | ​ `git push origin --delete [branchname]` 46 | 47 | 注意:在删除远程分支时,同名的本地分支并不会被删除,所以还需要单独删除本地同名分支 48 | 49 | 如果发生以下错误: 50 | 51 | error: unable to delete ‘origin/xxxxxxxx-fixbug’: remote ref does not exist 52 | 53 | error: failed to push some refs to ‘git@github.com:xxxxxxxx/xxxxxxxxxx.git’ 54 | 55 | 解决办法:git checkout xxxxx-fixbug切换到当前分支上,然后再进行git push –-delete origin origin/xxxxx-fixbug,此时将不会再发生错误 。 56 | 57 | 5. 打tag 58 | 59 | `git tag -a v191027 -m "19年10月27号版本" [7b5bccf]` 60 | 61 | `git push --tags` 62 | 63 | 6. 查看某个文件的修改历史 64 | 65 | git blame file和git log --follow file 66 | 67 | 7. 68 | 69 | ## 参考文献 70 | 71 | [Git菜单](https://geeeeeeeeek.github.io/git-recipes/) 72 | 73 | [gitmoji](https://gitmoji.carloscuesta.me/) 74 | 75 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(ADD) 3 | 4 | set(CMAKE_BUILD_TYPE Release) 5 | 6 | # 指定安装路径 7 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 8 | set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/install" CACHE PATH "Installation Directory") 9 | endif() 10 | 11 | message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") 12 | 13 | if(${CMAKE_MAJOR_VERSION} GREATER 2) 14 | CMAKE_POLICY(SET CMP0026 OLD) 15 | endif() 16 | 17 | # VERBOSE开关 18 | set(CMAKE_VERBOSE_MAKEFILE ON) 19 | # 打印平台信息 20 | message(STATUS "Operation System: " ${CMAKE_SYSTEM}) 21 | 22 | # 设置编译选项 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fvisibility=hidden -fPIC -O3") 24 | # 设置链接选项 25 | set(CMAKE_LDFLAGS "${CMAKE_LDFLAGS} -Wl,--gc-sections") 26 | 27 | #add cuda 28 | #set(CUDA_DIR /usr/local/cuda-9.0) 29 | #find_package(CUDA REQUIRED) 30 | #include_directories(${CUDA_DIR}/include) 31 | #link_directories(${CUDA_DIR}/lib64) 32 | 33 | #add opencv 34 | #set(OpenCV_DIR /home/dup/Downloads/opencv-3.4.1/build/install/share/OpenCV) 35 | #find_package(OpenCV REQUIRED) 36 | #include_directories(${OpenCV_INCLUDE_DIRS}) 37 | #link_directories(${OpenCV_LIBRARIES_DIRS}) 38 | #message(STATUS "OpenCV libraries: " ${OpenCV_LIBS}) 39 | 40 | #set rpath 41 | #set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true) 42 | #set(CMAKE_INSTALL_RPATH ./lib ./lib/tensorRT ./build) 43 | #set(CMAKE_BUILD_WITH_INSTALL_RPATH true) 44 | 45 | add_subdirectory(src/) 46 | add_subdirectory(sample/) 47 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/include/sdk.h: -------------------------------------------------------------------------------- 1 | //sdk.h 2 | #ifndef _SDK_ 3 | #define _SDK_ 4 | 5 | #include 6 | #include 7 | 8 | // sdk实现两个整数a和b相加,返回他们的和 9 | 10 | int sdk_add(const int a, const int b); 11 | 12 | #endif // !_SDK_ 13 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/sample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/include) 2 | 3 | set(APP_SRC main.cpp) 4 | add_executable(main ${APP_SRC}) 5 | target_link_libraries(main ${OpenCV_LIBS} sdk) 6 | 7 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 8 | 9 | install(TARGETS main RUNTIME DESTINATION bin) 10 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/sample/main.cpp: -------------------------------------------------------------------------------- 1 | //main.cpp 2 | #include 3 | #include 4 | #include 5 | #include "sdk.h" // 导入int sdk_add(const int a, const int b)函数的声明 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | 10 | int a = 1; 11 | int b = 2; 12 | int sum = sdk_add(a, b); 13 | 14 | printf("sum[%d].\n", sum); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/scripts/buildLinux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf build/ insall/ lib/ 4 | 5 | mkdir build/ 6 | cd build/ 7 | cmake .. 8 | make -j8 9 | make install 10 | cd .. 11 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/scripts/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf build/ insall/ lib/ 4 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/include) 2 | 3 | #设置nvcc编译相关选项 4 | #set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11") 5 | #set(GENCODE -gencode arch=compute_61,code=sm_61) 6 | #list(APPEND CUDA_NVCC_FLAGS ${GENCODE}) 7 | 8 | #file(GLOB_RECURSE CU_SRCS src/*.cu) 9 | #message(STATUS ${CU_SRCS}) 10 | #CUDA_COMPILE(CU_OBJS ${CU_SRCS}) 11 | 12 | #set(SRC_FILES sdk.cpp) 13 | aux_source_directory(./ SRC_FILES) 14 | #file(GLOB_RECURSE SRC_FILES "*.cpp") 15 | add_library(sdk SHARED ${SRC_FILES} ${CU_OBJS}) 16 | #set_target_properties(sdk PROPERTIES OUTPUT_NAME "sdk") 17 | 18 | set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 19 | 20 | install(TARGETS sdk LIBRARY DESTINATION lib) 21 | install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../include/sdk.h DESTINATION include) 22 | -------------------------------------------------------------------------------- /U#0009-CMake实用模板/src/sdk.cpp: -------------------------------------------------------------------------------- 1 | //sdk.cpp 2 | #include "sdk.h" 3 | 4 | int sdk_add(const int a, const int b) 5 | { 6 | int sum = 0; 7 | 8 | sum = a + b; 9 | 10 | return sum; 11 | } 12 | -------------------------------------------------------------------------------- /U#0010-scan_cvmat_efficiently/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | g++ main.cpp `pkg-config --libs --cflags opencv` -O0 -std=c++11 3 | -------------------------------------------------------------------------------- /U#0010-scan_cvmat_efficiently/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "opencv2/core/core.hpp" 5 | 6 | using namespace std; 7 | 8 | void method1(cv::Mat); 9 | void method2(cv::Mat); 10 | void method3(cv::Mat); 11 | void method4(cv::Mat); 12 | void method5(cv::Mat); 13 | void method5_2(cv::Mat); 14 | void method5_3(cv::Mat); // 最快的 15 | void method6(cv::Mat); 16 | void method7(cv::Mat); 17 | void method8(cv::Mat); 18 | 19 | int main(int argc, char* argv[]) 20 | { 21 | cv::Size imgSize(6400,4800); 22 | cv::Mat image = cv::Mat(imgSize, CV_8UC3, cv::Scalar(1,1,1)); 23 | method1(image); 24 | method2(image); 25 | method3(image); 26 | method4(image); 27 | method5(image); 28 | method5_2(image); 29 | method5_3(image); 30 | method6(image); 31 | method7(image); 32 | method8(image); 33 | } 34 | 35 | void method1(cv::Mat img){ 36 | // at access with Vec3b Vector 37 | double t0 = (double) cv::getTickCount(); 38 | int height = img.rows; 39 | int width = img.cols; 40 | int sum = 0; 41 | for(int row=0; row < height; row++){ 42 | for(int col=0; col < width; col++){ 43 | cv::Vec3b uc_pixel = img.at(row, col); 44 | int a = uc_pixel[0]; 45 | int b = uc_pixel[1]; 46 | int c = uc_pixel[2]; 47 | sum += a + b + c; 48 | } 49 | } 50 | assert(sum==3*height*width); 51 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 52 | std::cout << "Time for method1: " << time << std::endl; 53 | } 54 | 55 | void method2(cv::Mat img){ 56 | // direct at access 57 | double t0 = (double) cv::getTickCount(); 58 | int height = img.rows; 59 | int width = img.cols; 60 | int sum = 0; 61 | for(int row=0; row < height; row++){ 62 | for(int col=0; col < width; col++){ 63 | int a = img.at(row, col)[0]; 64 | int b = img.at(row, col)[1]; 65 | int c = img.at(row, col)[2]; 66 | sum += a + b + c; 67 | } 68 | } 69 | assert(sum==3*height*width); 70 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 71 | std::cout << "Time for method2: " << time << std::endl; 72 | } 73 | 74 | void method3(cv::Mat img){ 75 | // pointer + Vec3b vector 76 | double t0 = (double) cv::getTickCount(); 77 | int height = img.rows; 78 | int width = img.cols; 79 | int sum = 0; 80 | for(int row=0; row < height; row++){ 81 | cv::Vec3b *ptr = img.ptr(row); 82 | for(int col=0; col < width; col++){ 83 | cv::Vec3b pixel = ptr[col]; 84 | int a = pixel[0]; 85 | int b = pixel[1]; 86 | int c = pixel[2]; 87 | sum += a + b + c; 88 | } 89 | } 90 | assert(sum==3*height*width); 91 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 92 | std::cout << "Time for method3: " << time << std::endl; 93 | } 94 | 95 | void method4(cv::Mat img){ 96 | // pointer 97 | double t0 = (double) cv::getTickCount(); 98 | int height = img.rows; 99 | int width = img.cols; 100 | int sum = 0; 101 | for(int row=0; row < height; row++){ 102 | cv::Vec3b *ptr = img.ptr(row); 103 | for(int col=0; col < width; col++){ 104 | int a = ptr[col][0]; 105 | int b = ptr[col][1]; 106 | int c = ptr[col][2]; 107 | sum += a + b + c; 108 | } 109 | } 110 | assert(sum==3*height*width); 111 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 112 | std::cout << "Time for method4: " << time << std::endl; 113 | } 114 | 115 | void method5(cv::Mat img){ 116 | // raw pointer 117 | double t0 = (double) cv::getTickCount(); 118 | int height = img.rows; 119 | int width = img.cols; 120 | int sum=0; 121 | for(int row=0; row < height; row++){ 122 | const uchar *ptr = img.ptr(row); 123 | for(int col=0; col < width; col++){ 124 | const uchar *uc_pixel = ptr; 125 | int a = uc_pixel[0]; 126 | int b = uc_pixel[1]; 127 | int c = uc_pixel[2]; 128 | // int a = ptr[0]; 129 | // int b = ptr[1]; 130 | // int c = ptr[2]; 131 | sum += a + b + c; 132 | ptr += 3; 133 | } 134 | } 135 | assert(sum==3*height*width); 136 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 137 | std::cout << "Time for method5: " << time << std::endl; 138 | } 139 | 140 | void method5_2(cv::Mat img){ 141 | // raw pointer 142 | double t0 = (double) cv::getTickCount(); 143 | int height = img.rows; 144 | int width = img.cols; 145 | int sum=0; 146 | for(int row=0; row < height; row++){ 147 | const uchar *ptr = img.ptr(row); 148 | for(int col=0; col < width; col++){ 149 | // const uchar *uc_pixel = ptr; 150 | // int a = uc_pixel[0]; 151 | // int b = uc_pixel[1]; 152 | // int c = uc_pixel[2]; 153 | // 不使用中间指针 154 | int a = ptr[0]; 155 | int b = ptr[1]; 156 | int c = ptr[2]; 157 | sum += a + b + c; 158 | ptr += 3; 159 | } 160 | } 161 | assert(sum==3*height*width); 162 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 163 | std::cout << "Time for method5_2: " << time << std::endl; 164 | } 165 | 166 | void method5_3(cv::Mat img){ 167 | // raw pointer 168 | double t0 = (double) cv::getTickCount(); 169 | int height = img.rows; 170 | int width = img.cols; 171 | 172 | // 如果内存连续排列,当做单行处理 173 | if(img.isContinuous()) { 174 | width = width * height; 175 | height = 1; 176 | } else { 177 | printf("img.isContinuous() is false\n"); 178 | } 179 | 180 | int sum = 0; 181 | for(int row = 0; row < height; row++){ 182 | const uchar *ptr = img.ptr(row); 183 | for(int col = 0; col < width; col++){ 184 | sum += ptr[0] + ptr[1] + ptr[2]; 185 | ptr += 3; 186 | } 187 | } 188 | assert(sum==3*height*width); 189 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 190 | std::cout << "Time for method5_3: " << time << std::endl; 191 | } 192 | 193 | void method6(cv::Mat img){ 194 | // raw pointer + raw step 195 | // 必须保证Mat在内存的存储是连续的 196 | double t0 = (double) cv::getTickCount(); 197 | int height = img.rows; 198 | int width = img.cols; 199 | int sum = 0; 200 | const uchar *uc_pixel = img.data; 201 | for(int row=0; row < height; row++){ 202 | uc_pixel = img.data + row*img.step; 203 | for(int col=0; col < width; col++){ 204 | int a = uc_pixel[0]; 205 | int b = uc_pixel[1]; 206 | int c = uc_pixel[2]; 207 | sum += a + b + c; 208 | uc_pixel += 3; 209 | } 210 | } 211 | assert(sum==3*height*width); 212 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 213 | std::cout << "Time for method6: " << time << std::endl; 214 | } 215 | 216 | void method7(cv::Mat image){ 217 | double t0 = (double) cv::getTickCount(); 218 | int height = image.rows; 219 | int width = image.cols; 220 | cv::MatConstIterator_ it = image.begin(), it_end = image.end(); 221 | int sum = 0; 222 | for(; it != it_end; ++it){ 223 | int a = (*it)[0]; 224 | int b = (*it)[1]; 225 | int c = (*it)[2]; 226 | sum += a + b + c; 227 | } 228 | assert(sum==3*height*width); 229 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 230 | std::cout << "Time for method7: " << time << std::endl; 231 | } 232 | 233 | // C++11 Lambda 234 | //typedef cv::Point3_ Pixel; 235 | typedef cv::Vec3b Pixel; 236 | 237 | void method8(cv::Mat image){ 238 | if(image.isContinuous()) { 239 | printf("img.isContinuous() is true\n"); 240 | } else { 241 | printf("img.isContinuous() is false\n"); 242 | } 243 | double t0 = (double) cv::getTickCount(); 244 | int height = image.rows; 245 | int width = image.cols; 246 | // 用forEach,要小心Data Race!所以不一定高效的,反而有可能是最慢的 247 | #if 1 248 | std::atomic num; 249 | std::atomic sum; 250 | #else 251 | // 这个是不能用的,会有Data Race! 252 | int num, sum; 253 | #endif 254 | num = 0; 255 | sum = 0; 256 | image.forEach( 257 | [&](Pixel &pixel, const int * position) -> void { 258 | if(pixel[0] != 1 or pixel[1] != 1 or pixel[2] != 1) { 259 | printf("pixel[0] = %d, pixel[1] = %d, pixel[2] = %d\n", pixel[0], pixel[1], pixel[2]); 260 | } 261 | //sum += pixel.x + pixel.y + pixel.z; 262 | sum += pixel[0] + pixel[1] + pixel[2]; 263 | num++; 264 | } 265 | ); 266 | #if 1 267 | printf("num = %d, sum = %d, sum/3 = %d, 3*height*width = %d\n", num.load(), sum.load(), sum.load()/3, 3*height*width); 268 | assert(sum.load()==3*height*width); 269 | #else 270 | printf("num = %d, sum = %d, sum/3 = %d, 3*height*width = %d\n", num, sum, sum/3, 3*height*width); 271 | assert(sum==3*height*width); 272 | #endif 273 | double time = ((double) cv::getTickCount() - t0) / cv::getTickFrequency(); 274 | std::cout << "Time for method8: " << time << std::endl; 275 | } 276 | -------------------------------------------------------------------------------- /U#0010-scan_cvmat_efficiently/perf.log: -------------------------------------------------------------------------------- 1 | Time for method1: 0.491206 2 | Time for method2: 0.373942 3 | Time for method3: 0.443038 4 | Time for method4: 0.190631 5 | Time for method5: 0.0971285 6 | Time for method5_2: 0.0830259 7 | Time for method5_3: 0.064057 8 | Time for method6: 0.0820537 9 | Time for method7: 0.469414 10 | 11 | Time for method8: ~1.0 12 | -------------------------------------------------------------------------------- /U#0011-Anaconda使用经验/README.md: -------------------------------------------------------------------------------- 1 | #       Anaconda使用经验 2 | 3 | 1. 关闭默认进去base环境 4 | 5 | `conda config --set auto_activate_base false` 6 | 7 | 2. 换回默认源 8 | 9 | `conda config --remove-key channels` 10 | 11 | 3. 建立一个新的环境 12 | 13 | `conda create --name py352 python=3.5.2` 14 | 15 | 按照yml文件的配置建立一个新的环境 16 | 17 | `conda env create -f environment.yml` 18 | 19 | 按照yml更新现有环境 20 | 21 | `conda env update -f environment.yml` 22 | 23 | 4. 删除一个新的环境(然后选择y) 24 | 25 | `conda create --name py352 python=3.5.2` 26 | 27 | 或者 28 | 29 | `conda remove -n py352 --all` 30 | 31 | 5. 切换到一个已有的环境 32 | 33 | `conda activate py352` 34 | 35 | 6. 退出当前环境 36 | 37 | `conda deactivate` 38 | 39 | 7. 查看已有环境列表 40 | 41 | `conda info -e` 42 | 43 | 8. 添加镜像源(Anaconda的[清华TUNA镜像](https://mirror.tuna.tsinghua.edu.cn/help/anaconda/)) 44 | 45 | `conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/` 46 | 47 | `conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/` 48 | 49 | `conda config --set show_channel_urls yes` 50 | 51 | 9. 查看已经安装在本环境中的包 52 | 53 | `conda list` 54 | 55 | 10. 查找可安装的包(pandas为例) 56 | 57 | `conda search pandas` 58 | 59 | 11. 安装包 60 | 61 | `conda install pandas` 62 | 63 | 12. 更新包 64 | 65 | `conda update pandas` 66 | 67 | 13. 卸载包 68 | 69 | `conda remove pandas` 70 | 71 | 14. 72 | 73 | -------------------------------------------------------------------------------- /U#0012-Kaggle-api常用命令/README.md: -------------------------------------------------------------------------------- 1 | #       Kaggle-api常用命令 2 | 3 | **本文总结了Kaggle比赛常用的kaggle命令备查,更细节的内容可以参见https://github.com/Kaggle/kaggle-api** 4 | 5 | 1. 安装kaggle命令 6 | 7 | `pip install kaggle` 8 | 9 | 2. 安装kaggle API credentials 10 | 11 | Step 1. 登陆kaggle帐号,找到Account->Create API Token,下载一个kaggle.json文件; 12 | 13 | Step 2. 把刚下载的kaggle.json文件放到~/.kaggle/kaggle.json这里 14 | 15 | 3. 查看比赛列表 16 | 17 | `kaggle competitions list` 18 | 19 | 4. 提交一个结果 20 | 21 | `kaggle competitions submit house-prices-advanced-regression-techniques -f sample_submission.csv -m "My first submission"` 22 | 23 | -------------------------------------------------------------------------------- /U#0013-caffe_merge_bn_ssd/merge_bn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3.6 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import sys 6 | import argparse 7 | import logging 8 | 9 | import numpy as np 10 | try: 11 | caffe_root = '/home/dup/work/opensource/ssd/' 12 | sys.path.insert(0, caffe_root + 'python') 13 | import caffe 14 | except ImportError: 15 | logging.fatal("Cannot find caffe!") 16 | from caffe.proto import caffe_pb2 17 | from google.protobuf import text_format 18 | 19 | def make_parser(): 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument('--model', type=str, required=True, help='.prototxt file for inference') 22 | parser.add_argument('--weights', type=str, required=True, help='.caffemodel file for inference') 23 | return parser 24 | 25 | bn_maps = {} 26 | def find_top_after_bn(layers, name, top): 27 | bn_maps[name] = {} 28 | for l in layers: 29 | if len(l.bottom) == 0: 30 | continue 31 | if l.bottom[0] == top and l.type == "BatchNorm": 32 | bn_maps[name]["bn"] = l.name 33 | top = l.top[0] 34 | if l.bottom[0] == top and l.type == "Scale": 35 | bn_maps[name]["scale"] = l.name 36 | top = l.top[0] 37 | return top 38 | 39 | def pre_process(expected_proto, new_proto): 40 | net_specs = caffe_pb2.NetParameter() 41 | net_specs2 = caffe_pb2.NetParameter() 42 | with open(expected_proto, "r") as fp: 43 | text_format.Merge(str(fp.read()), net_specs) 44 | 45 | net_specs2.MergeFrom(net_specs) 46 | layers = net_specs.layer 47 | num_layers = len(layers) 48 | 49 | for i in range(num_layers - 1, -1, -1): 50 | del net_specs2.layer[i] 51 | 52 | for idx in range(num_layers): 53 | l = layers[idx] 54 | if l.type == "BatchNorm" or l.type == "Scale": 55 | continue 56 | elif l.type == "Convolution" or l.type == "Deconvolution": 57 | top = find_top_after_bn(layers, l.name, l.top[0]) 58 | bn_maps[l.name]["type"] = l.type 59 | layer = net_specs2.layer.add() 60 | layer.MergeFrom(l) 61 | layer.top[0] = top 62 | layer.convolution_param.bias_term = True 63 | else: 64 | layer = net_specs2.layer.add() 65 | layer.MergeFrom(l) 66 | 67 | with open(new_proto, "w") as fp: 68 | fp.write("{}".format(net_specs2)) 69 | 70 | def load_weights(net, nobn): 71 | if sys.version_info > (3,0): 72 | listKeys = nobn.params.keys() 73 | else: 74 | listKeys = nobn.params.iterkeys() 75 | for key in listKeys: 76 | if type(nobn.params[key]) is caffe._caffe.BlobVec: 77 | conv = net.params[key] 78 | if key not in bn_maps or "bn" not in bn_maps[key]: 79 | for i, w in enumerate(conv): 80 | nobn.params[key][i].data[...] = w.data 81 | else: 82 | print(key) 83 | bn = net.params[bn_maps[key]["bn"]] 84 | scale = net.params[bn_maps[key]["scale"]] 85 | wt = conv[0].data 86 | channels = 0 87 | if bn_maps[key]["type"] == "Convolution": 88 | channels = wt.shape[0] 89 | elif bn_maps[key]["type"] == "Deconvolution": 90 | channels = wt.shape[1] 91 | else: 92 | print("error type " + bn_maps[key]["type"]) 93 | exit(-1) 94 | bias = np.zeros(channels) 95 | if len(conv) > 1: 96 | bias = conv[1].data 97 | mean = bn[0].data 98 | var = bn[1].data 99 | scalef = bn[2].data 100 | 101 | scales = scale[0].data 102 | shift = scale[1].data 103 | 104 | if scalef != 0: 105 | scalef = 1. / scalef 106 | mean = mean * scalef 107 | var = var * scalef 108 | rstd = 1. / np.sqrt(var + 1e-5) 109 | if bn_maps[key]["type"] == "Convolution": 110 | rstd1 = rstd.reshape((channels,1,1,1)) 111 | scales1 = scales.reshape((channels,1,1,1)) 112 | wt = wt * rstd1 * scales1 113 | else: 114 | rstd1 = rstd.reshape((1, channels,1,1)) 115 | scales1 = scales.reshape((1, channels,1,1)) 116 | wt = wt * rstd1 * scales1 117 | bias = (bias - mean) * rstd * scales + shift 118 | 119 | nobn.params[key][0].data[...] = wt 120 | nobn.params[key][1].data[...] = bias 121 | 122 | if __name__ == '__main__': 123 | parser1 = make_parser() 124 | args = parser1.parse_args() 125 | pre_process(args.model, "no_bn.prototxt") 126 | 127 | net = caffe.Net(args.model, args.weights, caffe.TEST) 128 | net2 = caffe.Net("no_bn.prototxt", caffe.TEST) 129 | 130 | load_weights(net, net2) 131 | net2.save("no_bn.caffemodel") 132 | 133 | -------------------------------------------------------------------------------- /U#0014-打印OpenCV版本和编译信息/getOpenCVInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "opencv2/opencv.hpp" 2 | 3 | // 参考资料:https://www.learnopencv.com/how-to-find-opencv-version-python-cpp/ 4 | // https://www.learnopencv.com/get-opencv-build-information-getbuildinformation/ 5 | // 编译方法:g++ getOpenCVInfo.cpp `pkg-config --libs --cflags opencv` 6 | // 7 | int main(int argc, char** argv) 8 | { 9 | // 打印版本信息(从头文件中拿) 10 | std::cout << "OpenCV version : " << CV_VERSION << std::endl; 11 | std::cout << "Major version : " << CV_MAJOR_VERSION << std::endl; 12 | std::cout << "Minor version : " << CV_MINOR_VERSION << std::endl; 13 | std::cout << "Subminor version : " << CV_SUBMINOR_VERSION << std::endl; 14 | 15 | // 打印编译信息(从库中拿) 16 | std::cout << cv::getBuildInformation() << std::endl; 17 | 18 | if (CV_MAJOR_VERSION < 3) { 19 | // Old OpenCV 2 code goes here. 20 | } else { 21 | // New OpenCV 3 code goes here. 22 | } 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /U#0014-打印OpenCV版本和编译信息/getOpenCVInfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3.6 2 | #-*- coding: utf-8 -*- 3 | 4 | import cv2 5 | 6 | # 参考资料:https://www.learnopencv.com/how-to-find-opencv-version-python-cpp/ 7 | # https://www.learnopencv.com/get-opencv-build-information-getbuildinformation/ 8 | 9 | # Print version string 10 | print "OpenCV version : {0}".format(cv2.__version__) 11 | 12 | # Extract major, minor, and subminor version numbers 13 | (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.') 14 | print "Major version : {0}".format(major_ver) 15 | print "Minor version : {0}".format(minor_ver) 16 | print "Submior version : {0}".format(subminor_ver) 17 | 18 | # Print Build Information 19 | print cv2.getBuildInformation() 20 | 21 | if int(major_ver) < 3 : 22 | ''' 23 | Old OpenCV 2 code goes here 24 | ''' 25 | else : 26 | ''' 27 | New OpenCV 3 code goes here 28 | ''' 29 | -------------------------------------------------------------------------------- /U#0015-Docker使用经验/README.md: -------------------------------------------------------------------------------- 1 | #       Docker使用经验 2 | 3 | **本文总结了Kaggle比赛常用的kaggle命令备查** 4 | 5 | ### 使用经验 6 | 7 | #### **1. 在Ubuntu上安装Docker** 8 | 9 | Step 1. add the GPG key for the official Docker repository to the system 10 | 11 | `curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -` 12 | 13 | Step 2. Add the Docker repository to APT sources 14 | 15 | `sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"` 16 | 17 | Step 3. update the package database with the Docker packages from the newly added repo 18 | 19 | `sudo apt-get update` 20 | 21 | Step 4. Make sure you are about to install from the Docker repo instead of the default Ubuntu 16.04 repo 22 | 23 | `apt-cache policy docker-ce` 24 | 25 | Step 5. You should see output similar to the following: 26 | 27 | ``` 28 | docker-ce: 29 | Installed: (none) 30 | Candidate: 17.03.1~ce-0~ubuntu-xenial 31 | Version table: 32 | 17.03.1~ce-0~ubuntu-xenial 500 33 | 500 https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages 34 | 17.03.0~ce-0~ubuntu-xenial 500 35 | 500 https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages 36 | ``` 37 | 38 | Step 6. install Docker 39 | 40 | `sudo apt-get install -y docker-ce` 41 | 42 | #### **2. 安装Docker OpenCV Image** 43 | 44 | 注意,docker image默认不支持X11转发,需要自己做映射 45 | 46 | Step 1. 下载/更新Docker image 47 | 48 | `docker pull spmallick/opencv-docker:opencv` 49 | 50 | Step 2. 跑起来 51 | 52 | `docker run --device=/dev/video0:/dev/video0 -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -p 5000:5000 -p 8888:8888 -it spmallick/opencv-docker:opencv /bin/bash` 53 | 54 | 关于上面命令一些选项的注释: 55 | 56 | - **–device=/dev/video0:/dev/video0** allows use of webcam 57 | - **-v /tmp/.X11-unix:/tmp/.X11-unix** helps in X11 forwarding so that we can use functions like **cv::imshow**. 58 | - **-e** is used to pass an environment variable. 59 | - **-it** starts an interactive session 60 | - **-p** sets up a port forward. This flag maps the container’s port to a port on the host system. 61 | - **/bin/bash** runs **.bashrc** file on startup 62 | 63 | #### **3. 提交对Docker Image的修改** 64 | 65 | 默认在Docker容器内的修改是不会保存在Docker image里面的,需要自己如下图所示Commit一下: 66 | 67 | ![](images/commit-changes-to-docker-image.png) 68 | 69 | #### **4.** 70 | 71 | 72 | 73 | ### 参考资料 74 | 75 | [Install OpenCV Docker Image on Ubuntu, MacOS or Windows](https://www.learnopencv.com/install-opencv-docker-image-ubuntu-macos-windows/) 76 | -------------------------------------------------------------------------------- /U#0015-Docker使用经验/images/commit-changes-to-docker-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Captain1986/utils/1df307ac16dbe2fc33788a92033dddd7c5c3393a/U#0015-Docker使用经验/images/commit-changes-to-docker-image.png -------------------------------------------------------------------------------- /U#0016-JetsonNano使用经验/README.md: -------------------------------------------------------------------------------- 1 | #       JetsonNano使用经验 2 | 3 | **本文总结了JetsonNano常用的使用经验备查** 4 | 5 | ### 使用经验 6 | 7 | #### **1. 打开个关闭图形界面** 8 | 9 | 打开图形界面: 10 | 11 | `sudo systemctl set-default graphical.target` 12 | 13 | `sudo reboot` 14 | 15 | 关闭图形界面: 16 | 17 | `sudo systemctl set-default multi-user.target` 18 | 19 | `sudo reboot` 20 | 21 | #### **2.** 22 | 23 | ### 参考资料 24 | 25 | -------------------------------------------------------------------------------- /U#0017-PyTorch_tricks/README.md: -------------------------------------------------------------------------------- 1 | #       PyTorch Tricks 2 | 3 | **本文总结了PyTorch常用的使用经验备查** 4 | 5 | ### 使用经验 6 | 7 | #### **1. 指定使用哪些GPU** 8 | 9 | 设置当前使用的GPU设备为0,1号两个设备,名称依次为 `/gpu:0`、`/gpu:1`: 10 | 11 | `os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"` ,根据顺序表示优先使用0号设备,然后使用1号设备。 12 | 13 | 指定GPU的命令需要**放在和神经网络相关的一系列操作的前面**。 14 | 15 | #### **2. 查看模型每层输出详情** 16 | 17 | Keras有一个简洁的API来查看模型的每一层输出尺寸,这在调试网络时非常有用。现在在PyTorch中也可以实现这个功能。 18 | 19 | 使用很简单,如下用法: 20 | 21 | ```python3 22 | from torchsummary import summary 23 | 24 | summary(your_model, input_size=(channels, H, W)) 25 | ``` 26 | 27 | `input_size` 是根据你自己的网络模型的输入尺寸进行设置。 28 | 29 | #### **3. 梯度裁剪(Gradient Clipping)** 30 | 31 | ```python3 32 | import torch.nn as nn 33 | 34 | outputs = model(data) 35 | loss= loss_fn(outputs, target) 36 | optimizer.zero_grad() 37 | loss.backward() 38 | nn.utils.clip_grad_norm_(model.parameters(), max_norm=20, norm_type=2) 39 | optimizer.step() 40 | ``` 41 | 42 | `nn.utils.clip_grad_norm_` 的参数: 43 | 44 | - **parameters** – 一个基于变量的迭代器,会进行梯度归一化 45 | - **max_norm** – 梯度的最大范数 46 | - **norm_type** – 规定范数的类型,默认为L2 47 | 48 | #### **4. 扩展单张图片维度** 49 | 50 | 因为在训练时的数据维度一般都是 (batch_size, c, h, w),而在测试时只输入一张图片,所以需要扩展维度,扩展维度有多个方法: 51 | 52 | ```python3 53 | import cv2 54 | import torch 55 | 56 | image = cv2.imread(img_path) 57 | image = torch.tensor(image) 58 | print(image.size()) 59 | 60 | img = image.view(1, *image.size()) 61 | print(img.size()) 62 | 63 | # output: 64 | # torch.Size([h, w, c]) 65 | # torch.Size([1, h, w, c]) 66 | ``` 67 | 68 | 或 69 | 70 | ```python3 71 | import cv2 72 | import numpy as np 73 | 74 | image = cv2.imread(img_path) 75 | print(image.shape) 76 | img = image[np.newaxis, :, :, :] 77 | print(img.shape) 78 | 79 | # output: 80 | # (h, w, c) 81 | # (1, h, w, c) 82 | ``` 83 | 84 | 或(感谢知乎用户 `coldleaf` 的补充) 85 | 86 | ```python3 87 | import cv2 88 | import torch 89 | 90 | image = cv2.imread(img_path) 91 | image = torch.tensor(image) 92 | print(image.size()) 93 | 94 | img = image.unsqueeze(dim=0) 95 | print(img.size()) 96 | 97 | img = img.squeeze(dim=0) 98 | print(img.size()) 99 | 100 | # output: 101 | # torch.Size([(h, w, c)]) 102 | # torch.Size([1, h, w, c]) 103 | # torch.Size([h, w, c]) 104 | ``` 105 | 106 | `tensor.unsqueeze(dim)`:扩展维度,dim指定扩展哪个维度。 107 | 108 | `tensor.squeeze(dim)`:去除dim指定的且size为1的维度,维度大于1时,squeeze()不起作用,不指定dim时,去除所有size为1的维度。 109 | 110 | #### **5. 独热编码** 111 | 112 | 在PyTorch中使用交叉熵损失函数的时候会自动把label转化成onehot,所以不用手动转化,而使用MSE需要手动转化成onehot编码。 113 | 114 | ```python3 115 | import torch 116 | class_num = 8 117 | batch_size = 4 118 | 119 | def one_hot(label): 120 | """ 121 | 将一维列表转换为独热编码 122 | """ 123 | label = label.resize_(batch_size, 1) 124 | m_zeros = torch.zeros(batch_size, class_num) 125 | # 从 value 中取值,然后根据 dim 和 index 给相应位置赋值 126 | onehot = m_zeros.scatter_(1, label, 1) # (dim,index,value) 127 | 128 | return onehot.numpy() # Tensor -> Numpy 129 | 130 | label = torch.LongTensor(batch_size).random_() % class_num # 对随机数取余 131 | print(one_hot(label)) 132 | 133 | # output: 134 | [[0. 0. 0. 1. 0. 0. 0. 0.] 135 | [0. 0. 0. 0. 1. 0. 0. 0.] 136 | [0. 0. 1. 0. 0. 0. 0. 0.] 137 | [0. 1. 0. 0. 0. 0. 0. 0.]] 138 | ``` 139 | 140 | #### **6. 防止验证模型时爆显存** 141 | 142 | ```python3 143 | with torch.no_grad(): 144 | # 使用model进行预测的代码 145 | pass 146 | ``` 147 | 148 | #### **7. 学习率衰减** 149 | 150 | ```python3 151 | import torch.optim as optim 152 | from torch.optim import lr_scheduler 153 | 154 | # 训练前的初始化 155 | optimizer = optim.Adam(net.parameters(), lr=0.001) 156 | scheduler = lr_scheduler.StepLR(optimizer, 10, 0.1) # # 每过10个epoch,学习率乘以0.1 157 | 158 | # 训练过程中 159 | for n in n_epoch: 160 | scheduler.step() 161 | ... 162 | ``` 163 | 164 | #### **8. 冻结某些层的参数** 165 | 166 | 在加载预训练模型的时候,我们有时想冻结前面几层,使其参数在训练过程中不发生变化。 167 | 168 | 我们需要先知道每一层的名字,通过如下代码打印: 169 | 170 | ```python3 171 | net = Network() # 获取自定义网络结构 172 | for name, value in net.named_parameters(): 173 | print('name: {0},\t grad: {1}'.format(name, value.requires_grad)) 174 | ``` 175 | 176 | 假设前几层信息如下: 177 | 178 | ```python3 179 | name: cnn.VGG_16.convolution1_1.weight, grad: True 180 | name: cnn.VGG_16.convolution1_1.bias, grad: True 181 | name: cnn.VGG_16.convolution1_2.weight, grad: True 182 | name: cnn.VGG_16.convolution1_2.bias, grad: True 183 | name: cnn.VGG_16.convolution2_1.weight, grad: True 184 | name: cnn.VGG_16.convolution2_1.bias, grad: True 185 | name: cnn.VGG_16.convolution2_2.weight, grad: True 186 | name: cnn.VGG_16.convolution2_2.bias, grad: True 187 | ``` 188 | 189 | 后面的True表示该层的参数可训练,然后我们定义一个要冻结的层的列表: 190 | 191 | ```python3 192 | no_grad = [ 193 | 'cnn.VGG_16.convolution1_1.weight', 194 | 'cnn.VGG_16.convolution1_1.bias', 195 | 'cnn.VGG_16.convolution1_2.weight', 196 | 'cnn.VGG_16.convolution1_2.bias' 197 | ] 198 | ``` 199 | 200 | 冻结方法如下: 201 | 202 | ```python3 203 | net = Net.CTPN() # 获取网络结构 204 | for name, value in net.named_parameters(): 205 | if name in no_grad: 206 | value.requires_grad = False 207 | else: 208 | value.requires_grad = True 209 | ``` 210 | 211 | 冻结后我们再打印每层的信息: 212 | 213 | ```python3 214 | name: cnn.VGG_16.convolution1_1.weight, grad: False 215 | name: cnn.VGG_16.convolution1_1.bias, grad: False 216 | name: cnn.VGG_16.convolution1_2.weight, grad: False 217 | name: cnn.VGG_16.convolution1_2.bias, grad: False 218 | name: cnn.VGG_16.convolution2_1.weight, grad: True 219 | name: cnn.VGG_16.convolution2_1.bias, grad: True 220 | name: cnn.VGG_16.convolution2_2.weight, grad: True 221 | name: cnn.VGG_16.convolution2_2.bias, grad: True 222 | ``` 223 | 224 | 可以看到前两层的weight和bias的requires_grad都为False,表示它们不可训练。 225 | 226 | 最后在定义优化器时,只对requires_grad为True的层的参数进行更新。 227 | 228 | ```python3 229 | optimizer = optim.Adam(filter(lambda p: p.requires_grad, net.parameters()), lr=0.01) 230 | ``` 231 | 232 | #### **9. 对不同层使用不同学习率** 233 | 234 | 我们对模型的不同层使用不同的学习率。 235 | 236 | 还是使用这个模型作为例子: 237 | 238 | ```python3 239 | net = Network() # 获取自定义网络结构 240 | for name, value in net.named_parameters(): 241 | print('name: {}'.format(name)) 242 | 243 | # 输出: 244 | # name: cnn.VGG_16.convolution1_1.weight 245 | # name: cnn.VGG_16.convolution1_1.bias 246 | # name: cnn.VGG_16.convolution1_2.weight 247 | # name: cnn.VGG_16.convolution1_2.bias 248 | # name: cnn.VGG_16.convolution2_1.weight 249 | # name: cnn.VGG_16.convolution2_1.bias 250 | # name: cnn.VGG_16.convolution2_2.weight 251 | # name: cnn.VGG_16.convolution2_2.bias 252 | ``` 253 | 254 | 对 convolution1 和 convolution2 设置不同的学习率,首先将它们分开,即放到不同的列表里: 255 | 256 | ```python3 257 | conv1_params = [] 258 | conv2_params = [] 259 | 260 | for name, parms in net.named_parameters(): 261 | if "convolution1" in name: 262 | conv1_params += [parms] 263 | else: 264 | conv2_params += [parms] 265 | 266 | # 然后在优化器中进行如下操作: 267 | optimizer = optim.Adam( 268 | [ 269 | {"params": conv1_params, 'lr': 0.01}, 270 | {"params": conv2_params, 'lr': 0.001}, 271 | ], 272 | weight_decay=1e-3, 273 | ) 274 | ``` 275 | 276 | 我们将模型划分为两部分,存放到一个列表里,每部分就对应上面的一个字典,在字典里设置不同的学习率。当这两部分有相同的其他参数时,就将该参数放到列表外面作为全局参数,如上面的`weight_decay`。 277 | 278 | 也可以在列表外设置一个全局学习率,当各部分字典里设置了局部学习率时,就使用该学习率,否则就使用列表外的全局学习率。 279 | 280 | #### **10. 模型参数和计算量分析** 281 | 282 | **方法一**:参考这里的工具https://github.com/sovrasov/flops-counter.pytorch 283 | 284 | **Install** 285 | 286 | ```Python3 287 | pip install --upgrade git+https://github.com/sovrasov/flops-counter.pytorch.git 288 | ``` 289 | 290 | **Example** 291 | 292 | ```Python3 293 | import torchvision.models as models 294 | import torch 295 | from ptflops import get_model_complexity_info 296 | 297 | with torch.cuda.device(0): 298 | net = models.densenet161() 299 | flops, params = get_model_complexity_info(net, (3, 224, 224), as_strings=True, print_per_layer_stat=True) 300 | print('Flops: ' + flops) 301 | print('Params: ' + params) 302 | ``` 303 | 304 | **方法二**:参考这里的工具https://github.com/Lyken17/pytorch-OpCounter 305 | 306 | **Install** 307 | 308 | ```PyThon3 309 | pip install thop 310 | or 311 | pip install --upgrade git+https://github.com/Lyken17/pytorch-OpCounter.git 312 | ``` 313 | 314 | **Example** 315 | 316 | ```Python3 317 | from torchvision.models import resnet50 318 | from thop import profile 319 | model = resnet50() 320 | input = torch.randn(1, 3, 224, 224) 321 | flops, params = profile(model, inputs=(input, )) 322 | 323 | from thop import clever_format 324 | flops, params = clever_format([flops, params], "%.3f") 325 | ``` 326 | 327 | 328 | 329 | 330 | ### 参考资料 331 | 332 | [PyTorch trick 集锦](https://zhuanlan.zhihu.com/p/76459295) 333 | 334 | [CNN 模型所需的计算力(flops)和参数(parameters)数量是怎么计算的?](https://www.zhihu.com/question/65305385) 335 | 336 | -------------------------------------------------------------------------------- /U#0018-常见模型参数量、计算量和速度统计/README.md: -------------------------------------------------------------------------------- 1 | #       常见模型参数量、计算量和速度统计 2 | 3 | **本文总结常见模型参数量、计算量和速度信息备查** 4 | 5 | ## 目录 6 | 7 | [1. 分类网络](# 分类网络) 8 | 9 | [2.目标检测网络](# 目标检测网络) 10 | 11 | [3.关键点检测网络](# 关键点检测网络) 12 | 13 | [4. 参考资料](# 参考资料) 14 | 15 | ### 分类网络 16 | 17 | | Model | Input Resolution | Params(M) | MACs(GFLOPS) | Acc@1 | Acc@5 | 18 | | :-----------------: | :--------------: | :-------: | :----------: | :----: | ------ | 19 | | AlexNet | 224x224 | 61.10 | 0.72 | 56.432 | 79.194 | 20 | | GoogLeNet | 224x224 | 7.00 | 1.60 | | | 21 | | VGG11 | 224x224 | 132.86 | 7.63 | 69.02 | 88.63 | 22 | | VGG11_bn | 224x224 | 132.87 | 7.64 | 70.38 | 89.81 | 23 | | VGG13 | 224x224 | 133.05 | 11.34 | 69.93 | 89.25 | 24 | | VGG13_bn | 224x224 | 133.05 | 11.36 | 71.55 | 90.37 | 25 | | VGG16 | 224x224 | 138.36 | 15.5 | 71.59 | 90.38 | 26 | | VGG16_bn | 224x224 | 138.37 | 15.53 | 73.37 | 91.50 | 27 | | VGG19 | 224x224 | 143.67 | 19.67 | 72.38 | 90.88 | 28 | | VGG19_bn | 224x224 | 143.68 | 19.70 | 74.24 | 91.85 | 29 | | ResNet18 | 224x224 | 11.69 | 1.82 | 69.76 | 91.08 | 30 | | ResNet34 | 224x224 | 21.80 | 3.68 | 73.30 | 91.42 | 31 | | ResNet50 | 224x224 | 25.56 | 4.12 | 76.15 | 92.87 | 32 | | Wide_ResNet50_2 | | 68.88 | 11.46 | | | 33 | | ResNet101 | 224x224 | 44.55 | 7.85 | 77.37 | 93.56 | 34 | | Wide_ResNet101_2 | | 126.89 | 22.84 | | | 35 | | ResNet152 | 224x224 | 60.19 | 11.58 | 78.31 | 94.06 | 36 | | SqueezeNet1_0 | 224x224 | 1.25 | 0.83 | 58.10 | 80.42 | 37 | | SqueezeNet1_1 | 224x224 | 1.24 | 0.36 | 58.19 | 80.62 | 38 | | DenseNet121 | 224x224 | 7.98 | 2.88 | 74.65 | 92.17 | 39 | | DenseNet161 | 224x224 | 28.68 | 7.82 | 77.65 | 93.80 | 40 | | DenseNet169 | 224x224 | 14.15 | 3.42 | 76.00 | 93.00 | 41 | | DenseNet201 | 224x224 | 20.01 | 4.37 | 77.20 | 93.57 | 42 | | Inception_v3 | 224x224 | 27.16 | 2.85 | 77.45 | 93.56 | 43 | | Inception_v3 | 299x299 | 27.16 | 5.73 | 77.294 | 93.454 | 44 | | Inception_v4 | 299x299 | 42.68 | 13.31 | 80.062 | 94.926 | 45 | | Inception_bn | 224x224 | 11.3 | 2.05 | 73.524 | 91.562 | 46 | | DPN107 | 224x224 | 86.92 | 18.42 | 79.746 | 94.684 | 47 | | DPN131 | 224x224 | 79.25 | 16.13 | 79.432 | 94.574 | 48 | | DPN68 | 224x224 | 12.61 | 2.36 | 75.868 | 92.774 | 49 | | DPN68b | 224x224 | 12.61 | 2.36 | 77.034 | 93.59 | 50 | | DPN92 | 224x224 | 37.67 | 6.56 | 79.4 | 94.62 | 51 | | DPN98 | 224x224 | 61.57 | 11.76 | 79.224 | 94.488 | 52 | | FBResNet152 | 224x224 | 60.27 | 11.6 | 77.386 | 93.594 | 53 | | InceptionResNetv2 | 299x299 | 55.84 | 13.22 | 80.17 | 95.234 | 54 | | NasNetaLarge | 331x331 | 88.75 | 24.04 | 82.566 | 96.086 | 55 | | NasNetaMobile | 224x224 | 5.29 | 0.59 | 74.08 | 91.74 | 56 | | Pnasnet5Large | 331x331 | 86.06 | 25.21 | 82.736 | 95.992 | 57 | | PolyNet | 331x331 | 95.37 | 34.90 | 81.002 | 95.624 | 58 | | ResNeXt50_32x4d | | 25.03 | 4.29 | | | 59 | | ResNeXt101_32x4d | 224x224 | 44.18 | 8.03 | 78.188 | 93.886 | 60 | | ResNeXt101_32x8d | | 88.79 | 16.54 | | | 61 | | ResNeXt101_64x4d | 224x224 | 83.46 | 15.55 | 78.956 | 94.252 | 62 | | se_ResNet101 | 224x224 | 49.33 | 7.63 | 78.396 | 94.258 | 63 | | se_ResNet152 | 224x224 | 66.82 | 11.37 | 78.658 | 94.374 | 64 | | se_ResNet50 | 224x224 | 28.09 | 3.9 | 77.636 | 93.752 | 65 | | se_ResNeXt101_32x4d | 224x224 | 48.96 | 8.05 | 80.236 | 95.028 | 66 | | se_ResNeXt50_32x4d | 224x224 | 27.56 | 4.28 | 79.076 | 94.434 | 67 | | SENet154 | 224x224 | 115.09 | 20.82 | 81.304 | 95.498 | 68 | | Xception | 299x299 | 22.86 | 8.42 | 78.888 | 94.292 | 69 | | TextCNN | | 0.15 | 0.009 | | | 70 | | MnasNet0_5 | | 2.22 | 0.14 | | | 71 | | MnasNet0_75 | | 3.17 | 0.24 | | | 72 | | MnasNet1_0 | | 4.38 | 0.34 | | | 73 | | MnasNet1_3 | | 6.28 | 0.53 | | | 74 | | MobileNet_v2 | | 3.50 | 0.33 | | | 75 | | Shufflenet_v2_x0_5 | | 1.37 | 0.05 | | | 76 | | Shufflenet_v2_x1_0 | | 2.28 | 0.15 | | | 77 | | Shufflenet_v2_x1_5 | | 3.50 | 0.31 | | | 78 | | Shufflenet_v2_x2_0 | | 7.39 | 0.60 | | | 79 | 80 | ### 目标检测网络 81 | 82 | | Model | Input Resolution | Params Memory | Feature Memory | FLOPS | 83 | | :---------------------: | :--------------: | :-----------: | :------------: | :--------: | 84 | | RFCN-Res50-Pascal | 600x850 | 122 MB | 1 GB | 79 GFLOPS | 85 | | RFCN-Res101-Pascal | 600x850 | 194 MB | 2 GB | 117 GFLOPS | 86 | | SSD-Pascal-VGGvd-300 | 300x300 | 100 MB | 116 MB | 31 GFLOPS | 87 | | SSD-Pascal-VGGvd-512 | 512x512 | 104 MB | 337 MB | 91 GFLOPS | 88 | | SSD-Pascal-MobileNet-ft | 300x300 | 22 MB | 37 MB | 1 GFLOPS | 89 | | FasterRCNN-VGGvd-Pascal | 600x850 | 523 MB | 600 MB | 172 GFLOPS | 90 | 91 | ### 分割网络 92 | 93 | | Model | Input Resolution | Params Memory | Feature Memory | FLOPS | 94 | | :---------------: | :--------------: | :-----------: | :------------: | :--------: | 95 | | Pascal-FCN-32s | 384x384 | 519 MB | 423 MB | 125 GFLOPS | 96 | | Pascal-FCN-16s | 384x384 | 514 MB | 424 MB | 125 GFLOPS | 97 | | Pascal-FCN-8s | 384x384 | 513 MB | 426 MB | 125 GFLOPS | 98 | | Deeplab-VGGvd-v2 | 513x513 | 144 MB | 755 MB | 202 GFLOPS | 99 | | Deeplab-Res101-v2 | 513x513 | 505 MB | 4 GB | 346 GFLOPS | 100 | 101 | ### 关键点检测网络 102 | 103 | | Model | Input Resolution | Params Memory | Feature Memory | FLOPS | 104 | | :------------: | :--------------: | :-----------: | :------------: | :--------: | 105 | | MultiPose-mpi | 368x368 | 196 MB | 245 MB | 134 GFLOPS | 106 | | MultiPose-coco | 368x368 | 200 MB | 246 MB | 136 GFLOPS | 107 | 108 | ### 参考资料 109 | 110 | [pytorch-OpCounter](https://github.com/Lyken17/pytorch-OpCounter) 111 | 112 | [flops-counter.pytorch](https://github.com/sovrasov/flops-counter.pytorch) 113 | 114 | [convnet-burden](https://github.com/albanie/convnet-burden) 115 | 116 | [Characterization and Benchmarking of Deep Learning](https://www.hpcuserforum.com/presentations/Wisconsin2017/HPDLCookbook4HPCUserForum.pdf) 117 | 118 | -------------------------------------------------------------------------------- /U#0019-C++11线程池/build.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | g++ main.cpp thread_pool.cpp -std=c++11 -lpthread -O0 4 | -------------------------------------------------------------------------------- /U#0019-C++11线程池/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "thread_pool.h" 4 | 5 | #define TASK_NUM (32) 6 | #define POOL_SIZE (32) 7 | 8 | // 必须是一个返回void类型的函数(线程池的任务规定的) 9 | void my_sqrt(void* pData) 10 | { 11 | float* p = (float*)(pData); 12 | 13 | *p = sqrt(*p); 14 | 15 | return; 16 | } 17 | 18 | 19 | int main(int argc, char* argv[]) 20 | { 21 | 22 | ThreadPool tp(POOL_SIZE); // 假设电脑上有32个逻辑核心(一般是16个PU,32个AS) 23 | 24 | float arr[TASK_NUM] = {0.0f}; 25 | 26 | printf("before thread pool processing...\n"); 27 | for(int i = 0; i < TASK_NUM; i++) { 28 | arr[i] = i; 29 | printf("arr[%d] = %f\n", i, arr[i]); 30 | } 31 | 32 | for(int i = 0; i < TASK_NUM; i ++) { 33 | tp.enqueue(my_sqrt, (void*)&arr[i]); 34 | } 35 | 36 | printf("after thread pool processing...\n"); 37 | for(int i = 0; i < TASK_NUM; i++) { 38 | printf("arr[%d] = %f\n", i, arr[i]); 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /U#0019-C++11线程池/thread_pool.cpp: -------------------------------------------------------------------------------- 1 | #include "thread_pool.h" 2 | 3 | void Worker::operator()() { 4 | while(!_pool->_stop) { 5 | std::unique_lock lock(_pool->_mutex); 6 | while(!_pool->_stop && _pool->_task_queue.empty()) { 7 | _pool->_condition.wait(lock); 8 | } 9 | if (_pool->_stop) { 10 | //lock.unlock(); 11 | return; 12 | } 13 | 14 | //get the first task in the queue 15 | std::function task = _pool->_task_queue.front(); 16 | _pool->_task_queue.pop(); 17 | _pool->_inprogress++; 18 | lock.unlock(); 19 | 20 | task(); //run the task 21 | 22 | //notify the task is finished - this is for the wait() function 23 | lock.lock(); 24 | _pool->_inprogress--; 25 | _pool->_condition.notify_all(); 26 | lock.unlock(); 27 | } 28 | } 29 | 30 | ThreadPool::ThreadPool(const size_t threadcount) 31 | : _inprogress(0), _stop(false) { 32 | for (size_t i = 0; i < threadcount; i++) { 33 | Worker wk (this); 34 | _workers.push_back(std::thread(wk)); 35 | } 36 | } 37 | 38 | ThreadPool::~ThreadPool() { 39 | std::unique_lock lock(_mutex); 40 | _stop = true; 41 | _condition.notify_all(); 42 | lock.unlock(); 43 | 44 | for (size_t i = 0; i < _workers.size(); i++) { 45 | _workers.at(i).join(); 46 | } 47 | } 48 | 49 | void ThreadPool::wait() { 50 | std::unique_lock lock(_mutex); 51 | while(!_stop && (!_task_queue.empty() || _inprogress != 0)) { 52 | _condition.wait(lock); 53 | } 54 | //unlock releases 55 | } 56 | -------------------------------------------------------------------------------- /U#0019-C++11线程池/thread_pool.h: -------------------------------------------------------------------------------- 1 | // 用C++11实现的一个简单线程池 2 | 3 | #ifndef _THREAD_POOL_H_ 4 | #define _THREAD_POOL_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include // std::packaged_task 11 | #include 12 | 13 | // 提前声明 14 | class ThreadPool; 15 | 16 | class Worker { 17 | public: 18 | Worker(ThreadPool* tp) : _pool(tp) {} 19 | void operator()(); 20 | 21 | private: 22 | ThreadPool* _pool; 23 | }; 24 | 25 | class ThreadPool { 26 | public: 27 | ThreadPool(const size_t threadcount); 28 | ~ThreadPool(); 29 | 30 | // &&是右值引用 31 | // 注意:模板函数必须写在头文件里面! 32 | template 33 | void enqueue(Func&& func, Args&& args) { 34 | //create a shared pointer to a task and then put a lambda that 35 | //executes that task in the queue 36 | using rettype = typename std::result_of::type; 37 | auto task = std::make_shared>( 38 | std::bind(std::forward(func), std::forward(args))); 39 | 40 | std::unique_lock lock (_mutex); 41 | _task_queue.push([task]() { (*task)(); } ); 42 | lock.unlock(); 43 | 44 | _condition.notify_one(); 45 | } 46 | 47 | void wait(); 48 | 49 | private: 50 | friend Worker; 51 | std::vector _workers; 52 | std::queue> _task_queue; 53 | size_t _inprogress; 54 | 55 | std::mutex _mutex; 56 | std::condition_variable _condition; 57 | 58 | bool _stop; 59 | }; 60 | 61 | #endif // _THREAD_POOL_H_ 62 | -------------------------------------------------------------------------------- /U#0020-把git_commit_sha1、OpenCV版本和当前编译时间编译到ELF中/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | execute_process( 4 | COMMAND bash "-c" "git log | head -n 1 | awk '{printf $2}'" 5 | OUTPUT_VARIABLE GIT_COMMIT 6 | ) 7 | 8 | add_definitions(-DGIT_COMMIT_SHA1="${GIT_COMMIT}") 9 | 10 | find_package(OpenCV REQUIRED) 11 | 12 | add_executable(main main.cpp) 13 | 14 | target_link_libraries(main ${OpenCV_LIBS}) 15 | -------------------------------------------------------------------------------- /U#0020-把git_commit_sha1、OpenCV版本和当前编译时间编译到ELF中/main.cpp: -------------------------------------------------------------------------------- 1 | #include "opencv2/opencv.hpp" 2 | 3 | // 参考资料:https://www.learnopencv.com/how-to-find-opencv-version-python-cpp/ 4 | // https://www.learnopencv.com/get-opencv-build-information-getbuildinformation/ 5 | // 编译方法:g++ getOpenCVInfo.cpp `pkg-config --libs --cflags opencv` 6 | // 7 | // 8 | 9 | #define VERSION_STRING "ELF v1.0.0, " __DATE__ ", " __TIME__ 10 | 11 | int main(int argc, char** argv) 12 | { 13 | // 打印ELF版本和当前编译时间 14 | std::cout << "Welcome to use " << VERSION_STRING << std::endl; 15 | 16 | // 打印git commit sha1信息 17 | printf("git_commit_sha1:\t%s\n", GIT_COMMIT_SHA1); 18 | 19 | // 打印OpenCV版本信息(从头文件中拿) 20 | std::cout << "OpenCV version : " << CV_VERSION << std::endl; 21 | std::cout << "Major version : " << CV_MAJOR_VERSION << std::endl; 22 | std::cout << "Minor version : " << CV_MINOR_VERSION << std::endl; 23 | std::cout << "Subminor version : " << CV_SUBMINOR_VERSION << std::endl; 24 | 25 | // 打印OpenCV编译信息(从库中拿) 26 | std::cout << cv::getBuildInformation() << std::endl; 27 | 28 | if (CV_MAJOR_VERSION < 3) { 29 | // Old OpenCV 2 code goes here. 30 | } else { 31 | // New OpenCV 3 code goes here. 32 | } 33 | 34 | return 0; 35 | } 36 | --------------------------------------------------------------------------------