# Width measurement of image parts

Hello

I've been working on opencv for past few days , I have successfully run tbe basic operations of images on it.

I have an image whose edge detection was performed and the edges are showing up now . Now , I need to measure the distance between the two edges Note : The edges are not straight lines , also the edges are basically part of a band .!

Also the edge detection of this image is not working , so I need help on both parts , the edge detection and also the width measurement of the 3 bands shown .

Any help would be appreciated .

edit retag close merge delete

What do you want to measure on your image?

( 2013-02-12 02:47:11 -0600 )edit

I want to measure the width of the 3 bands formed , and then take their ratio . I have reached till the above image after various operations ( the original image had clear bands but edge detection wasnt possible , now it is due to clear difference between the bands and background)

( 2013-02-12 08:25:05 -0600 )edit

Sort by » oldest newest most voted

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;

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 ;

}

//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 ...
more

Thank you sir It's a good result , as I am pretty new to this , some explanation of your code would be very helpful..just a brief one will do ! And btw thanks a lot !

( 2013-02-13 05:11:12 -0600 )edit

It worked perfectly , thanks ! Now , I need to measure the width between the two red lines ( of all 3 red boxes ) I was thinking of traversing from one red pixel top to botton for all 3 , is that feasible in opencv? Can you suggest something else for measuring width ?

( 2013-02-14 02:53:19 -0600 )edit

BhLimit struct has len field when you call bhGetLimitInfo set it. For example limits[i].len

( 2013-02-14 03:05:39 -0600 )edit

I still am unable to find the width . Can you help me with the code for it pls ? It's urgent.

( 2013-02-28 06:18:10 -0600 )edit

To measure the width of the bands, you probably should used a connected component approach. You segment your bands into components, easily with the neighborhood search of black pixels. You keep only the biggest (with a threshold), and you can use statistical operations, like sum, average, ellipse fitting (in OpenCV), mean,... or use directly these components to find width and height (min in X and Y and max in X and Y). Additionally you may have to performed morphological math on your image (erode, dilate, Open/Close) to have better results.

more
more

Official site

GitHub

Wiki

Documentation