此处使用的投影直方图区间个数为BIN个,BIN越大,提取主分量的精度越高,同时对噪声的适应性越差。
一个直方图可能有多个主分量,以下函数中各参数的意义为:
pCheckImage: 原始二值图指针;
rect:计算投影直方图的矩形区域;
iHorProf:水平投影直方图数组名(暂时未用到);
iVerProf:垂直投影直方图数组名;
sliceRect:提取得到的各个主分量矩形的数组名;
iSliceNum:提取的主分量的个数。
投影直方图以最大值为100的方式做的归一化。
函数如下:
void SliceRegion(IplImage* pCheckImage, CvRect* rect, const int* iHorProj, const int* iVerProj, CvRect* sliceRect, int& iSliceNum)
{
int iStart = 0;
int iEnd = BIN - 1;
int iSum = 0;
int iX = rect->x;
int iY = rect->y;
int iWidth = rect->width;
int iHeight = rect->height;
int iMax = 0;
for (int i=0; i<BIN-1; i++)
{
if (iVerProj[i] - iVerProj[i+1] >= 35 || iVerProj[i+1] - iVerProj[i] >= 35)
{
iEnd = i;
for (int k=iStart; k<=iEnd; k++)
{
if (iVerProj[k] > iMax)
{
iMax = iVerProj[k];
}
}
if (iMax >= 70) //提取出主分量
{
int iE = 0;
sliceRect[iSliceNum].x = iStart == 0 ? iX : iX + (iStart - 1) * ((iWidth-1) / BIN + 1);
sliceRect[iSliceNum].y = iY;
if (iVerProj[iEnd+1] < 10) //主分量结束处后一个bin的值过小,则不扩展
{
iE = iStart == 0 ? 0 : 1;
}
else
{
iE = iStart == 0 ? 1 : 2;
}
sliceRect[iSliceNum].width = iWidth < BIN ? iWidth : (iEnd - iStart + 1 + iE) * ((iWidth-1) / BIN + 1);
sliceRect[iSliceNum].height = iHeight;
iSliceNum++;
iFlag = 0;
iMax = 0;
}
iStart = iEnd + 1;
}
}
for (int i=0; i<iSliceNum; i++)
{
cvRectangle(pCheckImage, cvPoint(sliceRect[i].x, sliceRect[i].y), cvPoint(sliceRect[i].x+sliceRect[i].width, sliceRect[i].y+sliceRect[i].height), CV_RGB(255,255,255));
}
//cvShowImage("Slice", pCheckImage);
//cvWaitKey(1);
}