1 前言

Caffe对于像我这样的初学者来说是一款非常容易上手的深度学习框架。关于用Caffe跑自己的数据这样的博客已经非常多,感谢前辈们为我们提供的这么好的学习资源。这里我主要结合我所在的行业,说下如何对跑通具有多通道多格式的遥感数据。

2 数据准备

Caffe封装的非常好,要想将我们的数据运用于Caffe上,我们唯一要做的工作就是准备好Caffe支持的数据输入格式(leveldb/lmdb)。

Caffe解决方案下有一个工程convert_imageset为我们提供了接口,主要是将图像文件转化为 Caffe支持的两种数据格式。工程实现数据格式转换主要经过以下几个步骤:

在细读这个工程文件是会发现,其数据读取函数用的是OpenCV 的imread函数,在io.cpp。关于OpenCV的imread函数,这里不做详细介绍,只说出其存在的问题:

1 对于图像文件,imread不能读取多波段数据(遥感图像),超过4个波段的;

2 读取的数据格式默认是CV_8UC(n),遥感数据明显不符合要求。

因此,要想通过Caffe自带的数据集转换接口将多波段多数据类型的遥感图像输出为Caffe支持的leveldb和lmdb格式存在明显的不合理问题。

关于遥感图像的读取,我想大家第一反应就是GDAL库。因此,我尝试在Caffe的解决方案下重写数据转换接口,利用GDAL库来读图像,并将读取的数据转换为OpenCV的Mat数据格式,从而和图1中流程的第二步接轨(GDAL数据读取转换为Mat格式可参看前面的博客)。但是后来一想,感觉这样做有点多余,为啥不通过GDAL读取的数据直接写入到Caffe::Datum中呢。

后来仔细看了Caffe::Datum类,发现其存储数据目前只支持uchar和float,如果读者愿意,我想还可以给Datum类添加其他的支持数据格式。但是,我觉得float格式已经满足我的要求了。因此,我写了一个简单的函数,实现从GDAL读取的数据到Datum的转化,其代码如下:

 bool ReadImageToDatum(const std::string &imgfilename,
const int label,
Datum &datum)
{
GDALAllRegister();
GDALDataset *poRemoteSensingImageDS = (GDALDataset*)GDALOpen(imgfilename.c_str(),GA_ReadOnly);
datum.set_channels(kRemoteSensingBandNums);
datum.set_height(kRemoteSensingSize);
datum.set_width(kRemoteSensingSize);
datum.set_label(label);
datum.clear_data();
datum.clear_float_data();
datum.set_encoded(false);
int *data = new int[kRemoteSensingImageNBytes];
int *pBandMap = new int[kRemoteSensingBandNums];
for (int b = ; b < kRemoteSensingBandNums; b++){
pBandMap[b] = b + ;
}
GDALDataType ty = poRemoteSensingImageDS->GetRasterBand()->GetRasterDataType();
poRemoteSensingImageDS->RasterIO(GF_Read, , , kRemoteSensingSize, kRemoteSensingSize,
data, kRemoteSensingSize, kRemoteSensingSize, ty, kRemoteSensingBandNums,
pBandMap, sizeof(int), kRemoteSensingSize*sizeof(int),
kRemoteSensingSize*kRemoteSensingSize*sizeof(int));
for (int i = ; i < kRemoteSensingImageNBytes; i++){
datum.add_float_data((float)data[i]);
}
delete[]data; data = nullptr;
delete[]pBandMap; pBandMap = nullptr;
GDALClose((GDALDatasetH)poRemoteSensingImageDS);
return ;
};

这里有个细节问题需要说下:因为我不大算动图1第三步中的Caffe::Datum--》leveldb/lmdb这个过程,所以GDAL读取的数据顺序需要与Mat中图像的存储格式一样。Mat默认数据存储格式是:BIP,及按像元保存,即先保存第一个波段的第一个像元,之后保存第二波段的第一个像元,依次保存存储。因此,在用GDAL读取图像的时候也应该用BIP格式读取,确保一致。到此遥感数据集的转换工作基本完成。我们可以将具有多波段和多数据类型的遥感数据顺利的保存为leveldb或者lmdb。我想其他的数据类型也可参考类似的方法。可以自己制作一个统一的二进制文件格式,然后轻松实现转换。

3 均值计算

这一步没有需要改动的地方,compute_image_mean 工程提供的接口完全可以支持之前Datum中的uchar和float两种数据格式。

     if (data.size() != ) {
CHECK_EQ(data.size(), size_in_datum);
for (int i = ; i < size_in_datum; ++i) {
sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]);
}
} else {
CHECK_EQ(datum.float_data_size(), size_in_datum);
for (int i = ; i < size_in_datum; ++i) {
sum_blob.set_data(i, sum_blob.data(i) +
static_cast<float>(datum.float_data(i)));
}
}

4 模型训练

这个过程也没有需要改动的,设置好网络参数,利用Caffe.exe提供的接口就可以顺利的完成模型的训练工作。

5 分类

分类同样存在之前数据准备中出现的问题,因此,还是要重写classification工程,主要在于图像的读取部分,并将用GDAL读取的数据,转化为Mat的多通道数据。具体不说了,上传部分代码供大家参考:

            float *readPatchImage = new float[kRemoteSensingSize*kRemoteSensingSize*bandNums];
int leftX = colIndex - constWidth;
if (leftX + kRemoteSensingSize > width) leftX = width - kRemoteSensingSize - ;
poRemoteSensingImageDS->RasterIO(GF_Read, leftX, leftY, kRemoteSensingSize, kRemoteSensingSize,
readPatchImage, kRemoteSensingSize, kRemoteSensingSize, GDT_Float32, bandNums,
pBandMap, bandNums*sizeof(float), bandNums*kRemoteSensingSize*sizeof(float),sizeof(float));
cv::Mat img = cv::Mat(kRemoteSensingSize, kRemoteSensingSize, CV_32FC(bandNums), readPatchImage);
std::vector<Prediction> predictions = classifier.Classify(img);
if (predictions[].first == "")
{
std::cout << "-----Find Suspicious Chinmey: Probability:" << predictions[].second << std::endl;
std::cout << " Position:leftX:" << leftX << " leftY:" << leftY << std::endl;
std::cout << std::endl;
unsigned char* buf = new unsigned char[kRemoteSensingSize*kRemoteSensingSize];
int i = ;
while (i < kRemoteSensingSize*kRemoteSensingSize)
buf[i++] = ;
poOutBand->RasterIO(GF_Write, leftX, leftY, kRemoteSensingSize, kRemoteSensingSize, buf,
kRemoteSensingSize, kRemoteSensingSize, GDT_Byte, , );
delete[]buf; buf = nullptr; }
delete[]readPatchImage; readPatchImage = nullptr;
}

Windows下用Caffe跑自己的数据(遥感影像)的更多相关文章

  1. windows下检验caffe是否配置正确

    windows下检验caffe是否配置正确:(注:不考虑搭建caffe的编译环境,而是直接使用caffe官网提供的二进制文件) windows版本源码以及二进制库文件下载地址:https://gith ...

  2. EOFError: Compressed file ended before the end-of-stream marker was reached解决办法(在Windows下查看已下载的MNIST数据文件)

    出现这个问题的原因是因为文件下载到一半就中断了,解决办法是删除datasets中下载到一半的数据包. 下面以我遇到的问题为例: 我下载数据下载到最后一个包就没有反应了,于是我强制终止了运行,可能是因为 ...

  3. 用caffe跑自己的数据,基于WINDOWS的caffe

    本文详细介绍,如何用caffe跑自己的图像数据用于分类. 1 首先需要安装过程见 http://www.cnblogs.com/love6tao/p/5706830.html 同时依据上面教程,生成了 ...

  4. 实践详细篇-Windows下使用Caffe训练自己的Caffemodel数据集并进行图像分类

    三:使用Caffe训练Caffemodel并进行图像分类 上一篇记录的是如何使用别人训练好的MNIST数据做训练测试.上手操作一边后大致了解了配置文件属性.这一篇记录如何使用自己准备的图片素材做图像分 ...

  5. windows下配置caffe(环境:win7+vs2013+opencv3.0)

    说明:大部分转载于initialneil的大作Caffe + vs2013 + OpenCV in Windows Tutorial (I) – Setup 准备工作: 1.下载CUDA7.5: ht ...

  6. windows下使用ofstream默认输出内存数据到文件中时,会自动将0A换成0A0D

    0A即\n,而0D是\r,windows下换行是\n\r,因此会自动转换. 但是,这样会带来很大的问题,导致由内存写入文件中的数据和内存中不一样,还不知道是什么原因造成的. 特别是将从网络接收来的pn ...

  7. Windows下VS2013+Caffe无GPU配置

    Windows版本的caffe工具包下载地址: 点击打开链接 1. 将下载的caffe-master.zip解压到 D:\Software\Caffe 文件夹下,把 D:\Software\Caffe ...

  8. windows下编译caffe报错:error MSB4062: 未能从程序集 E:\NugetPackages\OpenCV.2.4.10\......的解决办法

    参考博客:http://blog.csdn.net/u013277656/article/details/75040459 在windows上编译caffe时,用vs打开后会自动加载还原NugetPa ...

  9. flink入门实例-Windows下本地模式跑SocketWordCount

    一般情况下,开发大数据处理程序,我们希望能够在本地编写代码并调试通过,能够在本地进行数据测试,然后在生产环境去跑“大”数据. 一.nc工具 配置windows的nc端口,在网上下载nc.exe(htt ...

随机推荐

  1. Windows服务器之间rsync同步文件

    两台windows7机器 server:192.168.12.104 client:192.168.12.103 目的:将server上的E盘的目录FYFR里面的内容定时同步到client上的D盘下F ...

  2. SQL Server 2008 查询所有用户表

    SQL Server 2008 查询所有用户表的T-SQL语句是: SELECT * FROM sysobjects WHERE [xtype] = 'U' 或者是: SELECT * FROM sy ...

  3. 使用 ADD-ON SDK 开发 基于 Html JQuery 和 CSS 的 firefox 插件入门教程1: 创建一个简单的 Add-on

    [本文转载自http://sixpoint.me/942/implementing-simple-addon/] 实现一个简单的插件 教程的这个部分带你使用 SDK 来实现, 运行并打包一个插件. 这 ...

  4. wamp目录索引图片不显示

    在wampserver安装目录下  \bin\apache\Apache2.2.21\conf\extra\httpd-autoindex.conf Alias /icons/ "c:/Ap ...

  5. MySQL新建用户,授权,删除用户,修改密码总结

    首先要声明一下:一般情况下,修改MySQL密码,授权,是需要有mysql里的root权限的. 注:本操作是在WIN命令提示符下,phpMyAdmin同样适用. 用户:rdingcn 用户数据库:rdi ...

  6. 细说PHP优化那些事

    我们在用PHP编程的时候,总是想要使自己的程序占用资源最小,运行速度更快,代码量更少.往往我们在追求这些的同时却失去了很多东西.下面我想讲讲我对PHP优化的理解.优化的目的是花最少的代价换来最快的运行 ...

  7. 淘宝接口实现ip归属地查询

    <?php header('content-type:text/html;charset=utf-8'); /*获取当前ip归属地 调用淘宝接口 */ function get_ip_place ...

  8. python命令行运行在win和Linux系统的不同

    今天,在完成一个小的python习题,习题的主要内容是读取一个帮助模块,并保存到本地文件. 知道是用pydoc进行模块的读取,但是在windows系统下,调用os模块之后,结果总是为空. 核心语句: ...

  9. 003-C运算符

    运算符 C语言有34种运算符,常见的有加减乘除. 1>算术运算符 1.加 10+2 2.减 20-2 3.乘 12*2 4.除 10/2 5.取余 10%3 = 1; 10%-3 = 1; -1 ...

  10. oracle数据泵之解决方案(用户)导入导出。

    看到网上有这样的介绍而且很多,但觉得都是大神才能一下子看的懂.自己总结下菜鸟能看懂的. 1.导出. 首先第一步: 操作系统—开始—运行输入“cmd”进入dos界面输入“sqlplus/nolog”按回 ...