zhengli233
zhengli233
因为计算phase前总要计算gaussian和sobel,所以按照fuse的思路,我尝试把gaussian算子和sobel算子先算卷积,得到融合的卷积核,再用它对原图进行卷积。 ```c++ Mat src = imread("Hydrangeas.jpg", CV_8UC1); int g_k_size = 3; Mat sobel_x, sobel_y, phase_; Mat kernelX = (Mat_(3, 3)
直接乘起来是什么意思?
逐元素相乘是指矩阵点乘吗? 但src * gaussian_kernel * sobel_kernel不都是卷积运算吗,而且两个kernel的大小不一定一样啊。
@DennisLiu-elogic 你好, 看了你的代码,发现和我的代码最大的差别是你有一个flip的操作(另外就是sobel算子边缘补全)。这个flip应该就是相当于矩阵转置的操作吧。这里我不太明白。。虽然从结果上来说,你的比我好得多,能说说为什么要这么做吗? 另外,误差的原因我想可能就是在边缘上。我从知乎上找了一张图,介绍怎么把卷积转换成矩阵乘法。  可以看到,如果按正常顺序计算卷积,我们需要 1. 把原图展开; 2. 与卷积核做点乘; 3. 把点乘结果展开; 4. 与下一个卷积核做点乘。 这里实际上对原图展开了2次,而如果先计算后面2个卷积核,虽然也有2次展开,但是其中一次是对卷积核做的展开,因此丢失了一部分数据。
> 哦,之前我理解的有问题,fusion说的不是把卷积核都合成一个,因为这样会越来越大,比如两个3x3的合起来就变成5x5,虽然方法不明,但肯定不是直接一个filter2D另一个。 > fusion说的是局部读一块进去,一起算完再写出来,关键是提高了局部性,而且kernel不仅不应该合起来,还应该尽量拆开算,比如3x3算两次有mn*18次乘法,5x5一次就mn*25次。这也是为什么可分离卷积分开算要快点。 @meiqua 好像确实是这么个道理,kernel不应该合起来。 第二段中你说的提高局部性是指节省了写内存的开销吗?在计算量没有减少的情况下,写内存的开销与计算比起来应该占比很小吧。 > 推导了下,还真满足结合律,不过扩大成9x9也是应该的,改了下一点误差都没有了: > > ```c++ > Mat matSrc = imread ("", IMREAD_GRAYSCALE); > > // modification 1: double type, otherwise GaussianBlur will output...
@meiqua 没有修改你的代码,只是读了我本机路径的图片,结果是这样的  可以看到,偏差还是挺大的 : (
@xinsuinizhuan 不是在做pyrDown的融合,是高斯和sobel的融合
@xinsuinizhuan phase, magnitude不是卷积计算,所以也就没有算子,谈不上融合
 @meiqua 就是这张图,你试试看
Hi @kouchy , Here is my simple test code with "/arch:AVX2" compile command: ```c++ #include "stdafx.h" #include "mipp.h" int main() { uint8_t * arr = new uint8_t[256]; memset(arr, 1, sizeof(uint8_t)...