(原)使用intel的ipp库计算卷积及相关
2016-05-05 17:24
591 查看
转载请注明出处:
http://www.cnblogs.com/darkknightzh/p/5462631.html
参考网址:
https://software.intel.com/zh-cn/node/504170
https://software.intel.com/en-us/node/599808
https://software.intel.com/en-us/node/504340
说明:不确定的有2处:
1. 此程序计算卷积还是相关?感觉像是相关而非卷积(之前写过的程序计算相关,此处和之前的结果总体上相似。理论上卷积是核需要上下左右镜像的,这个地方不确定)
ps:应该是卷积。
2. CONVOLUTION_FULL没有问题,CONVOLUTION_SAME不确定矩形框是否正确,CONVOLUTION_VALID也不确定是否正确。实际上对于后两者,可以将标志funCfgFull从ippiROIFull改为ippiROISame或者ippiROIValid,不过卷积的缓冲区pConvRes需要相应的改变大小。还有,如果直接改标志的话,卷积的结果不正确。不清楚什么原因。
ps:当使用ippiROISame时,计算到的bufSizeFull的值为0,因而卷积的结果不正确。不明白为什么。
150506更新:
在第三个参考网址中,发现了另一个函数ippiCrossCorrNorm_32f_C1R,用于计算相关。可以选用ippiROISame参数。
从参考网址3中可以看到,ippiNormNone是计算相关的意思。
需要注意的是,第二个程序是计算相关的程序,而非卷积。和matlab的程序对比测试,发现第一个程序结果和卷积的结果相似,第二个程序的结果和相关的结果相似。
http://www.cnblogs.com/darkknightzh/p/5462631.html
参考网址:
https://software.intel.com/zh-cn/node/504170
https://software.intel.com/en-us/node/599808
https://software.intel.com/en-us/node/504340
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; #include <ipp.h> enum ConvolutionType // 卷积时参数的类型 { CONVOLUTION_FULL, // 卷积时的参数,和 matlab 的 full 一致 CONVOLUTION_SAME, // 卷积时的参数,和 matlab 的 same 一致 CONVOLUTION_VALID // 卷积时的参数,和 matlab 的 valid 一致 }; void Conv2IPP(Mat& convRes, const Mat& imgIn, const Mat& kernelIn, ConvolutionType type, int ddepth) { Mat img = imgIn.clone(), kernel = kernelIn.clone(); const IppiSize imgSize = { img.cols, img.rows }; const IppiSize kerSize = { kernel.cols, kernel.rows }; if (CV_32FC1 != img.type()) { img.convertTo(img, CV_32FC1); // ipp的库支持8u,16s,32f这几种精度的数据的卷积 } if (CV_32FC1 != kernel.type()) { kernel.convertTo(kernel, CV_32FC1); } int nConvResW = img.cols + kernel.cols - 1; int nConvResH = img.rows + kernel.rows - 1; // 如果直接声明Mat的变量,并在ippiConv_32f_C1R中传递.data缓冲区的话,程序会崩溃,因而只能先加一个临时变量 float *pConvRes = new float[nConvResW * nConvResH]; // ippiROIFull改为ippiROIValid或者ippiROISame对应matlab响应的参数。不能直接改,否则结果不对。具体怎么改,暂时不清楚。 IppEnum funCfgFull = (IppEnum)(ippAlgAuto | ippiROIFull | ippiNormNone); int bufSizeFull; IppStatus status = ippiConvGetBufferSize(imgSize, kerSize, ipp32f, 1, funCfgFull, &bufSizeFull); Ipp8u* pBuffer = ippsMalloc_8u(bufSizeFull); ippiConv_32f_C1R((Ipp32f*)img.data, img.step, imgSize, (Ipp32f*)kernel.data, kernel.step, kerSize, pConvRes, nConvResW * 4, funCfgFull, pBuffer); // 此处应该使用nConvResW * 4 Mat matConvResTemp(nConvResH, nConvResW, CV_32FC1); memcpy(matConvResTemp.data, pConvRes, sizeof(float)* nConvResH * nConvResW); Rect r; switch (type) { case CONVOLUTION_FULL: // full r = Rect(0, 0, matConvResTemp.cols, matConvResTemp.rows); break; case CONVOLUTION_SAME: // same r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows); break; case CONVOLUTION_VALID: // valid r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols - kernel.cols + 1, img.rows - kernel.rows + 1); break; default: // same r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows); break; } matConvResTemp(r).convertTo(convRes, ddepth, 1, 0); // ddepth为CV_32FC1等类型 ippsFree(pBuffer); delete[] pConvRes; pConvRes = nullptr; }
说明:不确定的有2处:
1. 此程序计算卷积还是相关?感觉像是相关而非卷积(之前写过的程序计算相关,此处和之前的结果总体上相似。理论上卷积是核需要上下左右镜像的,这个地方不确定)
ps:应该是卷积。
2. CONVOLUTION_FULL没有问题,CONVOLUTION_SAME不确定矩形框是否正确,CONVOLUTION_VALID也不确定是否正确。实际上对于后两者,可以将标志funCfgFull从ippiROIFull改为ippiROISame或者ippiROIValid,不过卷积的缓冲区pConvRes需要相应的改变大小。还有,如果直接改标志的话,卷积的结果不正确。不清楚什么原因。
ps:当使用ippiROISame时,计算到的bufSizeFull的值为0,因而卷积的结果不正确。不明白为什么。
150506更新:
在第三个参考网址中,发现了另一个函数ippiCrossCorrNorm_32f_C1R,用于计算相关。可以选用ippiROISame参数。
Mat Conv2IPPSame(const Mat& imgIn, const Mat& kernelIn) { Mat img = imgIn.clone(), kernel = kernelIn.clone(); const IppiSize imgSize = { img.cols, img.rows }; const IppiSize kerSize = { kernel.cols, kernel.rows }; if (CV_32FC1 != img.type()) { img.convertTo(img, CV_32FC1); } if (CV_32FC1 != kernel.type()) { kernel.convertTo(kernel, CV_32FC1); } int nConvResW = img.cols; int nConvResH = img.rows; float *pConvRes = new float[nConvResW * nConvResH]; int bufSize; IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiROISame | ippiNormNone); IppStatus status = ippiCrossCorrNormGetBufferSize(imgSize, kerSize, funCfg, &bufSize); Ipp8u* pBuffer = ippsMalloc_8u(bufSize); ippiCrossCorrNorm_32f_C1R((Ipp32f*)img.data, img.step, imgSize, (Ipp32f*)kernel.data, kernel.step, kerSize, pConvRes, nConvResW * 4, funCfg, pBuffer); Mat matConvRes(nConvResH, nConvResW, CV_32FC1); memcpy(matConvRes.data, pConvRes, sizeof(float)* nConvResH * nConvResW); ippsFree(pBuffer); delete[] pConvRes; pConvRes = nullptr; return matConvRes; }
从参考网址3中可以看到,ippiNormNone是计算相关的意思。
需要注意的是,第二个程序是计算相关的程序,而非卷积。和matlab的程序对比测试,发现第一个程序结果和卷积的结果相似,第二个程序的结果和相关的结果相似。
相关文章推荐
- 今天说一下 Group by 这个东西
- Android Activity启动流程(三)–Activity启动的详细流程
- 今天说一下Order by 这个常规东西~
- 今天说一下where 中 exists 和 in 里面的一些区别
- 今天简单说一下cdc 的使用
- 关于字符串查找 charindex ,Patindex 还有一个like
- 转换函数
- 好用的排名函数~ROW_NUMBER(),RANK(),DENSE_RANK() 三兄弟
- 今天说一下 tablesample 这个东西
- 小说一下case ~
- 说一下output子句
- 今天说一下Top ~
- 2个小栗子~
- JProfiler 9.1注册码
- 关于取反~的运算
- SLF4J配置
- 关于外键,再唠叨一下下
- 【招聘】寻找最棒的你~~
- 【干货】测试评估:14种排序算法和PHP数组
- 简单说下外键