From c936dcaef7a7b6de30ad4afc063faf27f98b5ccf Mon Sep 17 00:00:00 2001 From: Samaresh Kumar Singh Date: Sat, 6 Jun 2026 16:36:07 -0500 Subject: [PATCH] Speed up first BGR2Lab and BGR2Luv call by building the color LUT faster The first conversion to Lab or Luv lazily builds a softfloat lookup table, and that build was doing about 108000 software emulated pow calls plus a fully serial 33x33x33 cube loop. This memoizes applyGamma over the 33 grid values and runs the cube loop with parallel_for_, cutting the first call from around 110 ms to around 25 ms on my machine. The per point computation is unchanged so the tables stay bit exact. --- modules/imgproc/src/color_lab.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/modules/imgproc/src/color_lab.cpp b/modules/imgproc/src/color_lab.cpp index fe9888e381..5217d6e5a8 100644 --- a/modules/imgproc/src/color_lab.cpp +++ b/modules/imgproc/src/color_lab.cpp @@ -1160,20 +1160,23 @@ static LABLUVLUT_s16_t initLUTforLABLUVs16(const softfloat & un, const softfloat AutoBuffer RGB2Labprev(LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3); AutoBuffer RGB2Luvprev(LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3); - for(int p = 0; p < LAB_LUT_DIM; p++) + + softfloat gammaTab[LAB_LUT_DIM]; + for(int n = 0; n < LAB_LUT_DIM; n++) + gammaTab[n] = applyGamma(softfloat(n)/lld); + + cv::parallel_for_(cv::Range(0, LAB_LUT_DIM), [&](const cv::Range& prange) + { + for(int p = prange.start; p < prange.end; p++) { for(int q = 0; q < LAB_LUT_DIM; q++) { for(int r = 0; r < LAB_LUT_DIM; r++) { int idx = p*3 + q*LAB_LUT_DIM*3 + r*LAB_LUT_DIM*LAB_LUT_DIM*3; - softfloat R = softfloat(p)/lld; - softfloat G = softfloat(q)/lld; - softfloat B = softfloat(r)/lld; - - R = applyGamma(R); - G = applyGamma(G); - B = applyGamma(B); + softfloat R = gammaTab[p]; + softfloat G = gammaTab[q]; + softfloat B = gammaTab[r]; //RGB 2 Lab LUT building { @@ -1214,6 +1217,7 @@ static LABLUVLUT_s16_t initLUTforLABLUVs16(const softfloat & un, const softfloat } } } + }); int16_t *RGB2LabLUT_s16 = cv::allocSingleton(LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3*8); int16_t *RGB2LuvLUT_s16 = cv::allocSingleton(LAB_LUT_DIM*LAB_LUT_DIM*LAB_LUT_DIM*3*8);