Ask Your Question

Revision history [back]

You can solve it by projection.

code :

#define BH_HORZ_DIRECT  100
#define BH_VERT_DIRECT  101
#define BH_BOTH_DIRECT  102

#define BH_LIMIT_POS1 0
#define BH_LIMIT_POS2 1
#define BH_LIMIT_SIZE 2
#define BH_LIMIT_SUM 3
#define BH_LIMIT_SIZE_MIN 4
#define BH_LIMIT_SIZE_MAX 5

typedef struct BhLimit
{
    int pos1 ,pos2 ;
    double min_value , max_value;
    int min_pos , max_pos;
    double avg;
    double sum;
    int len;
}BhLimit;
typedef vector<BhLimit> BhLimits;
int bhGetLimitSize(BhLimit limit)
{
    return limit.pos2 - limit.pos1 + 1;
}

IplImage* bhGet8Depth(const IplImage* srcImage,int zeroFlag)
{
    IplImage* resultImg;
    if (srcImage->depth == 8)
    {
            resultImg= cvCreateImage(cvGetSize(srcImage),8,1);
            if (zeroFlag == 1)
                cvZero(resultImg);
            else if (zeroFlag == 2)
            {
                if (srcImage->depth == 8 )
                {
                    if ( srcImage->nChannels == 3)
                      cvCvtColor(srcImage,resultImg,CV_BGR2GRAY);
                    else if( srcImage->nChannels == 1)
                        cvCopyImage(srcImage,resultImg);

                }
            }
    }
    else if (srcImage->depth == IPL_DEPTH_32F)
            {
                if ( srcImage->nChannels ==1)
                    resultImg = cvCreateImage(cvGetSize(srcImage),8,1);
                else if (srcImage->nChannels == 3)
                    resultImg = cvCreateImage(cvGetSize(srcImage),8,3);

                cvNormalize(srcImage,resultImg,0,255,CV_MINMAX);
            }



    return  resultImg;
}

void bhGetHorzProjection(IplImage* srcImage,CvMat* srcProj)
{
    CvRect roi = cvGetImageROI(srcImage);

//  CvMat* result = cvCreateMat(1,srcImage->height,CV_32FC1);

    float* projP = srcProj->data.fl;
    IplImage* rowImg = cvCreateImageHeader(cvSize(roi.width,1),8,1) ;

    rowImg->imageData = srcImage->imageData + srcImage->widthStep * roi.y + roi.x; 
    rowImg->widthStep = srcImage->widthStep;

    for (int i= roi.y; i < roi.y + roi.height ;i++)
    {
        projP[i - roi.y] = float(cvSum(rowImg).val[0]);
        rowImg->imageData += rowImg->widthStep ;

    }

    cvReleaseImageHeader(&rowImg);

    //return result;

}

CvMat* bhGetHorzProjection(IplImage* srcImage)
{
    CvRect roi = cvGetImageROI(srcImage);
    CvMat* result = cvCreateMat(1,roi.height,CV_32FC1);
    bhGetHorzProjection(srcImage,result);
    return result;
}
BhLimit bhGetLimitInfo(CvMat* proj ,int pos1,int pos2)
{
    BhLimit result;
    result.pos1 = pos1;
    result.pos2 = pos2;
    float* p = (float*) (proj->data.fl);
    result.sum = p[pos1];
    result.avg = p[pos1];
    result.max_value = p[pos1];
    result.min_value = p[pos1];
    result.max_pos = 0;
    result.min_pos = 0;

    for (int j=pos1+1;j < pos2;j++)
    {
        result.sum += p[j];
        if (p[j] > result.max_value)
        {
            result.max_value = p[j];
            result.max_pos = j;
        }
        if (p[j] < result.min_value)
        {
            result.min_value = p[j];
            result.min_pos = j;
        }

    }

    result.len = result.pos2 - result.pos1 +1;
    result.avg = result.sum / result.len;

    return result;

}

void bhGetProjectionLimits(CvMat* proj,BhLimits& result)
{
    //BhLimits result;
    float* p = (float*) (proj->data.fl);
    int j=0;
    while ( j < proj->width)
    {
        if (p[j] > 0 )
        {
            int starttPos = j;
            int endPos = j;
            j++;
            while ((j < proj->width) && (p[j] > 0))
            {
                j++;
                endPos++;
            }
            BhLimit lim = bhGetLimitInfo(proj,starttPos,endPos);
            result.push_back(lim);

        }
        j++;
    }

    //return result;


}

void bhQueryLimits(BhLimits& limits,unsigned char op,int minValue,int maxValue)
{
    BhLimits result;
    if (op == BH_LIMIT_POS1)
      for (size_t i=0; i <limits.size();i++)
        {
            if (minValue <= limits[i].pos1 && limits[i].pos1 <= maxValue)
                result.push_back(limits[i]);
        }
    else if (op == BH_LIMIT_POS2)
      for (size_t i=0; i <limits.size();i++)
        {
            if (minValue <= limits[i].pos2 && limits[i].pos2 <= maxValue)
                result.push_back(limits[i]);
        }
    else if (op == BH_LIMIT_SIZE)
      for (size_t i=0; i <limits.size();i++)
        {
            int size = bhGetLimitSize(limits[i]);
            if (minValue <= size && size <= maxValue)
                result.push_back(limits[i]);
        }
    else if (op == BH_LIMIT_SUM)
      for (size_t i=0; i <limits.size();i++)
        {

            if (minValue <= limits[i].sum && limits[i].sum <= maxValue)
                result.push_back(limits[i]);
        }

      limits.clear();
      limits.assign(result.begin(),result.end());
}
IplImage* bhGetColorImage(const IplImage* srcImage,int flag)
{
    IplImage* resultImg = cvCreateImage(cvGetSize(srcImage),8,3);
    if (flag == 1)
    {
        cvZero(resultImg);
    }
    else if (flag == 2){
            if (srcImage->depth == IPL_DEPTH_8U)
            {
                if (srcImage->nChannels == 1)
                    cvCvtColor(srcImage,resultImg,CV_GRAY2BGR);
                else if (srcImage->nChannels == 3)
                    cvCopyImage(srcImage,resultImg);
                else if (srcImage->nChannels == 4)
                    cvCvtColor(srcImage,resultImg,CV_BGRA2BGR);
            }
            else if (srcImage->depth == IPL_DEPTH_32F)
            {
                IplImage* normImg = cvCreateImage(cvGetSize(srcImage),8,1);
                cvNormalize(srcImage,normImg,0,255,CV_MINMAX);

                cvCvtColor(normImg,resultImg,CV_GRAY2BGR);
                cvReleaseImage(&normImg);
            }

    }

    return resultImg;
}

void bhDrawLimits(IplImage* srcImage,BhLimits limits ,CvScalar color,int thickness,int direct)
{
    if (direct == BH_VERT_DIRECT)
    {
       for (size_t i=0; i< limits.size();i++)
        cvRectangle(srcImage,cvPoint(limits[i].pos1,0),cvPoint(limits[i].pos2,srcImage->height),color,thickness);
    }
    else if (direct == BH_HORZ_DIRECT)
    {
       for (size_t i=0; i< limits.size();i++)
           cvRectangle(srcImage,cvPoint(0,limits[i].pos1),cvPoint(srcImage->width, limits[i].pos2),color,thickness);

    }
}
int main( int argc, char** argv ) 
{
   IplImage* orgImg = cvLoadImage("c:\\test3.png",0);

    IplImage* img = bhGet8Depth(orgImg,2);
    cvNot(img,img);

    CvMat* horzProj = bhGetHorzProjection(img);
    cvNormalize(horzProj,horzProj,0,100,CV_MINMAX);
    cvSmooth(horzProj,horzProj,CV_GAUSSIAN,9);

    cvThreshold(horzProj,horzProj,10,100,CV_THRESH_BINARY);

    BhLimits limits;
    bhGetProjectionLimits(horzProj,limits);
    bhQueryLimits(limits,BH_LIMIT_SIZE,10,10000);
    IplImage* viewImg = bhGetColorImage(orgImg,2);
    bhDrawLimits(viewImg,limits,CV_RGB(255,0,0),2,BH_HORZ_DIRECT);
    cvShowImage("view",viewImg);
    cvWaitKey(0);

    cvReleaseMat(&horzProj);
    cvReleaseImage(&img);
    cvReleaseImage(&viewImg);
    cvReleaseImage(&orgImg);

}

result:

image description