[gegl] common-cxx: new denoise-dct operation
- From: Thomas Manni <tmanni src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] common-cxx: new denoise-dct operation
- Date: Mon, 11 Apr 2022 19:33:30 +0000 (UTC)
commit 1655651fd1201d2ea6e0f4e9570af990f3735230
Author: Thomas Manni <thomas manni free fr>
Date: Mon Apr 11 12:54:57 2022 +0200
common-cxx: new denoise-dct operation
This denoising operation decomposes the input buffer to sliding overlapping
patches, calculates the DCT denoising in each patch, and then aggregates the
denoised patches to the output buffer averaging the overlapped pixels.
operations/common-cxx/dct-basis.inc | 357 +++++++++++++++++++++++++
operations/common-cxx/denoise-dct.cc | 486 +++++++++++++++++++++++++++++++++++
operations/common-cxx/meson.build | 1 +
po/POTFILES.in | 1 +
4 files changed, 845 insertions(+)
---
diff --git a/operations/common-cxx/dct-basis.inc b/operations/common-cxx/dct-basis.inc
new file mode 100644
index 000000000..2cfddf20e
--- /dev/null
+++ b/operations/common-cxx/dct-basis.inc
@@ -0,0 +1,357 @@
+/* Following matrices come from the implementation provided by
+ * https://www.ipol.im/pub/art/2011/ys-dct/
+ * Copyright (c) 2010, Guoshen Yu <yu cmap polytechnique fr>,
+ * Guillermo Sapiro <guille umn edu>
+ */
+
+/* A 8x8 1D DCT basis (each ROW is a vector of the forward transform basis */
+
+const gfloat DCTbasis8x8[8][8] = {
+ { 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719,
+ 0.35355339059327373085750423342688009142875671386719, },
+
+ { 0.49039264020161521528962111915461719036102294921875,
+ 0.41573480615127261783570133957255166023969650268555,
+ 0.27778511650980114433551193542371038347482681274414,
+ 0.09754516100806412404189416065491968765854835510254,
+ -0.09754516100806412404189416065491968765854835510254,
+ -0.27778511650980114433551193542371038347482681274414,
+ -0.41573480615127261783570133957255166023969650268555,
+ -0.49039264020161521528962111915461719036102294921875, },
+
+ { 0.46193976625564336924156805253005586564540863037109,
+ 0.19134171618254489088961634024599334225058555603027,
+ -0.19134171618254489088961634024599334225058555603027,
+ -0.46193976625564336924156805253005586564540863037109,
+ -0.46193976625564336924156805253005586564540863037109,
+ -0.19134171618254489088961634024599334225058555603027,
+ 0.19134171618254489088961634024599334225058555603027,
+ 0.46193976625564336924156805253005586564540863037109, },
+
+ { 0.41573480615127261783570133957255166023969650268555,
+ -0.09754516100806417955304539191274670884013175964355,
+ -0.49039264020161521528962111915461719036102294921875,
+ -0.27778511650980108882436070416588336229324340820312,
+ 0.27778511650980108882436070416588336229324340820312,
+ 0.49039264020161521528962111915461719036102294921875,
+ 0.09754516100806417955304539191274670884013175964355,
+ -0.41573480615127261783570133957255166023969650268555, },
+
+ { 0.35355339059327378636865546468470711261034011840820,
+ -0.35355339059327378636865546468470711261034011840820,
+ -0.35355339059327378636865546468470711261034011840820,
+ 0.35355339059327378636865546468470711261034011840820,
+ 0.35355339059327378636865546468470711261034011840820,
+ -0.35355339059327378636865546468470711261034011840820,
+ -0.35355339059327378636865546468470711261034011840820,
+ 0.35355339059327378636865546468470711261034011840820, },
+
+ { 0.27778511650980114433551193542371038347482681274414,
+ -0.49039264020161532631192358167027123272418975830078,
+ 0.09754516100806412404189416065491968765854835510254,
+ 0.41573480615127261783570133957255166023969650268555,
+ -0.41573480615127261783570133957255166023969650268555,
+ -0.09754516100806412404189416065491968765854835510254,
+ 0.49039264020161532631192358167027123272418975830078,
+ -0.27778511650980114433551193542371038347482681274414, },
+
+ { 0.19134171618254491864519195587490685284137725830078,
+ -0.46193976625564336924156805253005586564540863037109,
+ 0.46193976625564336924156805253005586564540863037109,
+ -0.19134171618254491864519195587490685284137725830078,
+ -0.19134171618254491864519195587490685284137725830078,
+ 0.46193976625564336924156805253005586564540863037109,
+ -0.46193976625564336924156805253005586564540863037109,
+ 0.19134171618254491864519195587490685284137725830078, },
+
+ { 0.09754516100806416567525758409828995354473590850830,
+ -0.27778511650980108882436070416588336229324340820312,
+ 0.41573480615127267334685257083037868142127990722656,
+ -0.49039264020161521528962111915461719036102294921875,
+ 0.49039264020161521528962111915461719036102294921875,
+ -0.41573480615127267334685257083037868142127990722656,
+ 0.27778511650980108882436070416588336229324340820312,
+ -0.09754516100806416567525758409828995354473590850830 }
+};
+
+/* A 16x16 1D DCT basis (each ROW is a vector of the forward transform basis */
+
+const gfloat DCTbasis16x16[16][16] = {
+ { 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000,
+ 0.25000000000000000000000000000000000000000000000000, },
+
+ { 0.35185093438159564804834644746733829379081726074219,
+ 0.33832950029358815902114088203234132379293441772461,
+ 0.31180625324666783049210039280296768993139266967773,
+ 0.27330046675043939696791994720115326344966888427734,
+ 0.22429189658565909515353098413470434024930000305176,
+ 0.16666391461943663721001485100714489817619323730469,
+ 0.10263113188058936575686175274313427507877349853516,
+ 0.03465429229977286945674208595846721436828374862671,
+ -0.03465429229977286945674208595846721436828374862671,
+ -0.10263113188058936575686175274313427507877349853516,
+ -0.16666391461943663721001485100714489817619323730469,
+ -0.22429189658565909515353098413470434024930000305176,
+ -0.27330046675043939696791994720115326344966888427734,
+ -0.31180625324666783049210039280296768993139266967773,
+ -0.33832950029358815902114088203234132379293441772461,
+ -0.35185093438159564804834644746733829379081726074219, },
+
+ { 0.34675996133053688108560663749813102185726165771484,
+ 0.29396890060483971129912106334813870489597320556641,
+ 0.19642373959677555950165128706430550664663314819336,
+ 0.06897484482073575062788250988887739367783069610596,
+ -0.06897484482073575062788250988887739367783069610596,
+ -0.19642373959677555950165128706430550664663314819336,
+ -0.29396890060483971129912106334813870489597320556641,
+ -0.34675996133053688108560663749813102185726165771484,
+ -0.34675996133053688108560663749813102185726165771484,
+ -0.29396890060483971129912106334813870489597320556641,
+ -0.19642373959677555950165128706430550664663314819336,
+ -0.06897484482073575062788250988887739367783069610596,
+ 0.06897484482073575062788250988887739367783069610596,
+ 0.19642373959677555950165128706430550664663314819336,
+ 0.29396890060483971129912106334813870489597320556641,
+ 0.34675996133053688108560663749813102185726165771484, },
+
+ { 0.33832950029358815902114088203234132379293441772461,
+ 0.22429189658565906739795536850579082965850830078125,
+ 0.03465429229977286251784818205123883672058582305908,
+ -0.16666391461943663721001485100714489817619323730469,
+ -0.31180625324666783049210039280296768993139266967773,
+ -0.35185093438159559253719521620951127260923385620117,
+ -0.27330046675043934145676871594332624226808547973633,
+ -0.10263113188058933800128613711422076448798179626465,
+ 0.10263113188058933800128613711422076448798179626465,
+ 0.27330046675043934145676871594332624226808547973633,
+ 0.35185093438159559253719521620951127260923385620117,
+ 0.31180625324666783049210039280296768993139266967773,
+ 0.16666391461943663721001485100714489817619323730469,
+ -0.03465429229977286251784818205123883672058582305908,
+ -0.22429189658565906739795536850579082965850830078125,
+ -0.33832950029358815902114088203234132379293441772461, },
+
+ { 0.32664074121909414394338000420248135924339294433594,
+ 0.13529902503654925305376366395648801699280738830566,
+ -0.13529902503654925305376366395648801699280738830566,
+ -0.32664074121909414394338000420248135924339294433594,
+ -0.32664074121909414394338000420248135924339294433594,
+ -0.13529902503654925305376366395648801699280738830566,
+ 0.13529902503654925305376366395648801699280738830566,
+ 0.32664074121909414394338000420248135924339294433594,
+ 0.32664074121909414394338000420248135924339294433594,
+ 0.13529902503654925305376366395648801699280738830566,
+ -0.13529902503654925305376366395648801699280738830566,
+ -0.32664074121909414394338000420248135924339294433594,
+ -0.32664074121909414394338000420248135924339294433594,
+ -0.13529902503654925305376366395648801699280738830566,
+ 0.13529902503654925305376366395648801699280738830566,
+ 0.32664074121909414394338000420248135924339294433594, },
+
+ { 0.31180625324666783049210039280296768993139266967773,
+ 0.03465429229977286251784818205123883672058582305908,
+ -0.27330046675043939696791994720115326344966888427734,
+ -0.33832950029358821453229211329016834497451782226562,
+ -0.10263113188058936575686175274313427507877349853516,
+ 0.22429189658565906739795536850579082965850830078125,
+ 0.35185093438159564804834644746733829379081726074219,
+ 0.16666391461943663721001485100714489817619323730469,
+ -0.16666391461943663721001485100714489817619323730469,
+ -0.35185093438159564804834644746733829379081726074219,
+ -0.22429189658565906739795536850579082965850830078125,
+ 0.10263113188058936575686175274313427507877349853516,
+ 0.33832950029358821453229211329016834497451782226562,
+ 0.27330046675043939696791994720115326344966888427734,
+ -0.03465429229977286251784818205123883672058582305908,
+ -0.31180625324666783049210039280296768993139266967773, },
+
+ { 0.29396890060483971129912106334813870489597320556641,
+ -0.06897484482073579226124593333224765956401824951172,
+ -0.34675996133053688108560663749813102185726165771484,
+ -0.19642373959677553174607567143539199605584144592285,
+ 0.19642373959677553174607567143539199605584144592285,
+ 0.34675996133053688108560663749813102185726165771484,
+ 0.06897484482073579226124593333224765956401824951172,
+ -0.29396890060483971129912106334813870489597320556641,
+ -0.29396890060483971129912106334813870489597320556641,
+ 0.06897484482073579226124593333224765956401824951172,
+ 0.34675996133053688108560663749813102185726165771484,
+ 0.19642373959677553174607567143539199605584144592285,
+ -0.19642373959677553174607567143539199605584144592285,
+ -0.34675996133053688108560663749813102185726165771484,
+ -0.06897484482073579226124593333224765956401824951172,
+ 0.29396890060483971129912106334813870489597320556641, },
+
+ { 0.27330046675043939696791994720115326344966888427734,
+ -0.16666391461943663721001485100714489817619323730469,
+ -0.33832950029358821453229211329016834497451782226562,
+ 0.03465429229977287639563598986569559201598167419434,
+ 0.35185093438159564804834644746733829379081726074219,
+ 0.10263113188058935187907394492867751978337764739990,
+ -0.31180625324666783049210039280296768993139266967773,
+ -0.22429189658565909515353098413470434024930000305176,
+ 0.22429189658565909515353098413470434024930000305176,
+ 0.31180625324666783049210039280296768993139266967773,
+ -0.10263113188058935187907394492867751978337764739990,
+ -0.35185093438159564804834644746733829379081726074219,
+ -0.03465429229977287639563598986569559201598167419434,
+ 0.33832950029358821453229211329016834497451782226562,
+ 0.16666391461943663721001485100714489817619323730469,
+ -0.27330046675043939696791994720115326344966888427734, },
+
+ { 0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ -0.25000000000000005551115123125782702118158340454102,
+ 0.25000000000000005551115123125782702118158340454102, },
+
+ { 0.22429189658565909515353098413470434024930000305176,
+ -0.31180625324666783049210039280296768993139266967773,
+ -0.10263113188058937963464956055759103037416934967041,
+ 0.35185093438159564804834644746733829379081726074219,
+ -0.03465429229977282088448475860786857083439826965332,
+ -0.33832950029358815902114088203234132379293441772461,
+ 0.16666391461943658169886361974931787699460983276367,
+ 0.27330046675043934145676871594332624226808547973633,
+ -0.27330046675043934145676871594332624226808547973633,
+ -0.16666391461943658169886361974931787699460983276367,
+ 0.33832950029358815902114088203234132379293441772461,
+ 0.03465429229977282088448475860786857083439826965332,
+ -0.35185093438159564804834644746733829379081726074219,
+ 0.10263113188058937963464956055759103037416934967041,
+ 0.31180625324666783049210039280296768993139266967773,
+ -0.22429189658565909515353098413470434024930000305176, },
+
+ { 0.19642373959677558725722690269321901723742485046387,
+ -0.34675996133053693659675786875595804303884506225586,
+ 0.06897484482073573675009470207442063838243484497070,
+ 0.29396890060483971129912106334813870489597320556641,
+ -0.29396890060483971129912106334813870489597320556641,
+ -0.06897484482073573675009470207442063838243484497070,
+ 0.34675996133053693659675786875595804303884506225586,
+ -0.19642373959677558725722690269321901723742485046387,
+ -0.19642373959677558725722690269321901723742485046387,
+ 0.34675996133053693659675786875595804303884506225586,
+ -0.06897484482073573675009470207442063838243484497070,
+ -0.29396890060483971129912106334813870489597320556641,
+ 0.29396890060483971129912106334813870489597320556641,
+ 0.06897484482073573675009470207442063838243484497070,
+ -0.34675996133053693659675786875595804303884506225586,
+ 0.19642373959677558725722690269321901723742485046387, },
+
+ { 0.16666391461943669272116608226497191935777664184570,
+ -0.35185093438159559253719521620951127260923385620117,
+ 0.22429189658565901188680413724796380847692489624023,
+ 0.10263113188058929636792271367085049860179424285889,
+ -0.33832950029358821453229211329016834497451782226562,
+ 0.27330046675043939696791994720115326344966888427734,
+ 0.03465429229977293190678722112352261319756507873535,
+ -0.31180625324666777498094916154514066874980926513672,
+ 0.31180625324666777498094916154514066874980926513672,
+ -0.03465429229977293190678722112352261319756507873535,
+ -0.27330046675043939696791994720115326344966888427734,
+ 0.33832950029358821453229211329016834497451782226562,
+ -0.10263113188058929636792271367085049860179424285889,
+ -0.22429189658565901188680413724796380847692489624023,
+ 0.35185093438159559253719521620951127260923385620117,
+ -0.16666391461943669272116608226497191935777664184570, },
+
+ { 0.13529902503654928080933927958540152758359909057617,
+ -0.32664074121909414394338000420248135924339294433594,
+ 0.32664074121909414394338000420248135924339294433594,
+ -0.13529902503654928080933927958540152758359909057617,
+ -0.13529902503654928080933927958540152758359909057617,
+ 0.32664074121909414394338000420248135924339294433594,
+ -0.32664074121909414394338000420248135924339294433594,
+ 0.13529902503654928080933927958540152758359909057617,
+ 0.13529902503654928080933927958540152758359909057617,
+ -0.32664074121909414394338000420248135924339294433594,
+ 0.32664074121909414394338000420248135924339294433594,
+ -0.13529902503654928080933927958540152758359909057617,
+ -0.13529902503654928080933927958540152758359909057617,
+ 0.32664074121909414394338000420248135924339294433594,
+ -0.32664074121909414394338000420248135924339294433594,
+ 0.13529902503654928080933927958540152758359909057617, },
+
+ { 0.10263113188058933800128613711422076448798179626465,
+ -0.27330046675043939696791994720115326344966888427734,
+ 0.35185093438159564804834644746733829379081726074219,
+ -0.31180625324666788600325162406079471111297607421875,
+ 0.16666391461943666496559046663605840876698493957520,
+ 0.03465429229977289027342379768015234731137752532959,
+ -0.22429189658565906739795536850579082965850830078125,
+ 0.33832950029358821453229211329016834497451782226562,
+ -0.33832950029358821453229211329016834497451782226562,
+ 0.22429189658565906739795536850579082965850830078125,
+ -0.03465429229977289027342379768015234731137752532959,
+ -0.16666391461943666496559046663605840876698493957520,
+ 0.31180625324666788600325162406079471111297607421875,
+ -0.35185093438159564804834644746733829379081726074219,
+ 0.27330046675043939696791994720115326344966888427734,
+ -0.10263113188058933800128613711422076448798179626465, },
+
+ { 0.06897484482073577838345812551779090426862239837646,
+ -0.19642373959677555950165128706430550664663314819336,
+ 0.29396890060483971129912106334813870489597320556641,
+ -0.34675996133053688108560663749813102185726165771484,
+ 0.34675996133053688108560663749813102185726165771484,
+ -0.29396890060483971129912106334813870489597320556641,
+ 0.19642373959677555950165128706430550664663314819336,
+ -0.06897484482073577838345812551779090426862239837646,
+ -0.06897484482073577838345812551779090426862239837646,
+ 0.19642373959677555950165128706430550664663314819336,
+ -0.29396890060483971129912106334813870489597320556641,
+ 0.34675996133053688108560663749813102185726165771484,
+ -0.34675996133053688108560663749813102185726165771484,
+ 0.29396890060483971129912106334813870489597320556641,
+ -0.19642373959677555950165128706430550664663314819336,
+ 0.06897484482073577838345812551779090426862239837646, },
+
+ { 0.03465429229977292496789331721629423554986715316772,
+ -0.10263113188058928249013490585639374330639839172363,
+ 0.16666391461943666496559046663605840876698493957520,
+ -0.22429189658565903964237975287687731906771659851074,
+ 0.27330046675043939696791994720115326344966888427734,
+ -0.31180625324666771946979793028731364756822586059570,
+ 0.33832950029358815902114088203234132379293441772461,
+ -0.35185093438159559253719521620951127260923385620117,
+ 0.35185093438159559253719521620951127260923385620117,
+ -0.33832950029358815902114088203234132379293441772461,
+ 0.31180625324666771946979793028731364756822586059570,
+ -0.27330046675043939696791994720115326344966888427734,
+ 0.22429189658565903964237975287687731906771659851074,
+ -0.16666391461943666496559046663605840876698493957520,
+ 0.10263113188058928249013490585639374330639839172363,
+ -0.03465429229977292496789331721629423554986715316772 }
+};
\ No newline at end of file
diff --git a/operations/common-cxx/denoise-dct.cc b/operations/common-cxx/denoise-dct.cc
new file mode 100644
index 000000000..b44bfae10
--- /dev/null
+++ b/operations/common-cxx/denoise-dct.cc
@@ -0,0 +1,486 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2022 Thomas Manni <thomas manni free fr>
+ *
+ * following the paper (without channels decorellation)
+ * Guoshen Yu, and Guillermo Sapiro
+ * DCT Image Denoising: a Simple and Effective Image Denoising Algorithm
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_PROPERTIES
+
+enum_start (gegl_denoise_dct_patchsize)
+ enum_value (GEGL_DENOISE_DCT_8X8, "8x8", "8x8")
+ enum_value (GEGL_DENOISE_DCT_16X16, "16x16", "16x16")
+enum_end (GeglDenoiseDctPatchsize)
+
+property_enum (patch_size, _("Patch size"),
+ GeglDenoiseDctPatchsize, gegl_denoise_dct_patchsize,
+ GEGL_DENOISE_DCT_8X8)
+ description (_("Size of patches used to denoise"))
+
+property_double (sigma, _("Strength"), 5.0)
+ description (_("Noise standart deviation"))
+ value_range (1., 100.)
+
+#else
+
+#define GEGL_OP_FILTER
+#define GEGL_OP_NAME denoise_dct
+#define GEGL_OP_C_SOURCE denoise-dct.cc
+#include "gegl-op.h"
+#include "dct-basis.inc"
+
+/* 1 dimensional Discret Cosine Transform of a signal of size 8x1. */
+
+static void
+dct_1d_8x8 (gfloat *in,
+ gfloat *out,
+ gboolean forward)
+{
+ gint i, j;
+
+ if (forward)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ out[0] += in[i*3] * DCTbasis8x8[j][i];
+ out[1] += in[i*3+1] * DCTbasis8x8[j][i];
+ out[2] += in[i*3+2] * DCTbasis8x8[j][i];
+ }
+
+ out += 3;
+ }
+ }
+ else
+ {
+ for (j = 0; j < 8; j++)
+ {
+ for (i = 0; i < 8; i ++)
+ {
+ out[0] += in[i*3] * DCTbasis8x8[i][j];
+ out[1] += in[i*3+1] * DCTbasis8x8[i][j];
+ out[2] += in[i*3+2] * DCTbasis8x8[i][j];
+ }
+
+ out += 3;
+ }
+ }
+}
+
+/* 1 dimensional Discret Cosine Transform of a signal of size 16x1. */
+
+static void
+dct_1d_16x16 (gfloat *in,
+ gfloat *out,
+ gboolean forward)
+{
+ gint i, j;
+
+ if (forward)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ out[0] += in[i*3] * DCTbasis16x16[j][i];
+ out[1] += in[i*3+1] * DCTbasis16x16[j][i];
+ out[2] += in[i*3+2] * DCTbasis16x16[j][i];
+ }
+
+ out += 3;
+ }
+ }
+ else
+ {
+ for (j = 0; j < 16; j++)
+ {
+ for (i = 0; i < 16; i ++)
+ {
+ out[0] += in[i*3] * DCTbasis16x16[i][j];
+ out[1] += in[i*3+1] * DCTbasis16x16[i][j];
+ out[2] += in[i*3+2] * DCTbasis16x16[i][j];
+ }
+
+ out += 3;
+ }
+ }
+}
+
+/* 2 dimensional DCT of a 8x8 (or 16x16) patch */
+
+static void
+dct_2d (gfloat *patch,
+ gint patch_size,
+ gboolean forward)
+{
+ gfloat *tmp1;
+ gfloat *tmp2;
+ gint x, y;
+
+ tmp1 = g_new0 (gfloat, patch_size * patch_size * 3);
+ tmp2 = g_new (gfloat, patch_size * patch_size * 3);
+
+ /* transform row by row */
+
+ if (patch_size == 8)
+ {
+ for (y = 0; y < 8; y++)
+ {
+ dct_1d_8x8 (patch + y * 8 * 3,
+ tmp1 + y * 8 * 3,
+ forward);
+ }
+ }
+ else
+ {
+ for (y = 0; y < 16; y++)
+ {
+ dct_1d_16x16 (patch + y * 16 * 3,
+ tmp1 + y * 16 * 3,
+ forward);
+ }
+ }
+
+ /* transform column by column (by transposing the matrix, transforming row by
+ * row, and transposing again the matrix.)
+ */
+
+ for (y = 0; y < patch_size; y++)
+ {
+ for (x = 0; x < patch_size; x++)
+ {
+ tmp2[(y + x * patch_size) * 3] = tmp1[(x + y * patch_size) * 3];
+ tmp2[(y + x * patch_size) * 3+1] = tmp1[(x + y * patch_size) * 3+1];
+ tmp2[(y + x * patch_size) * 3+2] = tmp1[(x + y * patch_size) * 3+2];
+ }
+ }
+
+ memset (tmp1, 0.f, patch_size * patch_size * 3 * sizeof(gfloat));
+
+ if (patch_size == 8)
+ {
+ for (y = 0; y < 8; y++)
+ {
+ dct_1d_8x8 (tmp2 + y * 8 * 3,
+ tmp1 + y * 8 * 3,
+ forward);
+ }
+ }
+ else
+ {
+ for (y = 0; y < 16; y++)
+ {
+ dct_1d_16x16 (tmp2 + y * 16 * 3,
+ tmp1 + y * 16 * 3,
+ forward);
+ }
+ }
+
+ for (y = 0; y < patch_size; y++)
+ {
+ for (x = 0; x < patch_size; x++)
+ {
+ patch[(y + x * patch_size) * 3] = tmp1[(x + y * patch_size) * 3];
+ patch[(y + x * patch_size) * 3+1] = tmp1[(x + y * patch_size) * 3+1];
+ patch[(y + x * patch_size) * 3+2] = tmp1[(x + y * patch_size) * 3+2];
+ }
+ }
+
+ g_free (tmp1);
+ g_free (tmp2);
+}
+
+static void
+threshold_patch_coefficients (gfloat *patch,
+ gint patch_n_pixels,
+ gfloat threshold)
+{
+ gint i;
+ gfloat *p = patch;
+
+ for (i = 0; i < patch_n_pixels; i++)
+ {
+ p[0] = ABS (p[0]) < threshold ? 0.f : p[0];
+ p[1] = ABS (p[1]) < threshold ? 0.f : p[1];
+ p[2] = ABS (p[2]) < threshold ? 0.f : p[2];
+ p += 3;
+ }
+}
+
+static void
+prepare (GeglOperation *operation)
+{
+ const Babl *space = gegl_operation_get_source_space (operation, "input");
+ const Babl *format = babl_format_with_space ("R'G'B'A float", space);
+
+ gegl_operation_set_format (operation, "input", format);
+ gegl_operation_set_format (operation, "output", format);
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation *operation,
+ const GeglRectangle *roi)
+{
+ const GeglRectangle *in_rect =
+ gegl_operation_source_get_bounding_box (operation, "input");
+
+ if (! in_rect || gegl_rectangle_is_infinite_plane (in_rect))
+ return *roi;
+
+ return *in_rect;
+}
+
+static GeglRectangle
+get_required_for_output (GeglOperation *operation,
+ const gchar *input_pad,
+ const GeglRectangle *roi)
+{
+ return get_cached_region (operation, roi);
+}
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ const Babl *space = gegl_operation_get_source_space (operation, "input");
+ const Babl *rgb_f = babl_format_with_space ("R'G'B' float", space);
+ const Babl *rgba_f = babl_format_with_space ("R'G'B'A float", space);
+
+ GeglBuffer *sum;
+ gint width, height;
+ gint patch_size;
+ gint patch_len;
+ gfloat threshold;
+ gdouble progress;
+ gint *patch_n_x;
+ gint *patch_n_y;
+ gint i;
+
+ width = gegl_buffer_get_width (input);
+ height = gegl_buffer_get_height (input);
+ patch_size = o->patch_size == GEGL_DENOISE_DCT_8X8 ? 8 : 16;
+ patch_len = patch_size * patch_size;
+ threshold = 3.f * (gfloat) o->sigma / 255.;
+
+ sum = gegl_buffer_new (GEGL_RECTANGLE(0, 0, width, height), rgb_f);
+
+ patch_n_x = g_new (gint, width);
+ patch_n_y = g_new (gint, height);
+
+ GeglBufferIterator *iter;
+ gint x_offset;
+
+ gegl_operation_progress (operation, 0.0, (gchar *) "");
+
+ for (x_offset = 0; x_offset < patch_size; x_offset++)
+ {
+ /* Input buffer is split into vertical non-overlapping regions.
+ * Regions are distributed among threads.
+ */
+
+ gint n_regions = (width - x_offset) / patch_size;
+
+ gegl_parallel_distribute_range (
+ n_regions, gegl_operation_get_pixels_per_thread (operation)
+ / (height * patch_size),
+ [=] (gint region0, gint n)
+ {
+ gint x, y, j;
+ gfloat *in_buf;
+ gfloat *sum_buf;
+ gfloat *patch_buf;
+
+ in_buf = g_new (gfloat, patch_size * height * 3);
+ sum_buf = g_new (gfloat, patch_size * height * 3);
+ patch_buf = g_new (gfloat, patch_len * 3);
+
+ for (x = region0; x < region0 + n; x++)
+ {
+ /* Threads manage one region at a time:
+ * for each overlapping patch from top to bottom:
+ * 1. extract patch
+ * 2. dc transform, thresholding, inverse transform
+ * 3. sum the patch result into the sum memory buffer
+ * set the gegl buffer with the sum memory buffer
+ */
+
+ GeglRectangle roi = {x * patch_size + x_offset,
+ 0,
+ patch_size,
+ height};
+ gint patch_offset = 0;
+
+ gegl_buffer_get (input, &roi, 1.0, rgb_f, in_buf,
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+ gegl_buffer_get (sum, &roi, 1.0, rgb_f, sum_buf,
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+ for (y = 0; y < height - patch_size + 1; y++)
+ {
+ gfloat *sum_p = sum_buf + patch_offset;
+ gfloat *patch_p = patch_buf;
+
+ memcpy (patch_buf, in_buf + patch_offset,
+ patch_len * 3 * sizeof(gfloat));
+ dct_2d (patch_buf, patch_size, TRUE);
+ threshold_patch_coefficients (patch_buf, patch_len, threshold);
+ dct_2d (patch_buf, patch_size, FALSE);
+
+ for (j = 0; j < patch_len * 3; j++)
+ {
+ *sum_p++ += *patch_p++;
+ }
+
+ patch_offset += patch_size * 3;
+ }
+
+ gegl_buffer_set (sum, &roi, 0, rgb_f, sum_buf,
+ GEGL_AUTO_ROWSTRIDE);
+ }
+
+ g_free (in_buf);
+ g_free (sum_buf);
+ g_free (patch_buf);
+ });
+
+ progress = (gdouble) (x_offset + 1) / (gdouble) patch_size;
+ gegl_operation_progress (operation, progress, (gchar *) "");
+ }
+
+ /* Finally, average the accumulated values of the sum buffer, given the
+ * appropriate number of patches a pixel belongs to.
+ * Put the result in the ouput buffer with the original alpha value.
+ */
+
+ for (i = 0; i < patch_size; i++)
+ {
+ patch_n_x[i] = patch_n_x[width -1 - i] = i+1;
+ patch_n_y[i] = patch_n_y[height -1 -i] = i+1;
+ }
+
+ for (i = patch_size; i <= width - patch_size; i++)
+ patch_n_x[i] = patch_size;
+
+ for (i = patch_size; i <= height - patch_size; i++)
+ patch_n_y[i] = patch_size;
+
+ iter = gegl_buffer_iterator_new (input, NULL, 0, rgba_f,
+ GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 3);
+
+ gegl_buffer_iterator_add (iter, sum, NULL, 0, rgb_f,
+ GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+ gegl_buffer_iterator_add (iter, output, NULL, 0, rgba_f,
+ GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+
+ while (gegl_buffer_iterator_next (iter))
+ {
+ gfloat *in = (gfloat *) iter->items[0].data;
+ gfloat *sum = (gfloat *) iter->items[1].data;
+ gfloat *out = (gfloat *) iter->items[2].data;
+ GeglRectangle *roi = &iter->items[0].roi;
+ gint x, y;
+
+ for (y = roi->y; y < roi->y + roi->height; y++)
+ {
+ for (x = roi->x; x < roi->x + roi->width; x++)
+ {
+ gint n_patches = patch_n_x[x] * patch_n_y[y];
+ gfloat n = 1.f / (gfloat) n_patches;
+
+ out[0] = sum[0] * n;
+ out[1] = sum[1] * n;
+ out[2] = sum[2] * n;
+ out[3] = in[3];
+
+ in += 4;
+ sum += 3;
+ out += 4;
+ }
+ }
+ }
+
+ gegl_operation_progress (operation, 1.0, (gchar *) "");
+
+ g_object_unref (sum);
+ g_free (patch_n_x);
+ g_free (patch_n_y);
+
+ return TRUE;
+}
+
+static gboolean
+operation_process (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level)
+{
+ GeglOperationClass *operation_class;
+
+ const GeglRectangle *in_rect =
+ gegl_operation_source_get_bounding_box (operation, "input");
+
+ if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
+ {
+ gpointer in = gegl_operation_context_get_object (context, "input");
+ gegl_operation_context_take_object (context, "output",
+ G_OBJECT(g_object_ref (in)));
+ return TRUE;
+ }
+
+ operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);
+
+ return operation_class->process (operation, context, output_prop, result,
+ gegl_operation_context_get_level (context));
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationFilterClass *filter_class;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
+
+ operation_class->threaded = FALSE;
+ operation_class->prepare = prepare;
+ operation_class->process = operation_process;
+ operation_class->get_cached_region = get_cached_region;
+ operation_class->get_required_for_output = get_required_for_output;
+ filter_class->process = process;
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "gegl:denoise-dct",
+ "title", _("Denoise DCT"),
+ "categories", "enhance:noise-reduction",
+ "description", _("Denoising algorithm using a per-patch DCT thresholding"),
+ NULL);
+}
+
+#endif
diff --git a/operations/common-cxx/meson.build b/operations/common-cxx/meson.build
index 2d6c18b58..146967fae 100644
--- a/operations/common-cxx/meson.build
+++ b/operations/common-cxx/meson.build
@@ -1,5 +1,6 @@
gegl_common_cxx_sources = files(
+ 'denoise-dct.cc',
'distance-transform.cc',
'focus-blur.c',
'lens-blur.cc',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b47dc97c9..fce3d1232 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -132,6 +132,7 @@ operations/common/weighted-blend.c
operations/common/write-buffer.c
operations/common-cxx/distance-transform.cc
operations/common-cxx/focus-blur.c
+operations/common-cxx/denoise-dct.cc
operations/common-cxx/lens-blur.cc
operations/common-cxx/piecewise-blend.cc
operations/common-cxx/variable-blur.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]