之前对标尺图片进行了颜色滤波,使得图像中只剩下了红色的刻度,那么接下来希望找到这些刻度,并得到它们之间的距离作为一个度量标准。
不过问题来了,经过滤波处理后得到的刻度并不是一条直线,看上去是一个矩形框框,如图
这个时候用cvHoughLines2来找直线效果可就很不好哦,因为都是矩形框框。
想到图形学课上说过有腐蚀Erode这个操作,所以试了一试:
opencv中的腐蚀函数为:
第三个参数为采用的模板,默认取0,则为3*3模板,最后一个参数为腐蚀的迭代次数,如果腐蚀效果不明显,可以增加腐蚀次数。
CVAPI(void) cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element CV_DEFAULT(NULL), int iterations CV_DEFAULT(1) );
void Erode(IplImage *img) { <span style="white-space:pre"> </span>cvNamedWindow("Eroded image", CV_WINDOW_AUTOSIZE); //对彩色图像进行处理 if (!img) { cerr << "The input image is not valid\n"; return ; } if (img->nChannels != 3) { cerr << "The input image is not a color image\n"; return ; } IplImage* erodedImage=cvCreateImage(cvGetSize(img), img->depth, img->nChannels); <span style="white-space:pre"> </span>cvErode(img, erodedImage, 0, 2);//腐蚀 <span style="white-space:pre"> </span>cvShowImage("Eroded image", erodedImage); <span style="white-space:pre"> </span>cvWaitKey(0);//暂停用于显示图片 <span style="white-space:pre"> </span>cvDestroyWindow("Eroded image"); }腐蚀1次,2次,3次的效果分别如下:
1次和2次腐蚀效果都不算特别好,三次腐蚀倒是变成一条线了,可是却有一些刻度不见了。所以腐蚀不是很满足我的要求。
接下来考虑图像的细化算法,具体采用的是qianchenglenger的专栏所实现的方法。
效果如下,挺好的。
关于那个细化方法的调用,我也写了点代码,它的方法使用前要对图片做些预处理
void thin(IplImage *hsv, IplImage *&pDst) { IplImage *pTemp = cvCreateImage(cvGetSize(hsv), hsv->depth, 1); if (hsv->nChannels == 3) cvCvtColor(hsv, pTemp, CV_BGR2GRAY); else cvCopy(hsv, pTemp); //如果pDst不为空,则先释放掉它再重新申请空间 if (pDst) cvReleaseImage(&pDst); pDst = cvCreateImage(cvGetSize(hsv), hsv->depth, 1); //将原图像转换为二值图像 /* void cvThreshold ( const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type ); 第三个参数是阈值 当threshold_type = CV_THRESH_BINARY的时候 对于src中的任一(x,y)处的像素, if src(x,y) > threshold dst(x,y) = max_value; 所以下面的二值化是将所有大于阈值的点像素值都设置为1。 为什么要设置成1呢?这个是细化算法规定的啦。 原实例代码中的阈值设的是128,太高了,因为我首先已经做过滤波,所以将阈值设为1。 */ cvThreshold(pTemp,pTemp,1,1,CV_THRESH_BINARY); //图像细化 thinImage(pTemp,pDst); //图像细化处理之后pDst中每个像素值要么为0,要么为1,所以下面需要把1变为255,这样看起来才明显对吧 for (int i=0; i<pDst->height; ++i) { for (int j=0; j<pDst->width; ++j) { if(CV_IMAGE_ELEM(pDst,uchar,i,j)==1) CV_IMAGE_ELEM(pDst,uchar,i,j)= 255; } } }我这个函数这样调用就可以啦
<span style="white-space:pre"> </span>IplImage *pDst = NULL; thin(hsv, pDst);