Ask Your Question
8

Use of CLAHE

asked 2013-04-20 18:59:39 -0500

jhowland gravatar image

updated 2015-09-05 03:54:22 -0500

I am familiar with the CLAHE algorithm and have found it very useful. I am very pleased that it has been added to OpenCV. Is there any API documentation available other than the include files? Examples of use?

edit retag flag offensive close merge delete

Comments

documentation needs a contributor to be updated.

sturkmen gravatar imagesturkmen ( 2017-12-31 17:29:30 -0500 )edit

2 answers

Sort by » oldest newest most voted
17

answered 2013-05-20 08:46:35 -0500

updated 2017-12-31 17:11:25 -0500

Example of use:

Mat m= imread("lena.png",IMREAD_GRAYSCALE); //input image
imshow("lena_GRAYSCALE",m);

Ptr<CLAHE> clahe = createCLAHE();
clahe->setClipLimit(4);

Mat dst;
clahe->apply(m,dst);
imshow("lena_CLAHE",dst);

waitKey();

clipLimit = 2

image description

clipLimit = 4

image description

More information about CLAHE:

Zuiderveld, K. (1994, August). Contrast limited adaptive histogram equalization. In Graphics gems IV (pp. 474-485). Academic Press Professional, Inc..

edit flag offensive delete link more

Comments

nice one !

berak gravatar imageberak ( 2013-05-20 09:38:48 -0500 )edit
6

lena == arnie :p

Guanta gravatar imageGuanta ( 2013-05-20 10:03:12 -0500 )edit
3

yes :-)

albertofernandez gravatar imagealbertofernandez ( 2013-05-20 10:16:47 -0500 )edit

How do you de-allocate clahe's memory after using it ? I saw collectGarbage() as one of the methods. Is that the right one ?

curryage gravatar imagecurryage ( 2013-07-09 14:39:32 -0500 )edit
0

answered 2017-02-23 16:52:59 -0500

You can do it yourself ,this is my solution:

Mat claheGO(Mat src,int _step = 8)
{
    Mat CLAHE_GO = src.clone();
    int block = _step;//pblock
    int width = src.cols;
    int height= src.rows;
    int width_block = width/block; //每个小格子的长和宽
    int height_block = height/block;
    //存储各个直方图  
    int tmp2[8*8][256] ={0};
    float C2[8*8][256] = {0.0};
    //分块
    int total = width_block * height_block; 
    for (int i=0;i<block;i++)
    {
        for (int j=0;j<block;j++)
        {
            int start_x = i*width_block;
            int end_x = start_x + width_block;
            int start_y = j*height_block;
            int end_y = start_y + height_block;
            int num = i+block*j;  
            //遍历小块,计算直方图
            for(int ii = start_x ; ii < end_x ; ii++)  
            {  
                for(int jj = start_y ; jj < end_y ; jj++)  
                {  
                    int index =src.at<uchar>(jj,ii);
                    tmp2[num][index]++;  
                }  
            } 
            //裁剪和增加操作,也就是clahe中的cl部分
            //这里的参数 对应《Gem》上面 fCliplimit  = 4  , uiNrBins  = 255
            int average = width_block * height_block / 255;  
            //关于参数如何选择,需要进行讨论。不同的结果进行讨论
            //关于全局的时候,这里的这个cl如何算,需要进行讨论 
            int LIMIT = 40 * average;  
            int steal = 0;  
            for(int k = 0 ; k < 256 ; k++)  
            {  
                if(tmp2[num][k] > LIMIT){  
                    steal += tmp2[num][k] - LIMIT;  
                    tmp2[num][k] = LIMIT;  
                }  
            }  
            int bonus = steal/256;  
            //hand out the steals averagely  
            for(int k = 0 ; k < 256 ; k++)  
            {  
                tmp2[num][k] += bonus;  
            }  
            //计算累积分布直方图  
            for(int k = 0 ; k < 256 ; k++)  
            {  
                if( k == 0)  
                    C2[num][k] = 1.0f * tmp2[num][k] / total;  
                else  
                    C2[num][k] = C2[num][k-1] + 1.0f * tmp2[num][k] / total;  
            }  
        }
    }
    //计算变换后的像素值  
    //根据像素点的位置,选择不同的计算方法  
    for(int  i = 0 ; i < width; i++)  
    {  
        for(int j = 0 ; j < height; j++)  
        {  
            //four coners  
            if(i <= width_block/2 && j <= height_block/2)  
            {  
                int num = 0;  
                CLAHE_GO.at<uchar>(j,i) = (int)(C2[num][CLAHE_GO.at<uchar>(j,i)] * 255);  
            }else if(i <= width_block/2 && j >= ((block-1)*height_block + height_block/2)){  
                int num = block*(block-1);  
                CLAHE_GO.at<uchar>(j,i) = (int)(C2[num][CLAHE_GO.at<uchar>(j,i)] * 255);  
            }else if(i >= ((block-1)*width_block+width_block/2) && j <= height_block/2){  
                int num = block-1;  
                CLAHE_GO.at<uchar>(j,i) = (int)(C2[num][CLAHE_GO.at<uchar>(j,i)] * 255);  
            }else if(i >= ((block-1)*width_block+width_block/2) && j >= ((block-1)*height_block + height_block/2)){  
                int num = block*block-1;  
                CLAHE_GO.at<uchar>(j,i) = (int)(C2[num][CLAHE_GO.at<uchar>(j,i)] * 255);  
            }  
            //four edges except coners  
            else if( i <= width_block/2 )  
            {  
                //线性插值  
                int num_i = 0;  
                int num_j = (j - height_block/2)/height_block;  
                int num1 = num_j*block + num_i;  
                int num2 = num1 + block;  
                float p =  (j - (num_j*height_block+height_block/2))/(1.0f*height_block);  
                float q = 1-p;  
                CLAHE_GO.at<uchar>(j,i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j,i)]+ p*C2[num2][CLAHE_GO.at<uchar>(j,i)])* 255);  
            }else if( i >= ((block-1)*width_block+width_block/2)){  
                //线性插值  
                int num_i = block-1;  
                int num_j = (j - height_block/2)/height_block;  
                int num1 = num_j*block + num_i;  
                int num2 = num1 + block;  
                float p =  (j - (num_j*height_block+height_block/2))/(1.0f*height_block);  
                float q = 1-p;  
                CLAHE_GO.at<uchar>(j,i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j,i)]+ p*C2[num2][CLAHE_GO.at<uchar>(j,i)])* 255);  
            }else if( j <= height_block/2 ){  
                //线性插值  
                int num_i = (i - width_block/2)/width_block;  
                int num_j = 0;  
                int num1 = num_j*block + num_i;  
                int num2 = num1 ...
(more)
edit flag offensive delete link more

Comments

commentate are Chinese words,ignore themm,have fun.

jsxyhelu gravatar imagejsxyhelu ( 2017-02-23 16:54:49 -0500 )edit
Login/Signup to Answer

Question Tools

3 followers

Stats

Asked: 2013-04-20 18:59:39 -0500

Seen: 37,267 times

Last updated: Dec 31 '17