今天要记录的是树图第二次作业的第二题,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. libtool: line 990: g++: command not found的解决

    yum -y install gcc+ gcc-c++

  2. spring3种配置的比较

    引用自:Spring 3.x 企业应用开发实战

  3. IOS 视频缩略图的生成

    使用AVFoundation框架可以生成视频缩略图,用到的类: >>AVAsset: 用于获取多媒体的相关信息,如多媒体的画面和声音等. >>AVURLAsset: AVAss ...

  4. Scala学习资源

    Scala学习资源: Scala官方网站:http://www.scala-lang.org/ Scala github:https://github.com/scala/scala Twitter ...

  5. MBP使用笔记

    1. 链接测试机命令: 登录:ssh ria@000.000.000.000 然后输入密码即可 退出:exit 2. SwitchySharp导入的是bak文件. 3. 使用goagentFQ的使用的 ...

  6. PowerShell添加或修改注册表开机启动项脚本

    代码如下: $name = Read-Host "请输入开机启动项的名字(随便起)" $value = Read-Host "请输入开机启动项的值" try{ ...

  7. Java程序的编码规范

    所有的程序开发手册都包含了各种规则.一些习惯自由程序人员可能对这些规则很不适应,但是在多个开发人员共同写作的情况下,这些规则是必需的.这不仅仅是为了开发效率来考虑,而且也是为了后期维护考虑. 一.命名 ...

  8. 在iOS中使用OpenSSL的Public Key 进行加密

    这几天一直潜心于iOS开发,刚好把遇到的问题都记录一下.这次遇到的问题就是如果根据得到的Public Key在iOS 客户端对用户名和密码进行加密. Public Key如下: -----BEGIN ...

  9. 第一、初识C语言

    1·C语言强大而灵活,如python,LISP,FORTRAN,Perl,Logo,BASIC,PASACAL的编译器和解释器都是C语言编写的. 2·C语言的指针错误往往难以察觉,但这恰好告诉我们,一 ...

  10. 插件开发--BE插件开发

    U9的插件主要分为3种,即(1)BE插件(2)UI插件(3)BP/SV插件 1.新建类库解决方案 2.新建插件类,并引用以下dll,UBF安装目录U9.VOB.Product.UBF\UBFStudi ...