下面介绍一个改动Opencv代码实现更有用的功能的方法
图像的直方图均匀化在做光照均衡时十分有用,但实际上直方图规定话其实更有用,Opencv里面只提供了直方图均匀化的代码cvEqualizeHist
在这个函数的基础上稍加改动,就能得到直方图规定化的代码:- void cvMatchHist( const CvArr* src, CvArr* dst, CvHistogram * histdst )
- {
- CvHistogram* hist = 0;
- CvMat* lut = 0, *lutG = 0, *lutZ = 0;
- CvHistogram * histeq = NULL;
- CV_FUNCNAME( "cvMatchHist" );
- __BEGIN__;
- cvCopyHist( histdst, &histeq );
- cvNormalizeHist(histeq, 1.0);
- int i, hist_sz = 256;
- CvSize img_sz;
- float scale;
- float* h, *hG;
- int sum = 0;
- int type;
- CV_CALL( type = cvGetElemType( src ));
- if( type != CV_8UC1 )
- CV_ERROR( CV_StsUnsupportedFormat, "Only 8uC1 images are supported" );
- CV_CALL( hist = cvCreateHist( 1, &hist_sz, CV_HIST_ARRAY ));
- CV_CALL( lut = cvCreateMat( 1, 256, CV_8UC1 ));
- CV_CALL( lutG = cvCreateMat( 1, hist_sz, CV_8UC1 ));
- CV_CALL( lutZ = cvCreateMat( 1, hist_sz, CV_8UC1 ));
- CV_CALL( cvCalcArrHist( (CvArr**)&src, hist ));
- CV_CALL( img_sz = cvGetSize( src ));
- scale = 255.f/(img_sz.width*img_sz.height);
- h = (float*)cvPtr1D( hist->bins, 0 );
- hG = (float*)cvPtr1D( histeq->bins, 0 );
- for(i = 0; i < 256; i++)
- {
- sum += cvRound(hG[i]*255);
- lutG->data.ptr[i] = (uchar)cvRound(sum);
- }
- sum = 0;
- for( i = 0; i < hist_sz; i++ )
- {
- sum += cvRound(h[i]);
- lut->data.ptr[i] = (uchar)cvRound(sum*scale);
- }
- for (i = 0; i < 256; i++)
- {
- int k = 0;
- while(lutG->data.ptr[k] < i)
- {
- k++;
- }
- lutZ->data.ptr[i] = k;
- }
- lut->data.ptr[0] = 0;
- CV_CALL( cvLUT( src, dst, lut ));
- CV_CALL( cvLUT( dst, dst, lutZ ));
- __END__;
- cvReleaseHist(&hist);
- cvReleaseMat(&lut);
- cvReleaseMat(&lutG);
- cvReleaseMat(&lutZ);
- cvReleaseHist(&histeq);
- }
复制代码
上面代码似乎有误,两处sum += cvRound(h)语句中,cvRound函数似乎不需要,因为如果在这里舍入的话加出来的sum最后很可能不是255.
另外问一句,函数中很多的宏定义,比如__BEGIN__,CV_CALL,CV_FUNCNAME,都是干什么使的?我查了一下他们的定义,__BEGIN__只是一个大括号,CV_CALL似乎加入了出错处理,有谁能详细解释一下呢? |