学习opencv 第六章 习题十三
2015-11-01 00:54
316 查看
用傅里叶变换加速卷积,直接上代码,Mat版是Copy他人的。
CvMat版
Mat版
CvMat版
#include "stdafx.h" #include "cv.h" #include "highgui.h" #include <iostream> using namespace cv; using namespace std; void speedy_convolution(const CvMat* A,const CvMat* B,CvMat* C); int main() { IplImage* img=cvLoadImage("C:/Users/shark/Desktop/fruits.jpg",0); CvMat* src=cvCreateMat(img->height,img->width,CV_32FC1); /*int data; for(int i=0;i<img->height;i++) { for(int j=0;j<img->width;j++) { data=img->imageData[i*img->widthStep+j]; cvmSet(src,i,j,data); } }*/ //必须归一化矩阵的值为0-1之间(缩放比例在1/255.0附近效果最好,太小最后会全黑,接近1或大于1几乎是全白; //(还未深入了解函数cvConvertScale的机理),缩放比例不能为1,打出目标图像的像素有正有负 cvConvertScale(img,src,1/255.0,0); CvMat* kernel=cvCreateMat(3,3,CV_32FC1); cvSetReal2D(kernel,0,0,1.0/16); cvSetReal2D(kernel,0,1,2.0/16); cvSetReal2D(kernel,0,2,1.0/16); //注意设置值时必须加个.0否则1/16的值0 cvSetReal2D(kernel,1,0,2.0/16); cvSetReal2D(kernel,1,1,4.0/16); cvSetReal2D(kernel,1,2,2.0/16); cvSetReal2D(kernel,2,0,1.0/16); cvSetReal2D(kernel,2,1,2.0/16); cvSetReal2D(kernel,2,2,1.0/16); CvMat* C=cvCreateMat((src->rows+kernel->rows-1),(src->cols+kernel->cols-1),src->type); speedy_convolution(src,kernel,C); IplImage* img_src=cvCreateImage(cvGetSize(src),IPL_DEPTH_32F,1); cvGetImage(src,img_src); IplImage* img_dst=cvCreateImage(cvGetSize(C),IPL_DEPTH_32F,1); cvGetImage(C,img_dst); cvNamedWindow("img_src"); cvShowImage("img_src",img_src); cvNamedWindow("img"); cvShowImage("img",img); cvNamedWindow("dst"); cvShowImage("dst",img_dst); cvWaitKey(); return 0; } void speedy_convolution( const CvMat* A, const CvMat* B, CvMat* C ){ int dft_M=cvGetOptimalDFTSize(A->rows+B->rows-1); int dft_N=cvGetOptimalDFTSize(A->cols+B->cols-1); CvMat *dft_A=cvCreateMat(dft_M,dft_N,A->type); CvMat *dft_B=cvCreateMat(dft_M,dft_N,B->type); CvMat tmp; cvGetSubRect(dft_A,&tmp,cvRect(0,0,A->cols,A->rows)); cvCopy(A,&tmp); cvGetSubRect(dft_A,&tmp,cvRect(A->cols,0,dft_A->cols-A->cols,A->rows)); cvZero(&tmp); cvDFT(dft_A,dft_A,CV_DXT_FORWARD,A->rows); cvGetSubRect(dft_B,&tmp,cvRect(0,0,B->cols,B->rows)); cvCopy(B,&tmp); cvGetSubRect(dft_B,&tmp,cvRect(B->cols,0,dft_B->cols-B->cols,B->rows)); cvZero(&tmp); cvDFT(dft_B,dft_B,CV_DXT_FORWARD,B->rows); cvMulSpectrums(dft_A,dft_B,dft_A,0); cvDFT(dft_A,dft_A,CV_DXT_INV_SCALE,C->rows); cvGetSubRect(dft_A,&tmp,cvRect(0,0,C->cols,C->rows)); cvCopy(&tmp,C); cvReleaseMat(&dft_A); cvReleaseMat(&dft_B); }
Mat版
#include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> using namespace cv; using namespace std; //http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#dft[2] void convolveDFT(Mat A, Mat B, Mat& C) { // reallocate the output array if needed C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type()); Size dftSize; // calculate the size of DFT transform dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1); dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1); // allocate temporary buffers and initialize them with 0's Mat tempA(dftSize, A.type(), Scalar::all(0)); Mat tempB(dftSize, B.type(), Scalar::all(0)); // copy A and B to the top-left corners of tempA and tempB, respectively Mat roiA(tempA, Rect(0,0,A.cols,A.rows)); A.copyTo(roiA); Mat roiB(tempB, Rect(0,0,B.cols,B.rows)); B.copyTo(roiB); // now transform the padded A & B in-place; // use "nonzeroRows" hint for faster processing dft(tempA, tempA, 0, A.rows); dft(tempB, tempB, 0, B.rows); // multiply the spectrums; // the function handles packed spectrum representations well mulSpectrums(tempA, tempB, tempA, DFT_COMPLEX_OUTPUT); //mulSpectrums(tempA, tempB, tempA, DFT_REAL_OUTPUT); // transform the product back from the frequency domain. // Even though all the result rows will be non-zero, // you need only the first C.rows of them, and thus you // pass nonzeroRows == C.rows dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows); // now copy the result back to C. tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C); // all the temporary buffers will be deallocated automatically } int main(int argc, char* argv[]) { const char* filename = argc >=2 ? argv[1] : "Lenna.png"; Mat I = imread(filename, CV_LOAD_IMAGE_GRAYSCALE); if( I.empty()) return -1; Mat kernel = (Mat_<float>(3,3) << 1, 1, 1, 1, 1, 1, 1, 1, 1); cout << kernel; Mat floatI = Mat_<float>(I);// change image type into float Mat filteredI; convolveDFT(floatI, kernel, filteredI); normalize(filteredI, filteredI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a // viewable image form (float between values 0 and 1). imshow("image", I); imshow("filtered", filteredI); waitKey(0); } //一是输出Mat C应声明为引用;二是其中的mulSpectrums函数的第四个参数flag值没有指定,应指定为DFT_COMPLEX_OUTPUT或是DFT_REAL_OUTPUT. //main函数中首先按灰度图读入图像,然后创造一个平滑核kernel,将输入图像转换成float类型(注意这步是必须的,因为dft只能处理浮点数),在调用convolveDFT求出卷积结果后,将卷积结果归一化方便显示观看。 //需要注意的是,一般求法中,利用核游走整个图像进行卷积运算,实际上进行的是相关运算,真正意义上的卷积,应该首先把核翻转180度,再在整个图像上进行游走。OpenCV中的filter2D实际上做的也只是相关,而非卷积。
相关文章推荐
- Linux下socket编程实现客户机服务器通信的例子
- Linux开发二_构建标准c库newlib
- Linux开发一_Arm交叉编译环境
- 轻开纯HTML5的公司网站介绍
- 通过rsync+inotify实现服务器之间数据的实时备份
- git 服务器搭建 for linux
- Leap Motion 使用OpenCV获取和显示图像
- C++(也许算是吧)+Linux 简易web服务器实现(with EPOLL&THREAD POLL)(1)
- NSString属性什么时候用copy,什么时候用strong?
- 新人一枚,从此入驻CSDN博客
- opencv中三种像素访问方式的运行速度比较
- 硬盘分区 5
- linux 命令每天必学之tar命令
- linux shell4 判断登陆用户,然后重启关闭系统
- linux shell 编程5 函数获取参数
- 浅谈获取shell中函数的返回值
- Hadoop状态页面的Browse the filesystem链接无效的问题
- CentOS中设置.so链接文件路径
- linux共享内存
- CentOS 7安裝视频解码器