数字图像处理作业使用OpenCV - 块提取

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

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

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

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

1 for(i : W-w+1)
2    for(j : H-h+1)
3       for(ii : w)
4          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,代码如下

 1     vector<vector<vector<uchar>>> patches;
 2     for (int i = 0; i < rows; i++) {
 3         vector<vector<uchar>> pCols;
 4         for (int j = 0; j < cols; j++) {
 5             vector<uchar> patch;
 6             for (int ii = 0; ii < h; ii++) {
 7                 for (int jj = 0; jj < w; jj++) {
 8                     patch.push_back(img.ptr<uchar>(i+ii)[j+jj]);
 9                 }
10             }
11             pCols.push_back(patch);
12         }
13         patches.push_back(pCols);
14     }

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

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

1     uchar*** patches;
2     patches = new uchar** [rows];
3     for (int i = 0; i < rows; i++) {
4         patches[i] = new uchar* [cols];
5         for (int j = 0; j < cols; j++) {
6             patches[i][j] = new uchar [w * h];
7         }
8     }

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

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

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

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

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

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

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

时间: 2024-10-06 12:54:12

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

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

数字图像处理作业的输入图像全部都是灰度图像,所以汇总一下自己遇到的问题答案. OCV的图像容器是Mat<typename>,可以用imread(filename)读取图像,filename是c string,char*和const char*都行.灰度图像的typename是uchar,RGB图像的typename是Vec3b. Mat容器如果直接使用操作符赋值,只会复制一份信息头而不会复制包含数据的矩阵,由此而降低内存的浪费和速度,所以这样得到的多个Mat对象都指向同一个数据矩阵,换句话说,

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

第二次作业需要打印出来灰度直方图,当然不能使用ocv的自带calcHist函数来得到Mat对象了……结果上网搜索怎么用自己的数据创建直方图,搜到的都是直接用函数的_(:з」∠)_ 结果这个地方拖了好久呵呵呵呵呵呵呵.最后还是努力耐下性子来对照网上绘制灰度直方图的代码来看到底内藏什么玄机,结果发现其实真的,没什么,大不了(笑)(哭). 基本思路: 建立一个Mat对象作为直方图的画布,将256个灰度级的数值的直方用rectangle或者line一个一个画出来. ……简直简单到我无法想象_(:з」∠)

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

使用环境:Windows7 旗舰版 + vs2008 + OpenCV2.0a 基本上配置都是通过网上一个教程,在此附上地址 Click ME. 为了避免因不同版本而出现的安装问题,我还是下载了2.0版本的OCV,但是现在Win可用的最新版本都是2.4.10了,虽然2.3之后的版本都不在需要自己用CMAKE编译了,但一般网上教程都是配置的vs2010或以上版本. 至于还有搜到过vs2008配置OCV2.4.5的教程,也附上地址 Click ME,为什么不选择他是因为他没有图看着不那么清楚……比较

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

http://dongtingyueh.blog.163.com/blog/static/4619453201271481335630/ [函数名称] 二值图像轮廓提取         ContourExtraction(WriteableBitmap src) [算法说明] 二值图像的轮廓提取对于图像识别,图像分割有着重要意义.该算法的核心就是将图像目标的内部点消除.所谓内部点,我们要根据当前像素点的邻域来进行判断,假设邻域窗口为3*3窗口,如果当前像素P(x,y)的八个邻域像素满足如下条件,

哈工大深研院数字图像处理第二次大作业:水果自动识别(2)HSV空间聚类及SIFT算法目标识别

老规矩,直接贴报告~ Programe list: Programe was developed in the condition of Windows aswell as Linux server, programming language is Matlab (www.mathworks.com). Classify.m, Kmeans.m: function for K-means clustering. main_Kmeans.m: main function for K-means c

初始----python数字图像处理--:环境安装与配置

一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因此,我们这里使用python这个脚本语言来进行数字图像处理. 要使用python,必须先安装python,一般是2.7版本以上,不管是在windows系统,还是linux系统,安装都是非常简单的. 要使用python进行各种开发和科学计算,还需要安装对应的包.这和matlab非常相似,只是matla

【数字图像处理】七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行讲解,主要通过MFC单文档视图实现显示BMP图像增强处理,包括图像普通平滑.高斯平滑.不同算子的图像锐化知识.希望该篇文章对你有所帮助,尤其是初学者和学习图像处理的学生. [数字图像处理]一.MFC详解显示BMP格式图片 [数字图像处理]二.MFC单文档分割窗口显示图片 [数字图像处理]三.MFC实现图像灰度.采样和量化功能详解 [数字图像处理]四.MFC对话框绘制灰度直方图 [数字图像

OpenCV-跟我一起学数字图像处理之直方图均衡化

从这篇博文开始,小生正式从一个毫不相干专业转投数字图像处理.废话不多说了,talk is cheap. show me the code. 直方图均衡化目的 由于一些图像灰度的分布过于集中,这样会导致图像的层次不够分明,直方图均衡化就是为了让图像的灰度分布更均匀,图像的层次感更强. 数学原理 基于连续灰度分布的结论推导 直方图均衡化属于数字图像处理中灰度变换(intensity transformation)的内容,灰度变换的目的就是找到一个合适的映射函数s=T(r).将原图像的灰度值映射到新的

数字图像处理 简单介绍

 数字图像处理发展概况 数字图像处理发展概况数字图像处理(Digital Image Processing)又称为计算机图像处理,它是指将图像信号转换成数字信号并利用计算机对其进行处理的过程.数字图像处理最早出现于20世纪50年代,当时的电子计算机已经发展到一定水平,人们開始利用计算机来处理图形和图像信息.数字图像处理作为一门学科大约形成于20世纪60年代初期.早期的图像处理的目的是改善图像的质量,它以人为对象,以改善人的视觉效果为目的.图像处理中,输入的是质量低的图像,输出的是改善质量后的图像