pytorch统计模型计算量和参数量

利用thop库中的profile函数,可以实现统计pytorch模型的计算量和参数量。

import torch
from thop import profile

net = Net()     #net为pytorch的网络模型
input_ = torch.rand((1,2,512,512))  #随机初始化一个向量,用于网络输入
flops, params = profile(net, inputs = (input_,)) #得到计算量和参数量

ubuntu 挂载硬盘

添加全新的硬盘(未分区)到Ubuntu当中。

先查看硬盘信息sudo fdisk -lu。找到新加的硬盘,比如是/dev/sdc

然后对该硬盘进行分区。fdisk /dev/sdc 输入m查看帮助,输入n进行分区。查看新增分区fdisk -l

然后对硬盘进行格式化 mkfs.ext4 /dev/sdc1

使用lsblk查看硬盘的挂载情况

挂载。一般是挂载再/mnt目录下。新建挂载文件夹/mnt/c, 然后挂载mount /dev/sdc1 /mnt/c。

配置开机自动挂载。 vim /etc/fstab 添加一行

/dev/sdc1(磁盘分区) /mnt/c(挂载目录) ext4(文件格式)defaults 0 0

ubuntu 安装显卡驱动

刚刚装了ubuntu18.04的系统,没有显卡驱动,使用ubuntu自带的软件仓库中提供的驱动进行安装。首先输入:ubuntu-drivers devices ,可以看到显卡的信息和一些 驱动版本,其中有一个是推荐安装版本。我的推荐安装版本是450 。 也可以先添加 PPA 软件仓库:sudo add-apt-repository ppa:graphics-drivers/ppa,然后apt update更新仓库,再进行上一步操作

如果同意安装推荐版本,只需要终端输入:sudo ubuntu-drivers autoinstall 就可以自动安装了

或者sudo apt install nvidia-driver-455 (使用官方源,我换成清华源装不了)

禁用nouveau (自带的显卡驱动)

创建文件 sudo vim /etc/modprobe.d/blacklist-nouveau.conf
添加如下内容:
blacklist nouveau
options nouveau modeset=0
再更新一下
sudo update-initramfs -u

Linux 终端快捷键

CTRL+ALT+T 打开终端
Ctrl+a 光标移动到开始位置
Ctrl+e 光标移动到最末尾
Ctrl+k 删除此处至末尾的所有内容
Ctrl+u 删除此处至开始的所有内容
Ctrl+d 删除当前字符
Ctrl+h 删除当前字符前一个字符
Ctrl+w 删除此处到左边的单词
Ctrl+y 粘贴由Ctrl+u, Ctrl+d, Ctrl+w删除的单词
Ctrl+l 相当于clear,即清屏
Ctrl+r 查找历史命令
Ctrl+b 向回移动光标
Ctrl+f 向前移动光标
Ctrl+t 将光标位置的字符和前一个字符进行位置交换
Ctrl+& 恢复 ctrl+h 或者 ctrl+d 或者 ctrl+w 删除的内容
Ctrl+S 暂停屏幕输出
Ctrl+Q 继续屏幕输出
Ctrl+Left-Arrow 光标移动到上一个单词的词首
Ctrl+Right-Arrow 光标移动到下一个单词的词尾
Ctrl+p 向上显示缓存命令
Ctrl+n 向下显示缓存命令
Ctrl+d 关闭终端
Ctrl+xx 在EOL和当前光标位置移动
Ctrl+x@ 显示可能hostname补全
Ctrl+c 终止进程/命令
Shift+上或下 终端上下滚动
Shift+PgUp/PgDn 终端上下翻页滚动
Ctrl+Shift+n 新终端
alt+F2 输入gnome-terminal打开终端
Shift+Ctrl+T 打开新的标签页
Shift+Ctrl+W 关闭标签页
Shift+Ctrl+C 复制
Shift+Ctrl+V 粘贴
Alt+数字 切换至对应的标签页
Shift+Ctrl+N 打开新的终端窗口
Shift+Ctrl+Q 管壁终端窗口
Shift+Ctrl+PgUp/PgDn 左移右移标签页
Ctrl+PgUp/PgDn 切换标签页
F1 打开帮助指南
F10 激活菜单栏
F11 全屏切换

Alt+F 打开 “文件” 菜单(file)
Alt+E 打开 “编辑” 菜单(edit)
Alt+V 打开 “查看” 菜单(view)
Alt+S 打开 “搜索” 菜单(search)
Alt+T 打开 “终端” 菜单(terminal)
Alt+H 打开 “帮助” 菜单(help)

linux 下载命令axel

最常用的下载命令是wget,但是经常速度会比较慢。而axel尝试通过对一个文件使用多个连接来改进下载过程 ,实测比wget快很多

# 安装axel
sudo apt install axel

使用方式:

axel 下载链接

设置下载连接数–num-connections=x,设置最大连接数为x,设置大一些可以增加下载速度

vs 运行opencv的sample

opencv提供的源码里提供了很多的sample供我们学习。现在用vs跑一下其中的c++的sample代码,方便以后学习opencv和c++

为了方便起见,我下载的opencv是3.3.1的windows的安装包,而没有从源码进行编译。安装包打开后会自动解压到指定位置。该安装包中包含了源码和已经编译好的库。打开opencv的根目录,可以看到两个文件夹,build和sources,其中build中为已经编译好的库,而sources中为源码。打开sources,可以看到很多文件夹,其中modules为opencv的核心源码。3rdparty中为一些第三方库的源码。而samples中则是包含的opencv的示例代码,我们要演示的就是其中cpp文件夹下,tutorial_code中的HighGUI。它是一个具有UI的,可以调整图片对比度和亮度的示例。

打开vs,选择文件——新建——从现有代码创建项目,选择Visual C++,下一步,项目文件位置找到之前所述的HighGUI文件夹,然后输入一个项目名称,例如highgui,然后一直下一步,完成。vs会创建项目的解决方案。该文件夹下包含两个cpp文件,每个文件都有main函数。因此我们选择其中一个运行。选择BasicLinearTransformsTrackbar.cpp,需要在解决方案资源管理器中,右键另一个cpp文件AddingImagesTrackbar,从项目中排除。然后打开Basic LinearTransformsTrackbar.cpp 文件,可以看到有很多红色波浪线。因为还没对项目进行配置。选择项目-属性,默认的配置是Debug,win32 ,由于所提供的库只有x64的,因此这里要选择x64 。注意运行时也要改成x64。

选择c/c++,常规,在附加包含目录中,添加所需的头文件的目录。这里添加build目录下的include,include\opencv,include\opencv2。然后选择链接器,常规,附加库目录中,选择所需的lib库的目录,这里添加build目录下x86\vc14\lib。然后选择链接器,输入,附加依赖项,添加该目录下的lib文件。我这里是opencv_world331.lib和opencv_world331d.lib 。最后选择调试,在环境中,添加运行时所需dll的目录,这里的添加方式为Path=(opencv根目录)\build\x64\vc14\bin。然后工作目录,为上两级文件夹。(根据代码中读取图片../data/lena.jpg可以判断)

配置完成后点击应用就可以了。然后就可以点击F5运行。注意运行前配置管理器要改成x64。我们可以配置release版的,步骤与上述相同。运行成功后可以在release文件夹下找到exe文件。将该exe文件,还有运行需要的dll、一些资源文件拷贝到独立的文件夹,就可以当作独立的软件发布了。

在jni函数中使用传入的bitmap

在AS中,有时会要传递bitmap给c++函数,使用opencv等工具进行处理。这时会将bitmap传递给jni函数。bitmap在jni的函数参数中,是jobject类型。下面介绍如何将传入的bitmap转化成opencv常用的mat类型,从而进行处理

首先要包含bitmap的头文件<android/bitmap.h>。这个头文件中定义了一些重要信息。了解这些信息非常必要

AndroidBitmapInfo 一个包含bitmap常用信息的结构体

/** Bitmap info, see AndroidBitmap_getInfo(). */
typedef struct {
/** The bitmap width in pixels. */
uint32_t width;
/** The bitmap height in pixels. */
uint32_t height;
/** The number of byte per row. */
uint32_t stride;
/** The bitmap pixel format. See {@link AndroidBitmapFormat} */
int32_t format;
/** Unused. */
uint32_t flags; // 0 for now
} AndroidBitmapInfo;

AndroidBitmapFormat 图片格式的枚举类型。格式为图片的像素位数。最常见的是ANDROID_BITMAP_FORMAT_RGBA_8888

/** Bitmap pixel format. */
enum AndroidBitmapFormat {
/** No format. */
ANDROID_BITMAP_FORMAT_NONE = 0,
/** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
/** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
ANDROID_BITMAP_FORMAT_RGB_565 = 4,
/** Deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead. **/
ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
/** Alpha: 8 bits. */
ANDROID_BITMAP_FORMAT_A_8 = 8,
};

AndroidBitmap_getInfo 获取bitmap信息的函数。返回值为后面的枚举类型。成功读取的返回值为0

/**
* Given a java bitmap object, fill out the AndroidBitmapInfo struct for it.
* If the call fails, the info parameter will be ignored.
*/
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info);
/** AndroidBitmap functions result code. */
enum {
/** Operation was successful. */
ANDROID_BITMAP_RESULT_SUCCESS = 0,
/** Bad parameter. */
ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1,
/** JNI exception occured. */
ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2,
/** Allocation failed. */
ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3,
};

AndroidBitmap_lockPixels 非常关键的一个函数。将bitmap的像素在内存中的地址进行锁定,确保这一块内存不会被移动。传入的addrPtr是一个二级指针,*addPtr是指向bitmap像素地址的指针。该函数正确调用后,一定要在该像素地址指针不再使用后,使用AndroidBitmap_unlockPixels进行释放。

/**
* Given a java bitmap object, attempt to lock the pixel address.
* Locking will ensure that the memory for the pixels will not move
* until the unlockPixels call, and ensure that, if the pixels had been
* previously purged, they will have been restored.
*
* If this call succeeds, it must be balanced by a call to
* AndroidBitmap_unlockPixels, after which time the address of the pixels should
* no longer be used.
*
* If this succeeds, *addrPtr will be set to the pixel address. If the call
* fails, addrPtr will be ignored.
*/
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);

AndroidBitmap_unlockPixels

/**
* Call this to balance a successful call to AndroidBitmap_lockPixels.
*/
int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);

了解以上信息之后,就可以探索如何将传入的bitmap转为需要的mat了。通用的做法是先获取bitmap的信息

AndroidBitmapInfo img_info;
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &img_info) >= 0);
CV_Assert(img_info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);

使用CV_Assert确保获取信息成功

然后初始化一个指针,并将该指针的地址传递给AndroidBitmap_lockPixels,若成功则该指针即指向bitmap的像素在内存中的地址

void *ori_img_pxl = NULL;
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &ori_img_pxl) >= 0);
CV_Assert(ori_img_pxl);

然后就可以将该指针传递给mat的构造函数,创建出我们需要的mat了。

Mat ori_img_mat(img_info.height, img_info.width, CV_8UC4, ori_img_pxl);

需要注意得到的mat的数据指针是指向bitmap的像素内存的,因此mat中对像素的操作会直接反映在bitmap中

AndroidBitmap_unlockPixels(env, bitmap);

最后要记得释放锁定!