/// <summary>
/// processes incoming image
/// </summary>
/// <returns>error code, refer to AL_XXX codes</returns>
/// <remarks>
/// working parallel code with single loop, using Win32 events to protect data dependecies across vertical blocks
/// [Filter processing of full resolution image] in [1.131 seconds]
/// </remarks>
int CParallelEventAltaLuxFilter::Run()
{
	if (ClipLimit == 1.0) 
		return AL_OK;	  //< is OK, immediately returns original image

	PixelType *pImage = (PixelType *)ImageBuffer;

	/// pulMapArray is pointer to mappings
	unsigned int *pulMapArray = new unsigned int[NumHorRegions * NumVertRegions * NUM_GRAY_LEVELS];
	if (pulMapArray == 0) 
		return AL_OUT_OF_MEMORY;	  //< not enough memory

	/// region pixel count
	unsigned int NumPixels = (unsigned int)RegionWidth * (unsigned int)RegionHeight;	//< region pixel count

	unsigned int ulClipLimit;		//< clip limit
	if (ClipLimit > 0.0) 
	{
		/// calculate actual cliplimit
		ulClipLimit = (unsigned int) (ClipLimit * (RegionWidth * RegionHeight) / NUM_GRAY_LEVELS);
		ulClipLimit = (ulClipLimit < 1UL) ? 1UL : ulClipLimit;
	}
	else 
		ulClipLimit = 1UL<<14;		  //< large value, do not clip (AHE)

	/// Interpolate greylevel mappings to get CLAHE image
	// create events for signaling that the first phase is completed
	HANDLE FirstPhaseCompleted[MAX_VERT_REGIONS];
	for (int i = 0; i < NumVertRegions; i++)
		FirstPhaseCompleted[i] = CreateEvent( 
        NULL,               // default security attributes
        TRUE,               // manual-reset event
        FALSE,              // initial state is nonsignaled
        NULL				// object name
        ); 
	
	concurrency::parallel_for((int)0, (int)(NumVertRegions + 1), [&](int uiY) 
	{
		// first half
		PixelType* pImPointer = pImage;
		if (uiY > 0)
			pImPointer += ((RegionHeight >> 1) + ((uiY - 1) * RegionHeight)) * OriginalImageWidth;
		
		if (uiY < NumVertRegions)
		{
			/// calculate greylevel mappings for each contextual region
			for (unsigned int uiX = 0; uiX < NumHorRegions; uiX++, pImPointer += RegionWidth) 
			{
				unsigned int *pHistogram = &pulMapArray[NUM_GRAY_LEVELS * (uiY * NumHorRegions + uiX)];
				MakeHistogram(pImPointer, pHistogram);
				ClipHistogram(pHistogram, ulClipLimit);
				MapHistogram(pHistogram, NumPixels);
			}
		}

		// signal that the first phase is completed for this horizontal block
		if (uiY < NumVertRegions)
			SetEvent(FirstPhaseCompleted[uiY]);
		// wait for completion of first phase of the previous horizontal block
		if (uiY > 0)
			DWORD dwWaitResult = WaitForSingleObject(FirstPhaseCompleted[uiY-1], INFINITE);
		
		// second half
		unsigned int uiSubX, uiSubY;	//< size of subimages
		unsigned int uiXL, uiXR, uiYU, uiYB;	//< auxiliary variables interpolation routine

		pImPointer = pImage;
		if (uiY > 0)
			pImPointer += ((RegionHeight >> 1) + ((uiY - 1) * RegionHeight)) * OriginalImageWidth;

		if (uiY == 0) 
		{	
			/// special case: top row
			uiSubY = RegionHeight >> 1;  
			uiYU = 0; 
			uiYB = 0;
		} else {
			if (uiY == NumVertRegions) 
Exemplo n.º 2
0
/************************** main function CLAHE ******************/
static int CLAHE (kz_pixel_t* pImage, unsigned int uiXRes, unsigned int uiYRes,
         kz_pixel_t Min, kz_pixel_t Max, unsigned int uiNrX, unsigned int uiNrY,
              unsigned int uiNrBins, float fCliplimit)
/*   pImage - Pointer to the input/output image
 *   uiXRes - Image resolution in the X direction
 *   uiYRes - Image resolution in the Y direction
 *   Min - Minimum greyvalue of input image (also becomes minimum of output image)
 *   Max - Maximum greyvalue of input image (also becomes maximum of output image)
 *   uiNrX - Number of contextial regions in the X direction (min 2, max uiMAX_REG_X)
 *   uiNrY - Number of contextial regions in the Y direction (min 2, max uiMAX_REG_Y)
 *   uiNrBins - Number of greybins for histogram ("dynamic range")
 *   float fCliplimit - Normalized cliplimit (higher values give more contrast)
 * The number of "effective" greylevels in the output image is set by uiNrBins; selecting
 * a small value (eg. 128) speeds up processing and still produce an output image of
 * good quality. The output image will have the same minimum and maximum value as the input
 * image. A clip limit smaller than 1 results in standard (non-contrast limited) AHE.
 */
{
    unsigned int uiX, uiY;                /* counters */
    unsigned int uiXSize, uiYSize, uiSubX, uiSubY; /* size of context. reg. and subimages */
    unsigned int uiXL, uiXR, uiYU, uiYB;  /* auxiliary variables interpolation routine */
    unsigned long ulClipLimit, ulNrPixels;/* clip limit and region pixel count */
    kz_pixel_t* pImPointer;                /* pointer to image */
    kz_pixel_t aLUT[uiNR_OF_GREY];          /* lookup table used for scaling of input image */
    unsigned long* pulHist, *pulMapArray; /* pointer to histogram and mappings*/
    unsigned long* pulLU, *pulLB, *pulRU, *pulRB; /* auxiliary pointers interpolation */

    if (uiNrX > uiMAX_REG_X) return -1;    /* # of regions x-direction too large */
    if (uiNrY > uiMAX_REG_Y) return -2;    /* # of regions y-direction too large */
    if (uiXRes % uiNrX) return -3;        /* x-resolution no multiple of uiNrX */
    if (uiYRes % uiNrY) return -4;        /* y-resolution no multiple of uiNrY #TPB FIX */
    #ifndef BYTE_IMAGE                                    /* #TPB FIX */
                if (Max >= uiNR_OF_GREY) return -5;    /* maximum too large */
        #endif
    if (Min >= Max) return -6;            /* minimum equal or larger than maximum */
    if (uiNrX < 2 || uiNrY < 2) return -7;/* at least 4 contextual regions required */
    if (fCliplimit == 1.0) return 0;      /* is OK, immediately returns original image. */
    if (uiNrBins == 0) uiNrBins = 128;    /* default value when not specified */

    pulMapArray=(unsigned long *)malloc(sizeof(unsigned long)*uiNrX*uiNrY*uiNrBins);
    if (pulMapArray == 0) return -8;      /* Not enough memory! (try reducing uiNrBins) */

    uiXSize = uiXRes/uiNrX; uiYSize = uiYRes/uiNrY;  /* Actual size of contextual regions */
    ulNrPixels = (unsigned long)uiXSize * (unsigned long)uiYSize;

    if(fCliplimit > 0.0) {                /* Calculate actual cliplimit  */
       ulClipLimit = (unsigned long) (fCliplimit * (uiXSize * uiYSize) / uiNrBins);
       ulClipLimit = (ulClipLimit < 1UL) ? 1UL : ulClipLimit;
    }
    else ulClipLimit = 1UL<<14;           /* Large value, do not clip (AHE) */
    MakeLut(aLUT, Min, Max, uiNrBins);    /* Make lookup table for mapping of greyvalues */
    /* Calculate greylevel mappings for each contextual region */
    for (uiY = 0, pImPointer = pImage; uiY < uiNrY; uiY++) {
        for (uiX = 0; uiX < uiNrX; uiX++, pImPointer += uiXSize) {
            pulHist = &pulMapArray[uiNrBins * (uiY * uiNrX + uiX)];
            MakeHistogram(pImPointer,uiXRes,uiXSize,uiYSize,pulHist,uiNrBins,aLUT);
            ClipHistogram(pulHist, uiNrBins, ulClipLimit);
            MapHistogram(pulHist, Min, Max, uiNrBins, ulNrPixels);
        }
        pImPointer += (uiYSize - 1) * uiXRes;             /* skip lines, set pointer */
    }

    /* Interpolate greylevel mappings to get CLAHE image */
    for (pImPointer = pImage, uiY = 0; uiY <= uiNrY; uiY++) {
        if (uiY == 0) {                                   /* special case: top row */
            uiSubY = uiYSize >> 1;  uiYU = 0; uiYB = 0;
        }
        else {
            if (uiY == uiNrY) {                           /* special case: bottom row */
/// <summary>
/// processes incoming image
/// </summary>
/// <returns>error code, refer to AL_XXX codes</returns>
/// <remarks>
/// working parallel code with single loop, using active waits to protect data dependencies
/// [Filter processing of full resolution image] in [1.131 seconds]
/// </remarks>
int CParallelActiveWaitAltaLuxFilter::Run()
{
    if (ClipLimit == 1.0)
        return AL_OK;	  //< is OK, immediately returns original image

    PixelType *pImage = (PixelType *)ImageBuffer;

    /// pulMapArray is pointer to mappings
    unsigned int *pulMapArray = new unsigned int[NumHorRegions * NumVertRegions * NUM_GRAY_LEVELS];
    if (pulMapArray == 0)
        return AL_OUT_OF_MEMORY;	  //< not enough memory

    /// region pixel count
    unsigned int NumPixels = (unsigned int)RegionWidth * (unsigned int)RegionHeight;	//< region pixel count

    unsigned int ulClipLimit;		//< clip limit
    if (ClipLimit > 0.0)
    {
        /// calculate actual cliplimit
        ulClipLimit = (unsigned int) (ClipLimit * (RegionWidth * RegionHeight) / NUM_GRAY_LEVELS);
        ulClipLimit = (ulClipLimit < 1UL) ? 1UL : ulClipLimit;
    }
    else
        ulClipLimit = 1UL<<14;		  //< large value, do not clip (AHE)

    /// Interpolate greylevel mappings to get CLAHE image
    // create events for signaling that the first phase is completed
    __declspec(align(32)) volatile LONG FirstPhaseCompleted[MAX_VERT_REGIONS+1];
    for (int i = 0; i <= NumVertRegions; i++)
        InterlockedExchange((volatile LONG*)&FirstPhaseCompleted[i], -1);

    concurrency::parallel_for((LONG)0, (LONG)(NumVertRegions + 1), [&](LONG uiY)
    {
        // first half
        PixelType* pImPointer = pImage;
        if (uiY > 0)
            pImPointer += ((RegionHeight >> 1) + ((uiY - 1) * RegionHeight)) * OriginalImageWidth;

        if (uiY < NumVertRegions)
        {
            /// calculate greylevel mappings for each contextual region
            for (LONG uiX = 0; uiX < NumHorRegions; uiX++, pImPointer += RegionWidth)
            {
                unsigned int *pHistogram = &pulMapArray[NUM_GRAY_LEVELS * (uiY * NumHorRegions + uiX)];
                MakeHistogram(pImPointer, pHistogram);
                ClipHistogram(pHistogram, ulClipLimit);
                MapHistogram(pHistogram, NumPixels);
                InterlockedExchange((volatile LONG*) &FirstPhaseCompleted[uiY], uiX);
            }
        }

        // second half
        unsigned int uiSubX, uiSubY;	//< size of subimages
        unsigned int uiXL, uiXR, uiYU, uiYB;	//< auxiliary variables interpolation routine

        pImPointer = pImage;
        if (uiY > 0)
            pImPointer += ((RegionHeight >> 1) + ((uiY - 1) * RegionHeight)) * OriginalImageWidth;

        if (uiY == 0)
        {
            /// special case: top row
            uiSubY = RegionHeight >> 1;
            uiYU = 0;
            uiYB = 0;
        } else {