1 | initial version |
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: