{"id":21849302,"url":"https://github.com/pasaopasen/gabor-wavelet","last_synced_at":"2026-02-12T18:01:46.841Z","repository":{"id":112081473,"uuid":"294064395","full_name":"PasaOpasen/Gabor-wavelet","owner":"PasaOpasen","description":"Python realization of wavelet transform with Gabor-kernel (from matlab)","archived":false,"fork":false,"pushed_at":"2020-09-11T19:00:03.000Z","size":1127,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-01T03:49:38.285Z","etag":null,"topics":["math","numba","numpy","speedup","wavelet-transform"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PasaOpasen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-09-09T09:21:56.000Z","updated_at":"2025-06-19T07:51:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"df599a66-4880-4235-8456-95871f8740bd","html_url":"https://github.com/PasaOpasen/Gabor-wavelet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PasaOpasen/Gabor-wavelet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PasaOpasen%2FGabor-wavelet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PasaOpasen%2FGabor-wavelet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PasaOpasen%2FGabor-wavelet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PasaOpasen%2FGabor-wavelet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PasaOpasen","download_url":"https://codeload.github.com/PasaOpasen/Gabor-wavelet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PasaOpasen%2FGabor-wavelet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29375597,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T08:51:36.827Z","status":"ssl_error","status_checked_at":"2026-02-12T08:51:26.849Z","response_time":55,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["math","numba","numpy","speedup","wavelet-transform"],"created_at":"2024-11-28T00:12:20.217Z","updated_at":"2026-02-12T18:01:46.825Z","avatar_url":"https://github.com/PasaOpasen.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gabor wavelet\n\nPython realization of wavelet transform with Gabor-kernel (from matlab)\n\nТут хранятся скрипты для выполнения прямого и обратного вейвлет-преобразования Габора + визуализаций.\n\n\n## Прямое преобразование\n\nЦелью этой части работы была перезапись [кода с матлаба](https://github.com/PasaOpasen/Gabor-wavelet/tree/master/matlab_source) и его ускорение, так как очень часто требуется использовать прямое преобразование на большой сетке.\n\nТут имеется две функции. Первая - это сама функция вейвлета Габора:\n\n```python\nimport numpy as np\nimport math\nimport cmath\n\ndef GaborWavelet(omega, t, Gabor_coef):\n    return 0.3251520240633*math.sqrt(omega)*cmath.exp(complex(-0.5*Gabor_coef*(t*omega*0.187390625129278)**2, omega*t))\n```\n\nЗдесь `omega` и `Gabot_coef` - некоторые параметры, а `t` - время (аргумент), для которого надо посчитать функцию вейвлета.\n\nВторая функция - это само прямое преобразование:\n\n```python\ndef DWT_signal(ut, a, b, t0, AA, BB, TT, omega0, Gabor_coef):\n\n    h_step=t0[1]-t0[0]\n    \n    psi_t = np.empty(TT, dtype = np.complex128)\n    Wab = np.empty((BB, AA), dtype = np.complex128)\n    \n    for j in range(AA):\n        for i in range(BB):\n            for k in range(TT):\n\n                t_cur=(t0[k]-b[i])/a[j]               \n                psi_t[k] = GaborWavelet(omega0, t_cur, Gabor_coef).conjugate()\n\n            f_psi = psi_t * ut\n            \n                 \n            Wab[i,j] =  0.5*(f_psi[0]+f_psi[-1]) + np.sum(f_psi[2:TT-1])\n        \n    Wab = np.multiply(Wab, h_step/np.sqrt(a))\n    \n    return Wab\n```\n\n`ut` - значения сигнала, `a` - значения по второй оси, `b` - значения по первой оси, `t0` - массив времен, `AA, BB, TT`- длины первых трех массивов (в Matlab и Fortran их принято передавать как аргументы).\n\n\nПоработав над кодом, я добился очень существенного ускорения в сравнении с [исходным вариантом](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/translation_only.py). Это было сделано с помощью комбинации трёх подходов:\n\n1. оптимизации самого алгоритма, чтобы избавиться от повторных вычислений и множественных обращений к одним и тем же участкам памяти\n\n2. векторизации вычислений, чтобы больше кода выполнялось с помощью низкоуровневых функций\n\n3. jit-компиляции и возможной параллелизации\n\nЭти подходы применялись как к вейвлету Габора, так и к прямому преобразованию, причём в разных пропорциях. В итоге получилось несколько версии этого алгоритма с разными характеристиками. Далее представлены результаты их сравнения.\n\n### Benchmarks\n\nСделаем проверку скорости на среднем объёме данных:\n\n```python\na = np.arange(1,30,0.5) # 58 \nb = np.arange(0,50,0.5) # 100\n\nt = np.arange(0,101) # 101\nut = np.sin(2*math.pi/50 * t) + 100*np.cos(0.4*t)/(t*t+1)\n\nomega = 1\n\nGabor_coef = 8\n\n```\n\nПроверка делается с помощью инструкций `%timeit` IPython:\n\n```python\n%timeit translation_only.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n%timeit light_vectorization.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n%timeit strong_vectorization.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n%timeit numba_strong.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n%timeit numba_just.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n%timeit numba_vectorization.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n%timeit numba_vec_parallel.DWT_signal(ut, a, b, t, a.size, b.size, t.size, omega, Gabor_coef)\n```\n\nКаждый модуль здесь - это отдельная версия алгоритма.\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/W(a%2Cb).png)\n\nИтак, для этой размерности данных получаем результаты:\n\n| Version   |      Time      | \n|:----------:|:-------------:|\n| translation_only |  7.24 s ± 142 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)|\n| light_vectorization |    372 ms ± 8.83 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)   |\n| strong_vectorization | 368 ms ± 8.54 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) |\n| numba_strong |  219 ms ± 5.17 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) |\n| numba_just |    36.3 ms ± 914 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)   |\n| numba_vectorization | 35.1 ms ± 350 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)|\n| numba_vec_parallel |  8.33 ms ± 85.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) |\n\n\nКак видно, удалось добиться ускорения примерно в 7.24s/35ms = 200 раз, не делая никакого распараллеливания. Параллельная версия работает ещё в 4 раза быстрее на моём 8-ядерном компьютере. \n\n\n\n## Обратное преобразование\n\nДля обратного преобразования нужно иметь исходную матрицу `W(a,b)`, вдобавок желательно посмотреть её тепловую карту, чтобы убедиться, что заданная сетка `a x b` покрывает все возвышения (иногда эту сетку придётся сдвигать либо делать больше). Получить значения сигнала (обратного преобразования) для массиво времен `t` можно командой\n\n```python\nfrom Reverse import St_array\n\ns = St_array(t, Wab, a, b, omega, Gabor_coef)\n\n```\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/W(a%2Cb)%20from%20sin(2pi%20div%2050%20t).png)\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/sin(2pi%20div%2050%20t).png)\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/W(a%2Cb)%20from%20sin(2pi%20div%2050%20t)%2Bsin(2pi%20div%20100%20t).png)\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/sin(2pi%20div%2050%20t)%2Bsin(2pi%20div%20100%20t).png)\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/W(a%2Cb)%20from%20sin(2pi%20div%2050%20t)%20%2B%204sin(2pi%20div%2010%20t).png)\n\n![1](https://github.com/PasaOpasen/Gabor-wavelet/blob/master/images/sin(2pi%20div%2050%20t)%20%2B%204sin(2pi%20div%2010%20t).png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpasaopasen%2Fgabor-wavelet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpasaopasen%2Fgabor-wavelet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpasaopasen%2Fgabor-wavelet/lists"}