码迷,mamicode.com
首页 > 其他好文 > 详细

(原)使用intel的ippiConv对图像进行卷积

时间:2016-05-05 19:13:36      阅读:545      评论:0      收藏:0      [点我收藏+]

标签:

转载请注明出处:

http://www.cnblogs.com/darkknightzh/p/5462631.html

参考网址:

https://software.intel.com/zh-cn/node/504170

https://software.intel.com/en-us/node/599808

 

 1 #include <opencv2/opencv.hpp>
 2 #include <opencv2/highgui/highgui.hpp>
 3 #include <opencv2/imgproc/imgproc.hpp>
 4 using namespace cv;
 5 #include <ipp.h>
 6 
 7 enum ConvolutionType                      // 卷积时参数的类型
 8 {
 9     CONVOLUTION_FULL,                    // 卷积时的参数,和 matlab 的 full 一致
10     CONVOLUTION_SAME,                    // 卷积时的参数,和 matlab 的 same 一致
11     CONVOLUTION_VALID                    // 卷积时的参数,和 matlab 的 valid 一致
12 };
13 
14 void Conv2IPP(Mat& convRes, const Mat& imgIn, const Mat& kernelIn, ConvolutionType type, int ddepth)
15 {
16     Mat img = imgIn.clone(), kernel = kernelIn.clone();
17     const IppiSize imgSize = { img.cols, img.rows };
18     const IppiSize kerSize = { kernel.cols, kernel.rows };
19 
20     if (CV_32FC1 != img.type())
21     {
22         img.convertTo(img, CV_32FC1);  // ipp的库支持8u,16s,32f这几种精度的数据的卷积
23     }
24     if (CV_32FC1 != kernel.type())
25     {
26         kernel.convertTo(kernel, CV_32FC1);
27     }
28 
29     int nConvResW = img.cols + kernel.cols - 1;
30     int nConvResH = img.rows + kernel.rows - 1;
31     // 如果直接声明Mat的变量,并在ippiConv_32f_C1R中传递.data缓冲区的话,程序会崩溃,因而只能先加一个临时变量
32     float *pConvRes = new float[nConvResW * nConvResH];  
33 
34     // ippiROIFull改为ippiROIValid或者ippiROISame对应matlab响应的参数。不能直接改,否则结果不对。具体怎么改,暂时不清楚。
35     IppEnum funCfgFull = (IppEnum)(ippAlgAuto | ippiROIFull | ippiNormNone);  
36     int bufSizeFull;
37     IppStatus status = ippiConvGetBufferSize(imgSize, kerSize, ipp32f, 1, funCfgFull, &bufSizeFull);
38     Ipp8u* pBuffer = ippsMalloc_8u(bufSizeFull);
39 
40     ippiConv_32f_C1R((Ipp32f*)img.data, img.step, imgSize, (Ipp32f*)kernel.data, kernel.step, kerSize,
41         pConvRes, nConvResW * 4, funCfgFull, pBuffer);   // 此处应该使用nConvResW * 4
42 
43     Mat matConvResTemp(nConvResH, nConvResW, CV_32FC1);
44     memcpy(matConvResTemp.data, pConvRes, sizeof(float)* nConvResH * nConvResW);
45 
46     Rect r;
47     switch (type)
48     {
49     case CONVOLUTION_FULL:  // full
50         r = Rect(0, 0, matConvResTemp.cols, matConvResTemp.rows);
51         break;
52     case CONVOLUTION_SAME:  // same
53         r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows);
54         break;
55     case CONVOLUTION_VALID:  // valid
56         r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols - kernel.cols + 1, img.rows - kernel.rows + 1);
57         break;
58     default:  // same
59         r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows);
60         break;
61     }
62 
63     matConvResTemp(r).convertTo(convRes, ddepth, 1, 0);  // ddepth为CV_32FC1等类型
64 
65     ippsFree(pBuffer);
66     delete[] pConvRes;
67     pConvRes = nullptr;
68 }

说明:不确定的有2处:

1. 此程序计算卷积还是相关?感觉像是相关而非卷积(之前写过的程序计算相关,此处和之前的结果总体上相似。理论上卷积是核需要上下左右镜像的,这个地方不确定)

2. CONVOLUTION_FULL没有问题,CONVOLUTION_SAME不确定矩形框是否正确,CONVOLUTION_VALID也不确定是否正确。实际上对于后两者,可以将标志funCfgFullippiROIFull改为ippiROISame或者ippiROIValid,不过卷积的缓冲区pConvRes需要相应的改变大小。还有,如果直接改标志的话,卷积的结果不正确。不清楚什么原因。

 

(原)使用intel的ippiConv对图像进行卷积

标签:

原文地址:http://www.cnblogs.com/darkknightzh/p/5462631.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!