快速Gabor滤波(~1 ms) & python ctype 踩坑经验

最重要的更新:CSDN资源已经上传,想跑一下的可以直接下载!

链接:https://download.csdn.net/download/Zhang__zj__/89771265?spm=1001.2014.3001.5501

然后可能之后会小修小补一点代码的bug(有时候表现不是很好),不过可能不会及时在CSDN上更新(但是github大概率会),所以如果你有issue或者pull request,欢迎来github,我不太常用CSDN,只是ctype吃了很多史才想着来CSDN发一个(还有github我的代码也没人看来引流)。


# 一些更新内容

update: CSDN上同步了和github上一样的代码,之后估计不会有较大的变化,所以就这样了。主要是更新了虚部的计算(不然出的图不好)顺便修了一些小bug。

艹,所有的kernel都写成kernal了……fix typo以后再说吧


update:更新了一点算三角函数的小bug,顺便更新了虚部的计算(因为不算虚部效果确实不太好)

虚部的计算方法放在最后了,在资源给的代码里稍微改改就行。因为可能还有bug于是没有更新资源的内容,(不然还要再打包再改)想要开箱即用在github上直接下载吧。

建议用Frequency = np.float32(np.pi**2/2),同时注意传到C++代码里面的元素最大为1(我也不知道为啥),否则会出问题!


# 代码介绍

自己的CV代码想要做到realtime,需要一个巨快的Gabor滤波(而且我们需要好多次,效率一定要非常高),但是网上没有现成的轮子(大部分是基于卷积的,速度比较慢),于是下定决心自己写一个(而且也不难)。

实现基于J. Kim, S. Um and D. Min, "Fast 2D Complex Gabor Filter With Kernel Decomposition," in IEEE Transactions on Image Processing, vol. 27, no. 4, pp. 1713-1722, April 2018。他们自称是速度最快的方法,不过我们只算了实数部分,虚数部分没算,因为大部分纯卷积的也就只算实数部分。(update:我们后来加入了虚数部分因为纯实数效果不太好。)

# 代码可用性

代码开源在github上,链接放在下面。

如果看的人多了之后开一个gitee或者什么国内的应该也行?CSDN这个B资源还要审核,总之求大家给点star吧(你GitHub - Zhang-Zhaoji/FastGabor_Python: Based on J. Kim, S. Um and D. Min, "Fast 2D Complex Gabor Filter With Kernel Decomposition," in IEEE Transactions on Image Processing, vol. 27, no. 4, pp. 1713-1722, April 2018,​​​​​速度大概是:

对于一个 120x160 的矩阵,频率为 8 像素,核大小为 17x17(等效),我们的代码的运行时间为0.0010004043579101562 秒 (只看gabor滤波,不看什么plt之类的)

# 怎么用

python提供了原生的ctypes,基本上就是个C的接口,可以把我的python代码文件打包成一个函数直接调用,或者稍微改改也行。只要dll在旁边就能直接调,不用什么pybind之类的。

# 踩坑经验

不管是中英互联网大部分人都没有搞清楚ctypes还是比较恶心的,不支持C++的大部分内容,包括iostream/string/vector/...,所以,如果你想进一步优化我的代码,注意不要想着找C++的工具。

并行计算听起来很美妙,但是实操貌似会稍微慢一点。

-O3编译器优化非常有效,大概提高了20倍运行速度,赞美机神!

截图留档

# (可能)常见的问题

  • 运行python文件,但是没有plt的输出:

需要输入的image格式大概是np.float32(image),还必须是二维数组。

  • 明明就在同一个文件夹下,却说找不到dll

这个问题可能是你改了c++的代码?我遇到的大部分情况都是加入了C不兼容的(因此ctype也不兼容的)C++特性代码。如果不是,也许可以试试把写绝对的地址。

## 虚部的计算方法(已经在新代码中更改,如果用的是更新之后的可以不管)

// define IF
        float** IF = (float**)malloc(M * sizeof(float*));
        for (int i = 0; i < M; ++i) {
            IF[i] = (float*)malloc(N * sizeof(float));
        }

// ... 中间其他的计算代码

IF[_y][x] += sin_ws_y[_y] * S_sigma[std::abs(__kernel)] *\
                            (cos_s[std::abs(__kernel)] * RJ[mirror_index(_y,__kernel,M)][x] \
                           + sin_s[std::abs(__kernel)] * IJ[mirror_index(_y,__kernel,M)][x] * (1?__kernel>0:-1)) \
                              - cos_ws_y[_y] * S_sigma[std::abs(__kernel)] *\
                            (sin_s[std::abs(__kernel)] * RJ[mirror_index(_y,__kernel,M)][x] * (1?__kernel>0:-1)\
                           - cos_s[std::abs(__kernel)] * IJ[mirror_index(_y,__kernel,M)][x])  ;

// 其他计算代码

// write answer
        for (int i = 0; i < M; ++i) {
            for (int j = 0; j < N; ++j) {
                // send results towards original matrix
                image[i * N + j] = std::sqrt(F[i][j] * F[i][j] + IF[i][j] * IF[i][j]);
            }
        }
# 释放内存
       for (int i = 0; i < M; ++i) {
        free(IF[i]);
        }
        free(IF);
    }
2D-FFT的Gabor滤波是一种常用的图像处理方法,可以用于提取掌纹等生物特征。以下是使用 Python 实现 2D-FFT的Gabor滤波提取掌纹特征的示例代码: ```python import cv2 import numpy as np from scipy import fftpack # 读取图像 img = cv2.imread(&#39;input.jpg&#39;, 0) # 定义Gabor滤波器的参数 ksize = 31 theta = np.pi / 4 sigma = 2 * np.pi gamma = 0.5 psi = 0 # 生成Gabor滤波器的实部和虚部 kernel_real = cv2.getGaborKernel((ksize, ksize), sigma, theta, gamma, 1, psi, ktype=cv2.CV_32F) kernel_imag = cv2.getGaborKernel((ksize, ksize), sigma, theta, gamma, 1, psi + np.pi/2, ktype=cv2.CV_32F) # 对图像进行2D-FFT img_fft = fftpack.fft2(img) # 将滤波器转换为频率域 kernel_real_fft = fftpack.fft2(kernel_real, s=img.shape) kernel_imag_fft = fftpack.fft2(kernel_imag, s=img.shape) # 将滤波器应用于频率域图像 filtered_real = np.real(fftpack.ifft2(img_fft * kernel_real_fft)) filtered_imag = np.real(fftpack.ifft2(img_fft * kernel_imag_fft)) # 计算Gabor滤波器响应的幅值 gabor_response = np.sqrt(filtered_real ** 2 + filtered_imag ** 2) # 显示结果 cv2.imshow(&#39;input&#39;, img) cv2.imshow(&#39;gabor_response&#39;, gabor_response) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个例子中,我们首先使用 OpenCV 库中的 `cv2.imread()` 函数读取输入图像,并将其转换为灰度图像。然后,我们定义 Gabor 滤波器的参数,包括滤波器大小、方向、尺度、宽度和相位偏移等。 接下来,我们使用 OpenCV 库中的 `cv2.getGaborKernel()` 函数生成 Gabor 滤波器的实部和虚部。然后,我们使用 SciPy 库中的 `fftpack.fft2()` 函数对输入图像进行二维快速傅里叶变换,将其转换为频率域图像。 接下来,我们将 Gabor 滤波器转换为频率域,并使用 `fftpack.ifft2()` 函数将其应用于频率域图像。然后,我们计算 Gabor 滤波器响应的幅值,并使用 `cv2.imshow()` 函数显示输入图像和 Gabor 滤波器响应,并使用 `cv2.waitKey()` 和 `cv2.destroyAllWindows()` 函数等待用户按下键盘上的任意键以关闭窗口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值