图像卷积运算 速度好慢哦 求帮忙优化一下代码

阿哥大花轿 2015-04-02 11:32:21
大概思路是 对1600*400的图求每一个像素点附近7*7范围内的所有像素值最大值和最小值,然后求最大值和最小值之差。
int i, j, s,w ,nmax,nmin;
int rh=3, rw=3;
for(j=rh; j<nHeight-rh; j++)
{
w=j*nWidth;
for(i=rw; i<nWidth-rw; i++)
{

nmax=0,nmin=255;
for (int dj=-rh;dj<=rh;dj++)
for (int di=-rw;di<=rw;di++)
{
if (pbGray[w+dj*nWidth+i+di]>nmax)
{
nmax=pbGray[w+dj*nWidth+i+di];
}
if (pbGray[w+dj*nWidth+i+di]<nmin)
{
nmin=pbGray[w+dj*nWidth+i+di];
}

}
s=nmax-nmin;
if( s < 50)
pbEdge[w+i] = 128;
else if(s>50&&(nmax+nmin)<2*pbGray[w+i])
pbEdge[w+i] = 255;
else if(s>50&&(nmax+nmin)>2*pbGray[w+i])
pbEdge[w+i] = 0;

}
}

pbedge数组是输出结果,主要是嵌套循环太多,占用时间太久,有没有大神帮帮忙,给我一点改进的思路,谢谢
...全文
857 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
prfans1 2015-04-07
  • 打赏
  • 举报
回复
引用 15 楼 swanlung 的回复:
[quote=引用 13 楼 prfans1 的回复:] 最简单的把图像全部改为指针类运算,并且[ ]内别用太多运算。 如果还想提升,考虑用FFT。
BYTE *m_pbGray 其实几个数组都是 指针类型 [/quote] 其实我主要想说,如果求卷积,可以利用那条时域卷积和频域的乘积公式,会更快点。
阿哥大花轿 2015-04-07
  • 打赏
  • 举报
回复
引用 18 楼 wangyaninglm 的回复:
SIMD是指单指令多数据技术,它已经成为Intel处理器的重要性能扩展。目前Intel处理器支持的SIMD技术包括MMX,SSE,AVX. MMX提供了8个64bit的寄存器进行SIMD操作,SSE系列提供了128bit的8个寄存器进行SIMD指令操作。而最新的AVX指令则支持256bit的SIMD操作。 目前SIMD指令可以有四种方法进行使用分别是汇编语言,C++类,编译器Intrisincs和自动矢量化。我们用下面的求一个整数数组的和作为例子: int SumAarray(int *buf,int N) { int i,sum=0; for(i=0;i<N;i++) sum+=buf[i]; return sum; } 方法一:自动矢量化 Intel编译器支持自动矢量化,通过选择特点的处理器选项/Q[a]{T|P|N|W|K},上面的代码可以采用下来命令进行编译: icl /QxP/c /Fa test_vec.c test_vec.c(4):(col.1)remark:LOOP WAS VECTORIZED.从上面的报告中可以看到第四行的循环自动向量化,还可以通过生成的汇编代码,看到使用了SIMD指令。 方法二:C++类 Intel C++编译器和C++类库中提供了一些新的C++类,这些类对应那些可以直接使用的SIMD指令(支持MMX,SSE,SSE2,不支持SSE3)的数据类型,使用时需要包含如下头文件: #include <ivec.h> //MMX #include <fvec.h>//SSE(also include ivec.h) #include <dvec.h>//SSE2(also include fvec.h) 这些支持SIMD的向量类型采取下面的命名规则:前面用I和F分别表示是支持浮点还是整数SIMD指令,接下来是数字取值为8,16,32,64,表示组向量的基本元素大小。然后后面为字符串vec,最后的数组取值为8,4,2,1,表示组成向量的基本元素的个数。使用64bit的MMX技术的整数类包括I64vec1,I32vec2,I16vec4和I8vec8,而使用128bit的XMM寄存器的浮点类则包括F32vec4,F32vec1,F64vec2。SSE2中使用128bit的XMM寄存器,整数类包括:I128vec1,I64vec2,I32vec4,I16vec8,I8vec16,为了进一步区分封装的是有符号整数还是无符号整数,在那些整数之后也可以包含一个符号标志s或者u,比如I?vec4. 通过类的封装,程序员无须关心那些对于类的运算到底使用了哪些汇编指令或者SIMD intrinsic函数,应用易于阅读和编码,并且没有直接使用SIMD代码,在不同的处理器之间不需要任何改动,但是其缺点是无法访问所有的指令和数据类型的组合。 http://blog.chinaunix.net/uid-20385936-id-3902720.html
感谢普及知识
shiter 2015-04-07
  • 打赏
  • 举报
回复
SIMD是指单指令多数据技术,它已经成为Intel处理器的重要性能扩展。目前Intel处理器支持的SIMD技术包括MMX,SSE,AVX. MMX提供了8个64bit的寄存器进行SIMD操作,SSE系列提供了128bit的8个寄存器进行SIMD指令操作。而最新的AVX指令则支持256bit的SIMD操作。 目前SIMD指令可以有四种方法进行使用分别是汇编语言,C++类,编译器Intrisincs和自动矢量化。我们用下面的求一个整数数组的和作为例子: int SumAarray(int *buf,int N) { int i,sum=0; for(i=0;i<N;i++) sum+=buf[i]; return sum; } 方法一:自动矢量化 Intel编译器支持自动矢量化,通过选择特点的处理器选项/Q[a]{T|P|N|W|K},上面的代码可以采用下来命令进行编译: icl /QxP/c /Fa test_vec.c test_vec.c(4):(col.1)remark:LOOP WAS VECTORIZED.从上面的报告中可以看到第四行的循环自动向量化,还可以通过生成的汇编代码,看到使用了SIMD指令。 方法二:C++类 Intel C++编译器和C++类库中提供了一些新的C++类,这些类对应那些可以直接使用的SIMD指令(支持MMX,SSE,SSE2,不支持SSE3)的数据类型,使用时需要包含如下头文件: #include <ivec.h> //MMX #include <fvec.h>//SSE(also include ivec.h) #include <dvec.h>//SSE2(also include fvec.h) 这些支持SIMD的向量类型采取下面的命名规则:前面用I和F分别表示是支持浮点还是整数SIMD指令,接下来是数字取值为8,16,32,64,表示组向量的基本元素大小。然后后面为字符串vec,最后的数组取值为8,4,2,1,表示组成向量的基本元素的个数。使用64bit的MMX技术的整数类包括I64vec1,I32vec2,I16vec4和I8vec8,而使用128bit的XMM寄存器的浮点类则包括F32vec4,F32vec1,F64vec2。SSE2中使用128bit的XMM寄存器,整数类包括:I128vec1,I64vec2,I32vec4,I16vec8,I8vec16,为了进一步区分封装的是有符号整数还是无符号整数,在那些整数之后也可以包含一个符号标志s或者u,比如I?vec4. 通过类的封装,程序员无须关心那些对于类的运算到底使用了哪些汇编指令或者SIMD intrinsic函数,应用易于阅读和编码,并且没有直接使用SIMD代码,在不同的处理器之间不需要任何改动,但是其缺点是无法访问所有的指令和数据类型的组合。 http://blog.chinaunix.net/uid-20385936-id-3902720.html
阿哥大花轿 2015-04-07
  • 打赏
  • 举报
回复
引用 14 楼 DelphiGuy 的回复:
从这个运算来看,是可以用SSE/AVX指令优化的,如果灰度数据pbGray[]是8位每像素,可以计算到16x16(SSE)或者32x32(AVX)像素块。对于楼主的具体代码,就是7次movdqu装入待运算像素块的7行,然后分别6次比较pmaxub/pminub求出7列像素(注意不是7行)中的最大/最小值,再对结果用punpcklbw、phminposuw(最大值要先pxor求反,再phminposuw)求最终的最大、最小值。粗略估计可以在50个时钟周期之内完成,可以考虑使用Intrinsics实现,不必用嵌入汇编。
太专业了,我这点薄弱的编程基础完全看呆了,太强大了以至于不是我能实现的。。。
赵4老师 2015-04-07
  • 打赏
  • 举报
回复
14楼高人也!
阿哥大花轿 2015-04-07
  • 打赏
  • 举报
回复
引用 13 楼 prfans1 的回复:
最简单的把图像全部改为指针类运算,并且[ ]内别用太多运算。 如果还想提升,考虑用FFT。
BYTE *m_pbGray 其实几个数组都是 指针类型
阿哥大花轿 2015-04-03
  • 打赏
  • 举报
回复
引用 5 楼 FancyMouse 的回复:
不要直接做7*7的,做横向1D的附近7个元素范围的最值,再纵向1D做最值,出来的就是7*7范围的最值。 顺便,1D的做法也可以通过单调队列把常数从7降到2~3左右。
大神,帮忙简单写点代码,我还是不能领悟你的思路是如何提高效率的,
  • 打赏
  • 举报
回复
从这个运算来看,是可以用SSE/AVX指令优化的,如果灰度数据pbGray[]是8位每像素,可以计算到16x16(SSE)或者32x32(AVX)像素块。对于楼主的具体代码,就是7次movdqu装入待运算像素块的7行,然后分别6次比较pmaxub/pminub求出7列像素(注意不是7行)中的最大/最小值,再对结果用punpcklbw、phminposuw(最大值要先pxor求反,再phminposuw)求最终的最大、最小值。粗略估计可以在50个时钟周期之内完成,可以考虑使用Intrinsics实现,不必用嵌入汇编。
prfans1 2015-04-03
  • 打赏
  • 举报
回复
最简单的把图像全部改为指针类运算,并且[ ]内别用太多运算。

如果还想提升,考虑用FFT。
阿哥大花轿 2015-04-03
  • 打赏
  • 举报
回复
引用 11 楼 zhao4zhong1 的回复:
[quote=引用 10 楼 zhao4zhong1 的回复:] 我这个OpenCV版本教低,也许高版本的OpenCV里面有利用并发编程的卷积代码也说不定。 楼主自己搜搜看。 http://www.baigoogledu.com/s.php?hl=zh-CN&q=convolution+fast
自顶!自赞! 高效使用搜索引擎是现代码农必须掌握的技能之一![/quote] 向你学习,我在摸索摸索,感谢指教啊
赵4老师 2015-04-03
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
我这个OpenCV版本教低,也许高版本的OpenCV里面有利用并发编程的卷积代码也说不定。 楼主自己搜搜看。 http://www.baigoogledu.com/s.php?hl=zh-CN&q=convolution+fast
自顶!自赞! 高效使用搜索引擎是现代码农必须掌握的技能之一!
赵4老师 2015-04-03
  • 打赏
  • 举报
回复
我这个OpenCV版本教低,也许高版本的OpenCV里面有利用并发编程的卷积代码也说不定。 楼主自己搜搜看。 http://www.baigoogledu.com/s.php?hl=zh-CN&q=convolution+fast
阿哥大花轿 2015-04-03
  • 打赏
  • 举报
回复
引用 7 楼 zhao4zhong1 的回复:
File: "C:\Program Files\OpenCV\modules\objdetect\src\matching.cpp":
     13: /*
     14: // Function for convolution computation
     15: //
     16: // INPUT
     17: // Fi                - filter object
     18: // map               - feature map
     19: // OUTPUT
     20: // f                 - the convolution
     21: // RESULT
     22: // Error status
     23: */
     24: int convolution(const CvLSVMFilterObject *Fi, const CvLSVMFeatureMap *map, float *f)
     25: {
     26:     int n1, m1, n2, m2, p, size, diff1, diff2;
     27:     int i1, i2, j1, j2, k;
     28:     float tmp_f1, tmp_f2, tmp_f3, tmp_f4;
     29:     float *pMap = NULL;
     30:     float *pH = NULL;
     31:     
     32:     n1 = map->sizeY;
     33:     m1 = map->sizeX;
     34:     n2 = Fi->sizeY;
     35:     m2 = Fi->sizeX;
     36:     p = map->p;
     37: 
     38:     diff1 = n1 - n2 + 1;
     39:     diff2 = m1 - m2 + 1;
     40:     size = diff1 * diff2;
     41:     for (j1 = diff2 - 1; j1 >= 0; j1--)
     42:     {
     43:         
     44:         for (i1 = diff1 - 1; i1 >= 0; i1--)
     45:         {
     46:             tmp_f1 = 0.0f;
     47:             tmp_f2 = 0.0f;
     48:             tmp_f3 = 0.0f;
     49:             tmp_f4 = 0.0f;
     50:             for (i2 = 0; i2 < n2; i2++)
     51:             {
     52:                 for (j2 = 0; j2 < m2; j2++)
     53:                 {
     54:                     pMap = map->Map + (i1 + i2) * m1 * p + (j1 + j2) * p;//sm2
     55:                     pH = Fi->H + (i2 * m2 + j2) * p;//sm2
     56:                     for (k = 0; k < p/4; k++)
     57:                     {
     58: 
     59:                         tmp_f1 += pMap[4*k]*pH[4*k];//sm2
     60:                         tmp_f2 += pMap[4*k+1]*pH[4*k+1];
     61:                         tmp_f3 += pMap[4*k+2]*pH[4*k+2];
     62:                         tmp_f4 += pMap[4*k+3]*pH[4*k+3];
     63:                     }
     64:             
     65:                     if (p%4==1)
     66:                     {
     67:                         tmp_f1 += pH[p-1]*pMap[p-1];
     68:                     }
     69:                     else
     70:                     {
     71:                         if (p%4==2)
     72:                         {
     73:                             tmp_f1 += pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1];
     74:                         }
     75:                         else
     76:                         {
     77:                             if (p%4==3)
     78:                             {
     79:                                 tmp_f1 += pH[p-3]*pMap[p-3] + pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1];
     80:                             }
     81:                         }
     82:                     }
     83: 
     84:                 }
     85:             }
     86:             f[i1 * diff2 + j1] = tmp_f1 + tmp_f2 + tmp_f3 + tmp_f4;//sm1
     87:         }
     88:     }
     89:     return LATENT_SVM_OK;
     90: }
对分辨率较高的图像,貌似也不会节约多少时间哦,我电脑是i5,3.2GHZ,我希望能够在10ms以内完成
shiter 2015-04-03
  • 打赏
  • 举报
回复
这opencv 的代码跟楼主的代码好像也差不多。。。
赵4老师 2015-04-03
  • 打赏
  • 举报
回复
File: "C:\Program Files\OpenCV\modules\objdetect\src\matching.cpp":
     13: /*
     14: // Function for convolution computation
     15: //
     16: // INPUT
     17: // Fi                - filter object
     18: // map               - feature map
     19: // OUTPUT
     20: // f                 - the convolution
     21: // RESULT
     22: // Error status
     23: */
     24: int convolution(const CvLSVMFilterObject *Fi, const CvLSVMFeatureMap *map, float *f)
     25: {
     26:     int n1, m1, n2, m2, p, size, diff1, diff2;
     27:     int i1, i2, j1, j2, k;
     28:     float tmp_f1, tmp_f2, tmp_f3, tmp_f4;
     29:     float *pMap = NULL;
     30:     float *pH = NULL;
     31:     
     32:     n1 = map->sizeY;
     33:     m1 = map->sizeX;
     34:     n2 = Fi->sizeY;
     35:     m2 = Fi->sizeX;
     36:     p = map->p;
     37: 
     38:     diff1 = n1 - n2 + 1;
     39:     diff2 = m1 - m2 + 1;
     40:     size = diff1 * diff2;
     41:     for (j1 = diff2 - 1; j1 >= 0; j1--)
     42:     {
     43:         
     44:         for (i1 = diff1 - 1; i1 >= 0; i1--)
     45:         {
     46:             tmp_f1 = 0.0f;
     47:             tmp_f2 = 0.0f;
     48:             tmp_f3 = 0.0f;
     49:             tmp_f4 = 0.0f;
     50:             for (i2 = 0; i2 < n2; i2++)
     51:             {
     52:                 for (j2 = 0; j2 < m2; j2++)
     53:                 {
     54:                     pMap = map->Map + (i1 + i2) * m1 * p + (j1 + j2) * p;//sm2
     55:                     pH = Fi->H + (i2 * m2 + j2) * p;//sm2
     56:                     for (k = 0; k < p/4; k++)
     57:                     {
     58: 
     59:                         tmp_f1 += pMap[4*k]*pH[4*k];//sm2
     60:                         tmp_f2 += pMap[4*k+1]*pH[4*k+1];
     61:                         tmp_f3 += pMap[4*k+2]*pH[4*k+2];
     62:                         tmp_f4 += pMap[4*k+3]*pH[4*k+3];
     63:                     }
     64:             
     65:                     if (p%4==1)
     66:                     {
     67:                         tmp_f1 += pH[p-1]*pMap[p-1];
     68:                     }
     69:                     else
     70:                     {
     71:                         if (p%4==2)
     72:                         {
     73:                             tmp_f1 += pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1];
     74:                         }
     75:                         else
     76:                         {
     77:                             if (p%4==3)
     78:                             {
     79:                                 tmp_f1 += pH[p-3]*pMap[p-3] + pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1];
     80:                             }
     81:                         }
     82:                     }
     83: 
     84:                 }
     85:             }
     86:             f[i1 * diff2 + j1] = tmp_f1 + tmp_f2 + tmp_f3 + tmp_f4;//sm1
     87:         }
     88:     }
     89:     return LATENT_SVM_OK;
     90: }
FancyMouse 2015-04-02
  • 打赏
  • 举报
回复
不要直接做7*7的,做横向1D的附近7个元素范围的最值,再纵向1D做最值,出来的就是7*7范围的最值。 顺便,1D的做法也可以通过单调队列把常数从7降到2~3左右。
yshuise 2015-04-02
  • 打赏
  • 举报
回复
直接inline试试。
阿哥大花轿 2015-04-02
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
参考OpenCV源代码中相关片断。
我电脑上没有opencv源码查看软件,你方便截取一段给我参考一下嘛,自己写的效率太低了。
  • 打赏
  • 举报
回复
不要用CPU渲染啦,非常慢的。用GPU来做吧。
赵4老师 2015-04-02
  • 打赏
  • 举报
回复
参考OpenCV源代码中相关片断。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧