Finalize median.h

- Added median 13, 49, and 81
- Integrated Ingo's SSE optimization for "5x5 strong"
- Converted `MIDDLE4OF6`
- Refactored `enum mediantype`
This commit is contained in:
Flössie 2016-06-28 21:49:07 +02:00
parent a3bfd035fa
commit 5cbff43191
4 changed files with 5663 additions and 91 deletions

View File

@ -95,29 +95,29 @@ float media(float *elements, int N)
return elements[N >> 1]; return elements[N >> 1];
} }
void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width, const int height, const mediantype medianType, const int iterations, const int numThreads, float **buffer) void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width, const int height, const Median medianType, const int iterations, const int numThreads, float **buffer)
{ {
int border = 1; int border = 1;
switch(medianType) { switch (medianType) {
case MED_3X3SOFT: case Median::SIZE_3X3_SOFT:
case MED_3X3STRONG: case Median::SIZE_3X3_STRONG:
border = 1; border = 1;
break; break;
case MED_5X5SOFT: case Median::SIZE_5X5_SOFT:
border = 2; border = 2;
break; break;
case MED_5X5STRONG: case Median::SIZE_5X5_STRONG:
border = 2; border = 2;
break; break;
case MED_7X7: case Median::SIZE_7X7:
border = 3; border = 3;
break; break;
default: // includes MED_9X9 default: // includes Median::SIZE_9X9
border = 4; border = 4;
} }
@ -157,11 +157,11 @@ void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width,
} }
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for num_threads(numThreads) if(numThreads>1) #pragma omp parallel for num_threads(numThreads) if(numThreads>1) schedule(dynamic,16)
#endif #endif
for (int i = border; i < height - border; i++) { for (int i = border; i < height - border; i++) {
if(medianType == MED_3X3SOFT) { if (medianType == Median::SIZE_3X3_SOFT) {
int j; int j;
for (j = 0; j < border; j++) { for (j = 0; j < border; j++) {
@ -175,7 +175,7 @@ void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width,
for(; j < width; j++) { for(; j < width; j++) {
medianOut[i][j] = medianIn[i][j]; medianOut[i][j] = medianIn[i][j];
} }
} else if(medianType == MED_3X3STRONG) { } else if (medianType == Median::SIZE_3X3_STRONG) {
int j; int j;
for (j = 0; j < border; j++) { for (j = 0; j < border; j++) {
@ -189,7 +189,7 @@ void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width,
for(; j < width; j++) { for(; j < width; j++) {
medianOut[i][j] = medianIn[i][j]; medianOut[i][j] = medianIn[i][j];
} }
} else if(medianType == MED_5X5SOFT) { } else if (medianType == Median::SIZE_5X5_SOFT) {
int j; int j;
for (j = 0; j < border; j++) { for (j = 0; j < border; j++) {
@ -217,13 +217,21 @@ void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width,
for(; j < width; j++) { for(; j < width; j++) {
medianOut[i][j] = medianIn[i][j]; medianOut[i][j] = medianIn[i][j];
} }
} else if(medianType == MED_5X5STRONG) { } else if(medianType == Median::SIZE_5X5_STRONG) {
int j; int j;
for (j = 0; j < border; j++) { for (j = 0; j < border; j++) {
medianOut[i][j] = medianIn[i][j]; medianOut[i][j] = medianIn[i][j];
} }
#ifdef __SSE2__
for (; j < width - border - 3; j += 4) {
STVFU(medianOut[i][j], median(LVFU(medianIn[i][j]), LVFU(medianIn[i - 1][j]), LVFU(medianIn[i + 1][j]), LVFU(medianIn[i][j + 1]), LVFU(medianIn[i][j - 1]), LVFU(medianIn[i - 1][j - 1]), LVFU(medianIn[i - 1][j + 1]), LVFU(medianIn[i + 1][j - 1]), LVFU(medianIn[i + 1][j + 1]),
LVFU(medianIn[i - 2][j]), LVFU(medianIn[i + 2][j]), LVFU(medianIn[i][j + 2]), LVFU(medianIn[i][j - 2]), LVFU(medianIn[i - 2][j - 2]), LVFU(medianIn[i - 2][j + 2]), LVFU(medianIn[i + 2][j - 2]), LVFU(medianIn[i + 2][j + 2]),
LVFU(medianIn[i - 2][j + 1]), LVFU(medianIn[i + 2][j + 1]), LVFU(medianIn[i - 1][j + 2]), LVFU(medianIn[i - 1][j - 2]), LVFU(medianIn[i - 2][j - 1]), LVFU(medianIn[i + 2][j - 1]), LVFU(medianIn[i + 1][j + 2]), LVFU(medianIn[i + 1][j - 2])));
}
#endif
for (; j < width - border; j++) { for (; j < width - border; j++) {
medianOut[i][j] = median(medianIn[i][j], medianIn[i - 1][j], medianIn[i + 1][j], medianIn[i][j + 1], medianIn[i][j - 1], medianIn[i - 1][j - 1], medianIn[i - 1][j + 1], medianIn[i + 1][j - 1], medianIn[i + 1][j + 1], medianOut[i][j] = median(medianIn[i][j], medianIn[i - 1][j], medianIn[i + 1][j], medianIn[i][j + 1], medianIn[i][j - 1], medianIn[i - 1][j - 1], medianIn[i - 1][j + 1], medianIn[i + 1][j - 1], medianIn[i + 1][j + 1],
medianIn[i - 2][j], medianIn[i + 2][j], medianIn[i][j + 2], medianIn[i][j - 2], medianIn[i - 2][j - 2], medianIn[i - 2][j + 2], medianIn[i + 2][j - 2], medianIn[i + 2][j + 2], medianIn[i - 2][j], medianIn[i + 2][j], medianIn[i][j + 2], medianIn[i][j - 2], medianIn[i - 2][j - 2], medianIn[i - 2][j + 2], medianIn[i + 2][j - 2], medianIn[i + 2][j + 2],
@ -233,8 +241,8 @@ void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width,
for(; j < width; j++) { for(; j < width; j++) {
medianOut[i][j] = medianIn[i][j]; medianOut[i][j] = medianIn[i][j];
} }
} else if (medianType == MED_7X7) { } else if (medianType == Median::SIZE_7X7) {
std::array<float, 49> pp = {}; std::array<float, 49> pp;
int j; int j;
for (j = 0; j < border; j++) { for (j = 0; j < border; j++) {
@ -257,8 +265,8 @@ void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width,
for(; j < width; j++) { for(; j < width; j++) {
medianOut[i][j] = medianIn[i][j]; medianOut[i][j] = medianIn[i][j];
} }
} else { // includes MED_9X9 } else { // includes Median::SIZE_9X9
std::array<float, 81> pp = {}; std::array<float, 81> pp;
int j; int j;
for (j = 0; j < border; j++) { for (j = 0; j < border; j++) {
@ -1230,50 +1238,50 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef
tmL[i] = new float[wid]; tmL[i] = new float[wid];
} }
mediantype medianTypeL = MED_3X3SOFT; Median medianTypeL = Median::SIZE_3X3_SOFT;
mediantype medianTypeAB = MED_3X3SOFT; Median medianTypeAB = Median::SIZE_3X3_SOFT;
if(dnparams.medmethod == "soft") { if(dnparams.medmethod == "soft") {
if(metchoice != 4) { if(metchoice != 4) {
medianTypeL = medianTypeAB = MED_3X3SOFT; medianTypeL = medianTypeAB = Median::SIZE_3X3_SOFT;
} else { } else {
medianTypeL = MED_3X3SOFT; medianTypeL = Median::SIZE_3X3_SOFT;
medianTypeAB = MED_3X3SOFT; medianTypeAB = Median::SIZE_3X3_SOFT;
} }
} else if(dnparams.medmethod == "33") { } else if(dnparams.medmethod == "33") {
if(metchoice != 4) { if(metchoice != 4) {
medianTypeL = medianTypeAB = MED_3X3STRONG; medianTypeL = medianTypeAB = Median::SIZE_3X3_STRONG;
} else { } else {
medianTypeL = MED_3X3SOFT; medianTypeL = Median::SIZE_3X3_SOFT;
medianTypeAB = MED_3X3STRONG; medianTypeAB = Median::SIZE_3X3_STRONG;
} }
} else if(dnparams.medmethod == "55soft") { } else if(dnparams.medmethod == "55soft") {
if(metchoice != 4) { if(metchoice != 4) {
medianTypeL = medianTypeAB = MED_5X5SOFT; medianTypeL = medianTypeAB = Median::SIZE_5X5_SOFT;
} else { } else {
medianTypeL = MED_3X3SOFT; medianTypeL = Median::SIZE_3X3_SOFT;
medianTypeAB = MED_5X5SOFT; medianTypeAB = Median::SIZE_5X5_SOFT;
} }
} else if(dnparams.medmethod == "55") { } else if(dnparams.medmethod == "55") {
if(metchoice != 4) { if(metchoice != 4) {
medianTypeL = medianTypeAB = MED_5X5STRONG; medianTypeL = medianTypeAB = Median::SIZE_5X5_STRONG;
} else { } else {
medianTypeL = MED_3X3STRONG; medianTypeL = Median::SIZE_3X3_STRONG;
medianTypeAB = MED_5X5STRONG; medianTypeAB = Median::SIZE_5X5_STRONG;
} }
} else if(dnparams.medmethod == "77") { } else if(dnparams.medmethod == "77") {
if(metchoice != 4) { if(metchoice != 4) {
medianTypeL = medianTypeAB = MED_7X7; medianTypeL = medianTypeAB = Median::SIZE_7X7;
} else { } else {
medianTypeL = MED_3X3STRONG; medianTypeL = Median::SIZE_3X3_STRONG;
medianTypeAB = MED_7X7; medianTypeAB = Median::SIZE_7X7;
} }
} else if(dnparams.medmethod == "99") { } else if(dnparams.medmethod == "99") {
if(metchoice != 4) { if(metchoice != 4) {
medianTypeL = medianTypeAB = MED_9X9; medianTypeL = medianTypeAB = Median::SIZE_9X9;
} else { } else {
medianTypeL = MED_5X5SOFT; medianTypeL = Median::SIZE_5X5_SOFT;
medianTypeAB = MED_9X9; medianTypeAB = Median::SIZE_9X9;
} }
} }

View File

@ -184,6 +184,14 @@ class ImProcFunctions
public: public:
enum class Median {
SIZE_3X3_SOFT,
SIZE_3X3_STRONG,
SIZE_5X5_SOFT,
SIZE_5X5_STRONG,
SIZE_7X7,
SIZE_9X9
};
double lumimul[3]; double lumimul[3];
// float chau; // float chau;
@ -310,8 +318,7 @@ public:
enum mediantype {MED_3X3SOFT, MED_3X3STRONG, MED_5X5SOFT, MED_5X5STRONG, MED_7X7, MED_9X9}; void Median_Denoise( float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = NULL);
void Median_Denoise( float **src, float **dst, int width, int height, mediantype medianType, int iterations, int numThreads, float **buffer = NULL);
void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & ctNoisCurve , const NoiseCurve & ctNoisCCcurve , float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi); void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & ctNoisCurve , const NoiseCurve & ctNoisCCcurve , float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi);
void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope); void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope);
void RGB_denoise_info(Imagefloat * src, Imagefloat * calclum, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false); void RGB_denoise_info(Imagefloat * src, Imagefloat * calclum, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);

File diff suppressed because it is too large Load Diff

View File

@ -3439,17 +3439,12 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D
vfloat* pre2 = &buffer[3]; vfloat* pre2 = &buffer[3];
vfloat* post1 = &buffer[6]; vfloat* post1 = &buffer[6];
vfloat* post2 = &buffer[9]; vfloat* post2 = &buffer[9];
vfloat middle[6];
#else #else
float buffer[12]; float buffer[12];
float* pre1 = &buffer[0]; float* pre1 = &buffer[0];
float* pre2 = &buffer[3]; float* pre2 = &buffer[3];
float* post1 = &buffer[6]; float* post1 = &buffer[6];
float* post2 = &buffer[9]; float* post2 = &buffer[9];
float middle[6];
#endif #endif
int px = (row_from - 1) % 3, cx = row_from % 3, nx = 0; int px = (row_from - 1) % 3, cx = row_from % 3, nx = 0;
@ -3473,7 +3468,6 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D
#ifdef __SSE2__ #ifdef __SSE2__
pre1[0] = _mm_setr_ps(rbconv_I[px][0], rbconv_Q[px][0], 0, 0) , pre1[1] = _mm_setr_ps(rbconv_I[cx][0], rbconv_Q[cx][0], 0, 0), pre1[2] = _mm_setr_ps(rbconv_I[nx][0], rbconv_Q[nx][0], 0, 0); pre1[0] = _mm_setr_ps(rbconv_I[px][0], rbconv_Q[px][0], 0, 0) , pre1[1] = _mm_setr_ps(rbconv_I[cx][0], rbconv_Q[cx][0], 0, 0), pre1[2] = _mm_setr_ps(rbconv_I[nx][0], rbconv_Q[nx][0], 0, 0);
pre2[0] = _mm_setr_ps(rbconv_I[px][1], rbconv_Q[px][1], 0, 0) , pre2[1] = _mm_setr_ps(rbconv_I[cx][1], rbconv_Q[cx][1], 0, 0), pre2[2] = _mm_setr_ps(rbconv_I[nx][1], rbconv_Q[nx][1], 0, 0); pre2[0] = _mm_setr_ps(rbconv_I[px][1], rbconv_Q[px][1], 0, 0) , pre2[1] = _mm_setr_ps(rbconv_I[cx][1], rbconv_Q[cx][1], 0, 0), pre2[2] = _mm_setr_ps(rbconv_I[nx][1], rbconv_Q[nx][1], 0, 0);
vfloat temp[7];
// fill first element in rbout_I and rbout_Q // fill first element in rbout_I and rbout_Q
rbout_I[cx][0] = rbconv_I[cx][0]; rbout_I[cx][0] = rbconv_I[cx][0];
@ -3482,12 +3476,12 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D
// median I channel // median I channel
for (int j = 1; j < W - 2; j += 2) { for (int j = 1; j < W - 2; j += 2) {
post1[0] = _mm_setr_ps(rbconv_I[px][j + 1], rbconv_Q[px][j + 1], 0, 0), post1[1] = _mm_setr_ps(rbconv_I[cx][j + 1], rbconv_Q[cx][j + 1], 0, 0), post1[2] = _mm_setr_ps(rbconv_I[nx][j + 1], rbconv_Q[nx][j + 1], 0, 0); post1[0] = _mm_setr_ps(rbconv_I[px][j + 1], rbconv_Q[px][j + 1], 0, 0), post1[1] = _mm_setr_ps(rbconv_I[cx][j + 1], rbconv_Q[cx][j + 1], 0, 0), post1[2] = _mm_setr_ps(rbconv_I[nx][j + 1], rbconv_Q[nx][j + 1], 0, 0);
VMIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); const auto middle = middle4of6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2]);
vfloat medianval = median(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4]); vfloat medianval = median(pre1[0], pre1[1], pre1[2], middle[0], middle[1], middle[2], middle[3]);
rbout_I[cx][j] = medianval[0]; rbout_I[cx][j] = medianval[0];
rbout_Q[cx][j] = medianval[1]; rbout_Q[cx][j] = medianval[1];
post2[0] = _mm_setr_ps(rbconv_I[px][j + 2], rbconv_Q[px][j + 2], 0, 0), post2[1] = _mm_setr_ps(rbconv_I[cx][j + 2], rbconv_Q[cx][j + 2], 0, 0), post2[2] = _mm_setr_ps(rbconv_I[nx][j + 2], rbconv_Q[nx][j + 2], 0, 0); post2[0] = _mm_setr_ps(rbconv_I[px][j + 2], rbconv_Q[px][j + 2], 0, 0), post2[1] = _mm_setr_ps(rbconv_I[cx][j + 2], rbconv_Q[cx][j + 2], 0, 0), post2[2] = _mm_setr_ps(rbconv_I[nx][j + 2], rbconv_Q[nx][j + 2], 0, 0);
medianval = median(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4]); medianval = median(post2[0], post2[1], post2[2], middle[0], middle[1], middle[2], middle[3]);
rbout_I[cx][j + 1] = medianval[0]; rbout_I[cx][j + 1] = medianval[0];
rbout_Q[cx][j + 1] = medianval[1]; rbout_Q[cx][j + 1] = medianval[1];
std::swap(pre1, post1); std::swap(pre1, post1);
@ -3503,7 +3497,6 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D
#else #else
pre1[0] = rbconv_I[px][0], pre1[1] = rbconv_I[cx][0], pre1[2] = rbconv_I[nx][0]; pre1[0] = rbconv_I[px][0], pre1[1] = rbconv_I[cx][0], pre1[2] = rbconv_I[nx][0];
pre2[0] = rbconv_I[px][1], pre2[1] = rbconv_I[cx][1], pre2[2] = rbconv_I[nx][1]; pre2[0] = rbconv_I[px][1], pre2[1] = rbconv_I[cx][1], pre2[2] = rbconv_I[nx][1];
float temp[7];
// fill first element in rbout_I // fill first element in rbout_I
rbout_I[cx][0] = rbconv_I[cx][0]; rbout_I[cx][0] = rbconv_I[cx][0];
@ -3511,10 +3504,10 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D
// median I channel // median I channel
for (int j = 1; j < W - 2; j += 2) { for (int j = 1; j < W - 2; j += 2) {
post1[0] = rbconv_I[px][j + 1], post1[1] = rbconv_I[cx][j + 1], post1[2] = rbconv_I[nx][j + 1]; post1[0] = rbconv_I[px][j + 1], post1[1] = rbconv_I[cx][j + 1], post1[2] = rbconv_I[nx][j + 1];
MIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); const auto middle = middle4of6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2]);
rbout_I[cx][j] = median(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4]); rbout_I[cx][j] = median(pre1[0], pre1[1], pre1[2], middle[0], middle[1], middle[2], middle[3]);
post2[0] = rbconv_I[px][j + 2], post2[1] = rbconv_I[cx][j + 2], post2[2] = rbconv_I[nx][j + 2]; post2[0] = rbconv_I[px][j + 2], post2[1] = rbconv_I[cx][j + 2], post2[2] = rbconv_I[nx][j + 2];
rbout_I[cx][j + 1] = median(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4]); rbout_I[cx][j + 1] = median(post2[0], post2[1], post2[2], middle[0], middle[1], middle[2], middle[3]);
std::swap(pre1, post1); std::swap(pre1, post1);
std::swap(pre2, post2); std::swap(pre2, post2);
} }
@ -3532,10 +3525,10 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D
// median Q channel // median Q channel
for (int j = 1; j < W - 2; j += 2) { for (int j = 1; j < W - 2; j += 2) {
post1[0] = rbconv_Q[px][j + 1], post1[1] = rbconv_Q[cx][j + 1], post1[2] = rbconv_Q[nx][j + 1]; post1[0] = rbconv_Q[px][j + 1], post1[1] = rbconv_Q[cx][j + 1], post1[2] = rbconv_Q[nx][j + 1];
MIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); const auto middle = middle4of6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2]);
rbout_Q[cx][j] = median(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4]); rbout_Q[cx][j] = median(pre1[0], pre1[1], pre1[2], middle[0], middle[1], middle[2], middle[3]);
post2[0] = rbconv_Q[px][j + 2], post2[1] = rbconv_Q[cx][j + 2], post2[2] = rbconv_Q[nx][j + 2]; post2[0] = rbconv_Q[px][j + 2], post2[1] = rbconv_Q[cx][j + 2], post2[2] = rbconv_Q[nx][j + 2];
rbout_Q[cx][j + 1] = median(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4]); rbout_Q[cx][j + 1] = median(post2[0], post2[1], post2[2], middle[0], middle[1], middle[2], middle[3]);
std::swap(pre1, post1); std::swap(pre1, post1);
std::swap(pre2, post2); std::swap(pre2, post2);
} }