今天要记录的是树图第二次作业的第二题,Image Patch Extraction。这个概念真的不难懂,但是如果要我实际写的话,还真的不知道要怎么去遍历图像矩阵来提取块。在此要多谢邓大神的热心帮助,告诉了我一个遍历的思路_(:з」∠)_

一开始我是从原图像矩阵来考虑循环的,也就是两层循环的边界分别是原图像的width和height。这样思考的话,我完全不知道应该如何移动这个patch。

之后思考了从得到的patch列表来考虑,也就两侧循环的边界分别是W-w+1和H-h+1(W是原图像的width,H是原图像的height,w和h分别是patch的宽度和高度),这样思考之后我依然卡住,虽然得到的patch列表是方便了,但是怎么样用这几个索引变量来定位到原图上的像素让我苦恼了很久。

请教过邓大神之后,得到一个确切可行的循环,大致如下:

 for(i : W-w+)
for(j : H-h+1)
for(ii : w)
for(jj : h)

跟第二次想到的是一样的思路,而因为这是确定正确的循环,所以思考的时候就不会怕自己出错。加上看过了他的java代码后,知道要定位到原图像素,可以直接用img.ptr<uchar>(i+ii)[j+jj]来定位,也就是二维坐标定位,指向的像素点坐标为(i+ii, j+jj)。觉得自己语言说不清楚,还是努力画个图来说明一下。
老是会把图像的存储模式定性为线性存储的习惯要好好改改了_(:з」∠)_

而提取出来的块存在一个三维定长数组中,patches[W-w+1][H-h+1][w*h],从左到右的下标表示在第几行、在第几列的矩阵中的哪个元素,所以准确来说每一个patch是用一个长度为w*h的一维数组存储的,所以访问元素的时候还是要按照线性的方法来,ii*w+jj。前面两个参数就是表示分解出来的矩阵的坐标了,组成这个矩阵的基本元素是一个w*h的数组。

一开始我是用三层vector的push_back来存patch,代码如下

     vector<vector<vector<uchar>>> patches;
for (int i = ; i < rows; i++) {
vector<vector<uchar>> pCols;
for (int j = ; j < cols; j++) {
vector<uchar> patch;
for (int ii = ; ii < h; ii++) {
for (int jj = ; jj < w; jj++) {
patch.push_back(img.ptr<uchar>(i+ii)[j+jj]);
}
}
pCols.push_back(patch);
}
patches.push_back(pCols);
}

结果发现,运行计算patches竟然要用三分多钟,听说一般一分钟都不用的时间,我跑出了这么长的时间也是吓快了_(:з」∠)_想了一下,应该是因为vector是动态分配的数组,而每一次进入新的循环都创建了新的vector,这部分费时让总时间变得那么长,所以就复习了一下如何用new分配定长的三维数组。

因为很少用到new来分配多维数组,所以在这里贴上分配空间的代码。基本思路,是先创建外围的数组,再创建内围的数组。

     uchar*** patches;
patches = new uchar** [rows];
for (int i = ; i < rows; i++) {
patches[i] = new uchar* [cols];
for (int j = ; j < cols; j++) {
patches[i][j] = new uchar [w * h];
}
}

之后的访问就直接用数组下标。运行之后,发现时间节省了很多,用时只需要30-40秒。所以应该还是每一个循环都创建了新的vector浪费了时间,如果在循环之前创建好三个vector,每一次处理完一行的块就清理掉重复利用,应该也会节省到这个时间段里。不过我认为还是定长的数组时间会少些,所以暂时不再实验vector的改进。

另外要注意的就是使用完数组后,需要进行delete操作,同样也是需要用两层循环来从内到外delete。

做完这个题目,感觉还是逻辑思维搞不清楚,虽然思考的时候有画例子比比划划,但是明明已经靠近结果了、却没办法凭一己之力到达终点,还是需要变换思维的角度,从多个角度去看问题。另外还要懂得将基础的知识扩展到实际应用中,比如说这一次的多维数组空间分配,竟然一开始还在疑惑为什么第二行的类型是uchar**……

还是不能把学过的东西丢掉啊。

以上内容参考了这几个博客,感谢他们的分享!

http://www.lewensky.cn/read.php/186.htm

http://pppboy.blog.163.com/blog/static/302037962010218103838998/

数字图像处理作业使用OpenCV - 块提取的更多相关文章

  1. 数字图像处理作业使用OpenCV - 使用笔记

    数字图像处理作业的输入图像全部都是灰度图像,所以汇总一下自己遇到的问题答案. OCV的图像容器是Mat<typename>,可以用imread(filename)读取图像,filename ...

  2. 数字图像处理作业使用OpenCV - 自定义直方图

    第二次作业需要打印出来灰度直方图,当然不能使用ocv的自带calcHist函数来得到Mat对象了……结果上网搜索怎么用自己的数据创建直方图,搜到的都是直接用函数的_(:з」∠)_ 结果这个地方拖了好久 ...

  3. 数字图像处理作业使用OpenCV - 配置

    使用环境:Windows7 旗舰版 + vs2008 + OpenCV2.0a 基本上配置都是通过网上一个教程,在此附上地址 Click ME. 为了避免因不同版本而出现的安装问题,我还是下载了2.0 ...

  4. Win8 Metro(C#)数字图像处理--2.65形态学轮廓提取算法

    原文:Win8 Metro(C#)数字图像处理--2.65形态学轮廓提取算法  [函数名称]   形态学轮廓提取函数       WriteableBitmap Morcontourextract ...

  5. Win8 Metro(C#)数字图像处理--2.40二值图像轮廓提取算法

    原文:Win8 Metro(C#)数字图像处理--2.40二值图像轮廓提取算法  [函数名称]   二值图像轮廓提取         ContourExtraction(WriteableBitm ...

  6. BJUT数字图像处理作业

    一. n的正方形图像,用FFT算法从空域变换到频域,并用频域图像的模来进行显示. 2) 使图像能量中心,对应到几何中心,并用频域图像的模来进行显示. 3)将频域图象,通过FFT逆变换到空域,并显示. ...

  7. Win8Metro(C#)数字图像处理--2.40二值图像轮廓提取

    http://dongtingyueh.blog.163.com/blog/static/4619453201271481335630/ [函数名称] 二值图像轮廓提取         Contour ...

  8. python数字图像处理(1):环境安装与配置

    一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因 ...

  9. FPGA与数字图像处理技术

    数字图像处理方法的重要性源于两个主要应用领域: 改善图像信息以便解释. 为存储.传输和表示而对图像数据进行处理,以便于机器自动理解. 图像处理(image processing): 用计算机对图像进行 ...

随机推荐

  1. python学习笔记之类class(第六天)

         参考文档:              1.金角大王博客:http://www.cnblogs.com/alex3714/articles/5188179.html               ...

  2. TurboDemo软件使用教程:视频编辑

    视频软件TurboDemo中不仅可以快速的捕捉屏幕,而且可以对视频进行编辑,本文来详细的了解一下这个步骤. 当你完整屏幕捕捉和录制后,点击系统托盘上的箭头或点击键盘上的“print screen”键之 ...

  3. 学习Linux系列--布署常用服务

    本系列文章记录了个人学习过程的点点滴滴. 回到目录 10.mediawiki 知名开源维基框架,我用来构建自己的知识库. 在mediawiki中新建一个http.conf文件 sudo vim /op ...

  4. git github简单知识

    Git 常用命令 git init here -- 创建本地仓库(repository),将会在文件夹下创建一个 .git 文件夹,.git 文件夹里存储了所有的版本信息.标记等内容 git remo ...

  5. js高级程序设计书中,有一句话在全局作用域中定义的函数实际上只 能被某个对象调用???

    js没有块级作用域(题外话:函数可以作为一个块级),所以我们经常使用闭包来模拟块级作用域,以避免变量或者函数因为名称相同而产生的冲突. 重点来了: 所以,如果我们把哪个变量或者函数放在全局作用域中,那 ...

  6. C4.5算法的学习笔记

    有日子没写博客了,这些天忙着一些杂七杂八的事情,直到某天,老师喊我好好把数据挖掘的算法搞一搞!于是便由再次埋头看起算法来!说起数据挖掘的算法,我想首先不得的不提起的就是大名鼎鼎的由决策树算法演化而来的 ...

  7. [翻译]lithium介绍

    什么是li3? 首创框架 li3 是第一个并且是唯一一个从PHP 5.3+建立起来的相当出色的php框架,而且破天荒的第一次引入全新技术,包括通过一组唯一,统一的api(接口)在关系型(relatio ...

  8. [模板] SAP

    int dfs(int x,int flow){ if(x==T) return flow; int tmp=res=0; for(int i=last[x];i;i=next[i]) if (d[x ...

  9. ubuntu各种应用安装

    微信安装,编译包下载,双击electronic-wechat就能用了,记得lock在launcher上 https://github.com/geeeeeeeeek/electronic-wechat ...

  10. 正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样...

    出错提示: 正尝试在 OS 加载程序锁内执行托管代码.不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起. 原因分析: .NET2.0中增加了42种非常强大的调试助手 ...