基于HEP(histograms of equivalent patterns【1】)框架下的特征具有良好的纹理分类效果,LBP(local binary patterns【2】)属于HEP框架下最常用的特征,具有对亮度、旋转等良好的不变特性。在基于分块的视频烟雾检测中,常使用其作为纹理分类的特征。然而,分块的图像具有局部性。这篇文章主要提出使用图像金字塔的方法让提取的烟雾块特征具有一定的全局属性。它将待检测烟雾块构成3级的金字塔,再对金字塔每一级提取不同模式的LBP特征,构成一个直方图序列作为特征向量,最后采用神经网络分类。

1.LBP 与 LBPV

本文用到的LBP共三种模式:统一模式,旋转不变模式,统一的旋转不变模式。每一级金字塔采用一种模式。LBP详见博客【3】

LBPV与LBP不同的是,LBP统计直方图的时候是每一个LBP(i,j)使第k个分量加1,而LBPV是加一个VAR(方差吧),VAR计算公式:

上面gp为领域内像素值,然后再归一化。

2.金字塔

共三级金字塔,I0,I1,I2,I0为输入图像,I0通过高斯低通滤波(Gaussian low pass filter, LPF),然后下采样得到I1(采样大小2),同样由I1得到I2,如图:

最后从下到上对每一级分别提取统一模式LBP,旋转不变LBP,统一旋转不变LBP,按照如下的顺序组合成向量:

对于24x24的图像块,I2的大小仅为6x6,这样会获得稀疏的特征向量,不利于分类。因此,I1和I2通过相邻像素增大搜索窗口。如图:

3.实现

本人采用文章中的数据集作为训练与测试,剪切成96x96的灰度图,这样大小的图像下采样两次刚好24x24。提取每一张图像特征代码:

feature_t get_pyramid_feature(cv::Mat & img)
{
assert((img.dims == 2) && (img.rows == 96) && (img.cols == 96));
feature_t result, lbp0, lbp1, lbp2, lbpv0, lbpv1, lbpv2;
result.resize(210);
cv::Mat I0, I1, I2, L0, S0, L1; I0 = img(cv::Rect(36, 36, 24, 24)).clone();
cv::GaussianBlur(img, L0, cv::Size(3,3), 0);
cv::resize(L0, S0, cv::Size(48, 48));
I1 = S0(cv::Rect(12, 12, 24, 24)).clone();
cv::GaussianBlur(S0, L1, cv::Size(3,3), 0);
cv::resize(L1, I2, cv::Size(24, 24)); lbp0 = get_u_lbp_gray(I0);
lbp1 = get_ri_lbp_gray(I1);
lbp2 = get_riu_lbp_gray(I2);
lbpv0 = get_u_lbpv_gray(I0);
lbpv1 = get_ri_lbpv_gray(I1);
lbpv2 = get_riu_lbpv_gray(I2); std::copy(lbp0.begin(), lbp0.end(), result.begin());
std::copy(lbpv0.begin(), lbpv0.end(), result.begin()+59);
std::copy(lbp1.begin(), lbp1.end(), result.begin()+118);
std::copy(lbpv1.begin(), lbpv1.end(), result.begin()+154);
std::copy(lbp2.begin(), lbp2.end(), result.begin()+190);
std::copy(lbpv2.begin(), lbpv2.end(), result.begin()+200);
return result;
}

提取特征过后,采用神经网络训练(采样tiny_cnn这个轻量级的神经网络库):

void mlp_train(std::vector<feature_t> & train_x, std::vector<int> & train_y, std::vector<feature_t> & test_x, std::vector<int> & test_y, const char * weights_file, int iter_num = 20)
{
const int num_input = train_x[0].size();
const int num_hidden_units = 30;
int num_units[] = { num_input, num_hidden_units, 2 };
auto nn = make_mlp<mse, gradient_descent_levenberg_marquardt, tan_h>(num_units, num_units + 3); //train mlp
nn.optimizer().alpha = 0.005;
boost::progress_display disp(train_x.size());
boost::timer t;
// create callback
auto on_enumerate_epoch = [&](){
std::cout << t.elapsed() << "s elapsed." << std::endl;
tiny_cnn::result res = nn.test(test_x, test_y);
std::cout << nn.optimizer().alpha << "," << res.num_success << "/" << res.num_total << std::endl;
nn.optimizer().alpha *= 0.85; // decay learning rate
nn.optimizer().alpha = std::max(0.00001, nn.optimizer().alpha);
disp.restart(train_x.size());
t.restart();
};
auto on_enumerate_data = [&](){
++disp;
}; nn.train(train_x, train_y, 1, iter_num, on_enumerate_data, on_enumerate_epoch);
nn.test(test_x, test_y).print_detail(std::cout);
nn.save_weights(weights_file);
}

最后得到测试的结果96%以上。

然后用于视频的处理中,只用处理单幅图像的情况。对于一副图像,首先得分块,将每一个分块的区域保存到向量中。分块的时候就考虑到金字塔每一级,因此3级的每一个向量对应的位置是对应的一个块。对于边缘块的处理忽略图像外的像素。分块代码如下:

std::vector<std::vector<cv::Rect>> make_image_blocks(const cv::Mat &in, const int iWD)
{
std::vector<std::vector<cv::Rect>> result;
std::vector<cv::Rect> level0, level1, level2;
int rows = in.rows;
int cols = in.cols;
int rows_level1 = rows / 2;
int cols_level1 = cols / 2;
int rows_level2 = rows / 4;
int cols_level2 = cols / 4;
int left, top, right, bottom;
for(int i = 0; i <= rows - iWD; i += iWD)
{
for(int j = 0; j <= cols - iWD; j += iWD)
{
level0.push_back(cv::Rect(j, i, iWD, iWD));
//level1
left = std::max(j/2-6,0);
top = std::max(i/2-6,0);
right = std::min(j/2+18, cols_level1);
bottom = std::min(i/2+18, rows_level1);
level1.push_back(cv::Rect(left, top, right-left, bottom-top));
//level2
left = std::max(j/4-9,0);
top = std::max(i/4-9,0);
right = std::min(j/4+15, cols_level2);
bottom = std::min(i/4+15, rows_level2);
level2.push_back(cv::Rect(left, top, right-left, bottom-top));
}
}
result.push_back(level0);
result.push_back(level1);
result.push_back(level2);
return result;
}

然后就是对每一张图像的处理了,首先创建3级金字塔,然后按照上面得到的分块索引轻松得到每一块的特征,然后predict就完事了。

template<typename NN>
std::vector<int> single_image_smoke_detect(const cv::Mat & img, const std::vector<std::vector<cv::Rect>> & locate_list, const std::vector<int> smoke_block, NN & nn)
{
std::vector<int> result;
cv::Mat I1, I2, L0, L1;
cv::GaussianBlur(img, L0, cv::Size(3,3), 0);
cv::resize(L0, I1, cv::Size(img.cols/2, img.rows/2));
cv::GaussianBlur(I1, L1, cv::Size(3,3), 0);
cv::resize(L1, I2, cv::Size(I1.cols/2, I1.rows/2)); for(auto i : smoke_block)
{
cv::Mat block = img(locate_list[0][i]);
auto lbp0 = get_u_lbp_gray(block);
auto lbpv0 = get_u_lbpv_gray(block);
block = I1(locate_list[1][i]);
auto lbp1 = get_ri_lbp_gray(block);
auto lbpv1 = get_ri_lbpv_gray(block);
block = I2(locate_list[2][i]);
auto lbp2 = get_riu_lbp_gray(block);
auto lbpv2 = get_riu_lbpv_gray(block); feature_t feat;
feat.resize(210,0);
std::copy(lbp0.begin(), lbp0.end(), feat.begin());
std::copy(lbpv0.begin(), lbpv0.end(), feat.begin()+59);
std::copy(lbp1.begin(), lbp1.end(), feat.begin()+118);
std::copy(lbpv1.begin(), lbpv1.end(), feat.begin()+154);
std::copy(lbp2.begin(), lbp2.end(), feat.begin()+190);
std::copy(lbpv2.begin(), lbpv2.end(), feat.begin()+200); vec_t y;
nn.predict(feat, &y);
const int predicted = max_index(y);
if(predicted == 1)
result.push_back(i);
}
return result;
}

在这之前加入运动检测:

smoke_blocks = single_image_smoke_detect(gray_img, locate_list, smoke_blocks, nn);

然后将检测得到的烟雾块显示出来:

auto merged_blocks = merge_blocks(smoke_blocks, gray_img.size(), 24);
for(auto rect : merged_blocks)
{
cv::rectangle(img, rect, cv::Scalar(0,0,255));
} cv::imshow("smoke", img);

效果图:

1.实验结果分析

试了一下仅使用LBP或LBPV的情况下,单独使用LBPV的分类效果最差,多次测试平均94%多一点,而LBP和LBP+LBPV情况差不多,平均都在96%以上,因此,不加LBPV更好一点。

2.总结

加入金字塔对每一级提取特征的方法的确比单独采用分块提取特征的方法稍好一点,但是对于烟雾的检测,单帧的检测并不能满足于实际。这个可以作为一个novel方法用在一个框架中。

6.引用

【1】 Texture description through histograms of equivalent patterns

【2】  Multiresolution gray-scale and rotation invariant texture classification with local binary patterns

【3】  http://blog.csdn.net/zouxy09/article/details/7929531

@waring

烟雾检测笔记1--《Video-based smoke detection with histogram sequence of LBP and LBPV pyramids》解析、实现的更多相关文章

  1. paper 27 :图像/视觉显著性检测技术发展情况梳理(Saliency Detection、Visual Attention)

    1. 早期C. Koch与S. Ullman的研究工作. 他们提出了非常有影响力的生物启发模型. C. Koch and S. Ullman . Shifts in selective visual ...

  2. 个性探测综述阅读笔记——Recent trends in deep learning based personality detection

    目录 abstract 1. introduction 1.1 个性衡量方法 1.2 应用前景 1.3 伦理道德 2. Related works 3. Baseline methods 3.1 文本 ...

  3. 论文阅读笔记五十二:CornerNet-Lite: Efficient Keypoint Based Object Detection(CVPR2019)

    论文原址:https://arxiv.org/pdf/1904.08900.pdf github:https://github.com/princeton-vl/CornerNet-Lite 摘要 基 ...

  4. Tensorflow Object_Detection 目标检测 笔记

    Tensorflow models Code:https://github.com/tensorflow/models 编写时间:2017.7 记录在使用Object_Detection 中遇到的问题 ...

  5. 论文笔记: Deep Learning based Recommender System: A Survey and New Perspectives

    (聊两句,突然记起来以前一个学长说的看论文要能够把论文的亮点挖掘出来,合理的进行概括23333) 传统的推荐系统方法获取的user-item关系并不能获取其中非线性以及非平凡的信息,获取非线性以及非平 ...

  6. 谣言检测(ClaHi-GAT)《Rumor Detection on Twitter with Claim-Guided Hierarchical Graph Attention Networks》

    论文信息 论文标题:Rumor Detection on Twitter with Claim-Guided Hierarchical Graph Attention Networks论文作者:Erx ...

  7. 论文笔记--PCN:Real-Time Rotation-Invariant Face Detection with Progressive Calibration Networks

    关键词:rotation-invariant face detection, rotation-in-plane, coarse-to-fine 核心概括:该篇文章为中科院计算所智能信息处理重点实验室 ...

  8. 谣言检测(GACL)《Rumor Detection on Social Media with Graph Adversarial Contrastive Learning》

    论文信息 论文标题:Rumor Detection on Social Media with Graph AdversarialContrastive Learning论文作者:Tiening Sun ...

  9. 谣言检测(RDEA)《Rumor Detection on Social Media with Event Augmentations》

    论文信息 论文标题:Rumor Detection on Social Media with Event Augmentations论文作者:Zhenyu He, Ce Li, Fan Zhou, Y ...

随机推荐

  1. MyBatis映射文件的resultMap如何做表关联

    MyBatis的核心是其映射文件,SqlMap文件,里面配置了项目中用到了什么SQL语句,和数据库相关的逻辑都在这个映射文件里.顾名思义,映射文件就是对Java对象和SQL的映射.这里简单介绍一下映射 ...

  2. ASP.NET 实现PDF文件下载

    本文介绍了一种在ASP.NET中下载文件的方法. 方法一:可能是最简单的.最短的方式: Response.ContentType = "application/pdf"; Resp ...

  3. 【技术文档】《算法设计与分析导论》R.C.T.Lee等·第7章 动态规划

    由于种种原因(看这一章间隔的时间太长,弄不清动态规划.分治.递归是什么关系),导致这章内容看了三遍才基本看懂动态规划是什么.动态规划适合解决可分阶段的组合优化问题,但它又不同于贪心算法,动态规划所解决 ...

  4. android AsyncTask 详细例子(2)

    超时处理 001 import java.util.Timer; 002 import java.util.TimerTask; 003   004 import android.app.Activi ...

  5. Samba通过ad域进行认证并限制空间大小《转载》

    本文实现了samba服务被访问的时候通过windows域服务器进行用户名和密码验证;认证通过的用户可以自动分配500M的共享空间;在用户通过windows域登陆系统的时候可以自动把这块空间映射成一块硬 ...

  6. IE6,IE7下滚动条没有生效解决方法

    需要加个相对定位 position:relative;

  7. (转)jQuery插件开发模式

    要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...

  8. js 计算某年某周日期范围

    <HTML><HEAD><script type="text/javascript"> //目前只判断了4位有效输入的年份,//日期输出格式已处 ...

  9. poj1562 DFS入门

    K - 搜索 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:10000KB     64bit I ...

  10. 《转载》深入理解 cocos2d-x 坐标系

    原文地址:http://www.cnblogs.com/lyout/p/3292702.html. 首先我们添加两个测试精灵(宽:27,高:40)到场景里面: CCSprite *sprite1 = ...