10.1國慶後,知名博主:laviewpbt http://www.cnblogs.com/Imageshop/
發起了一個優化3x3中值模糊的小活動。
俺也參加其中,今天博主laviewpbt 共享了一份不錯的CLAHE代碼。
free精神,真心為其點贊。
故俺也分享這份最快的3x3中值模糊的代碼。
/// 編寫者: laviewpbt, 編寫時間: 2015.10.16, 聯系QQ: 33184777 /// <summary> /// 快速的實現3*3大小的中值模糊,邊緣1像素未做處理。(2015.10.12日) /// </summary> /// <param name="Src">原始數據。</param> /// <param name="Dest">目標數據。</param> /// 百度: Fast median search_ an ANSI C implementation.html /// 優化版本: 落羽の殇 聯系QQ:200759103 static unsigned int* pixGreater = NULL; static unsigned int* pixLess = NULL; static unsigned int cmpTable[256 * 256 * 2] = { 0 }; class autoCmpTable { public: autoCmpTable() { unsigned int x, y, p; unsigned int tableLength = 256 * 256; pixGreater = cmpTable; pixLess = cmpTable + tableLength; for (x = 0; x < 256; x++) { for (y = 0; y < 256; y++) { p = x + y * 256; if (x > y) { pixLess[p] = x; pixGreater[p] = y; } else { pixGreater[p] = x; pixLess[p] = y; } } } } }; static autoCmpTable initCmpTable; IS_RET __stdcall Fastest33MedianBlur(TMatrix *Src, TMatrix *Dest) { if (Src == NULL || Dest == NULL) return IS_RET_ERR_NULLREFERENCE; if (Src->Data == NULL || Dest->Data == NULL) return IS_RET_ERR_NULLREFERENCE; if (Src->Width != Dest->Width || Src->Height != Dest->Height || Src->Channel != Dest->Channel || Src->Depth != Dest->Depth || Src->WidthStep != Dest->WidthStep) return IS_RET_ERR_PARAMISMATCH; if (Src->Depth != IS_DEPTH_8U || Dest->Depth != IS_DEPTH_8U) return IS_RET_ERR_NOTSUPPORTED; IS_RET Ret = IS_RET_OK; if (!pixGreater&&!pixLess) { return IS_RET_ERR_NOTSUPPORTED; } if (Src->Data == Dest->Data) { TMatrix *Clone = NULL; Ret = IS_CloneMatrix(Src, &Clone); if (Ret != IS_RET_OK) return Ret; Ret = Fastest33MedianBlur(Clone, Dest); IS_FreeMatrix(&Clone); return Ret; } unsigned int X, Y, Width = Src->Width, Height = Src->Height; unsigned char *LineP0, *LineP1, *LineP2, *LinePD; unsigned int srcWidthStep = Src->WidthStep; unsigned int dstWidthStep = Dest->WidthStep; unsigned int srcChannel = Src->Channel; unsigned int dstChannel = Dest->Channel; unsigned char* SrcData = Src->Data; unsigned char* DstData = Dest->Data; if (srcChannel == 1) { unsigned int Gray0, Gray1, Gray2, Gray3, Gray4, Gray5, Gray6, Gray7, Gray8, pos; for (Y = 1; Y < Height - 1; Y++) { LineP0 = SrcData + (Y - 1) * srcWidthStep + 1; LineP1 = LineP0 + srcWidthStep; LineP2 = LineP1 + srcWidthStep; LinePD = DstData + Y *dstWidthStep + 1; for (X = 1; X < Width - 1; X++) { Gray0 = LineP0[X - 1]; Gray1 = LineP0[X]; Gray2 = LineP0[X + 1]; Gray3 = LineP1[X - 1]; Gray4 = LineP1[X]; Gray5 = LineP2[X + 1]; Gray6 = LineP2[X - 1]; Gray7 = LineP2[X]; Gray8 = LineP2[X + 1]; /* if (Gray1 > Gray2) Swap(Gray1, Gray2);*/ pos = Gray1 + Gray2 * 256; Gray2 = pixLess[pos]; Gray1 = pixGreater[pos]; /* if (Gray4 > Gray5) Swap(Gray4, Gray5);*/ pos = Gray4 + Gray5 * 256; Gray5 = pixLess[pos]; Gray4 = pixGreater[pos]; /* if (Gray7 > Gray8) Swap(Gray7, Gray8);*/ pos = Gray7 + Gray8 * 256; Gray8 = pixLess[pos]; Gray7 = pixGreater[pos]; /* if (Gray0 > Gray1) Swap(Gray0, Gray1);*/ pos = Gray0 + Gray1 * 256; Gray1 = pixLess[pos]; Gray0 = pixGreater[pos]; /* if (Gray3 > Gray4) Swap(Gray3, Gray4);*/ pos = Gray3 + Gray4 * 256; Gray4 = pixLess[pos]; Gray3 = pixGreater[pos]; /* if (Gray6 > Gray7) Swap(Gray6, Gray7);*/ pos = Gray6 + Gray7 * 256; Gray7 = pixLess[pos]; Gray6 = pixGreater[pos]; /* if (Gray1 > Gray2) Swap(Gray1, Gray2);*/ pos = Gray1 + Gray2 * 256; Gray2 = pixLess[pos]; Gray1 = pixGreater[pos]; /* if (Gray4 > Gray5) Swap(Gray4, Gray5);*/ pos = Gray4 + Gray5 * 256; Gray5 = pixLess[pos]; Gray4 = pixGreater[pos]; /* if (Gray7 > Gray8) Swap(Gray7, Gray8);*/ pos = Gray7 + Gray8 * 256; Gray8 = pixLess[pos]; Gray7 = pixGreater[pos]; /* if (Gray0 > Gray3) Swap(Gray0, Gray3);*/ pos = Gray0 + Gray3 * 256; Gray3 = pixLess[pos]; Gray0 = pixGreater[pos]; /* if (Gray5 > Gray8) Swap(Gray5, Gray8);*/ pos = Gray5 + Gray8 * 256; Gray8 = pixLess[pos]; Gray5 = pixGreater[pos]; /* if (Gray4 > Gray7) Swap(Gray4, Gray7);*/ pos = Gray4 + Gray7 * 256; Gray7 = pixLess[pos]; Gray4 = pixGreater[pos]; /* if (Gray3 > Gray6) Swap(Gray3, Gray6);*/ pos = Gray3 + Gray6 * 256; Gray6 = pixLess[pos]; Gray3 = pixGreater[pos]; /* if (Gray1 > Gray4) Swap(Gray1, Gray4);*/ pos = Gray1 + Gray4 * 256; Gray4 = pixLess[pos]; Gray1 = pixGreater[pos]; /* if (Gray2 > Gray5) Swap(Gray2, Gray5);*/ pos = Gray2 + Gray5 * 256; Gray5 = pixLess[pos]; Gray2 = pixGreater[pos]; /* if (Gray4 > Gray7) Swap(Gray4, Gray7);*/ pos = Gray4 + Gray7 * 256; Gray7 = pixLess[pos]; Gray4 = pixGreater[pos]; /* if (Gray4 > Gray2) Swap(Gray4, Gray2);*/ pos = Gray4 + Gray2 * 256; Gray2 = pixLess[pos]; Gray4 = pixGreater[pos]; /* if (Gray6 > Gray4) Swap(Gray6, Gray4);*/ pos = Gray6 + Gray4 * 256; Gray4 = pixLess[pos]; Gray6 = pixGreater[pos]; /* if (Gray4 > Gray2) Swap(Gray4, Gray2); */ pos = Gray4 + Gray2 * 256; Gray2 = pixLess[pos]; Gray4 = pixGreater[pos]; LinePD[1] = Gray4; LinePD++; } } return Ret; } else { TMatrix *Blue = NULL, *Green = NULL, *Red = NULL, *Alpha = NULL; // 由於C變量如果不初始化,其值是隨機值,可能會導致釋放時的錯誤。 IS_RET Ret = SplitRGBA(Src, &Blue, &Green, &Red, &Alpha); if (Ret != IS_RET_OK) goto Done24; #pragma omp parallel num_threads(3) { #pragma omp sections { #pragma omp section { Ret = Fastest33MedianBlur(Blue, Blue); } #pragma omp section { Ret = Fastest33MedianBlur(Green, Green); } #pragma omp section { Ret = Fastest33MedianBlur(Red, Red); } } } Ret = CombineRGBA(Dest, Blue, Green, Red, Alpha); Done24: IS_FreeMatrix(&Blue); IS_FreeMatrix(&Green); IS_FreeMatrix(&Red); IS_FreeMatrix(&Alpha); return Ret; } return Ret; }
關於交換法短值快速排序的參考資料見:https://github.com/afniHQ/AFNI/blob/ab8ca253b784ae71401927df88da2bc6e16d07c1/src/cs_qsort_small.h