设为首页 - 加入收藏 焦点技术网
热搜:java
当前位置:首页 >

OpenCV提取轮廓(去掉面积小的轮廓)

2012-03-23 14:05:00.0 OpenCV Contour Detection dst image list header 存储 c  
导读:转自:http://www.kaixuela.net/?p=23 #include#include"cv.h"#include"cxcore.h"#include"highgui.h"#includeusingnamespace std;#pragmacomment(lib,"cv.lib")#pragmacomment(lib,"cxcore.lib")#pragmacomment(lib,"h...。。。

转自:http://www.kaixuela.net/?p=23

 

#include

#include"cv.h"

#include"cxcore.h"

#include"highgui.h"

#include

usingnamespace std;

#pragmacomment(lib,"cv.lib")

#pragmacomment(lib,"cxcore.lib")

#pragmacomment(lib,"highgui.lib")

 

structPosition

{

    intx,y;

};

 

doubleper[256];// 保存灰度概率

IplImage *FindCountours(IplImage*src,IplImage *pContourImg);

int ImageStretchByHistogram(IplImage *src,IplImage *dst);

IplImage*Hist_Equalization(IplImage *srcimg);

voidproBorder(IplImage *src);// 边界的处理

voidGetBackImage(IplImage*src,IplImage*src_back);

voidThreshold(IplImage *src);

int GetThreshold(double *constprob);

voidGetprobability(IplImage *src);

doubleEccentricity(IplImage *src);

 

voidmain()

{

    //IplImage * src = cvLoadImage("C:\\image19\\A634.jpg",-1);//灰度图的方式载入

    IplImage *src = cvLoadImage("C:\\image19\\A857.jpg",-1);

    IplImage *dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);

    IplImage *src_back =cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,src->nChannels);

    GetBackImage(src,src_back);

    dst =FindCountours(src_back,dst);

 

    cvNamedWindow("test",CV_WINDOW_AUTOSIZE);

    cvShowImage("test",dst);

    cvWaitKey(0);

    cvReleaseImage(&src);

    cvReleaseImage(&dst);

}

 

voidGetBackImage(IplImage*src,IplImage*src_back)

{

    //cvCvtColor(src,src,CV_RGB2GRAY);//灰度化

    IplImage *tmp =cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);

    // 创建结构元素

    IplConvKernel  *element =cvCreateStructuringElementEx( 2, 2, 0, 0, CV_SHAPE_ELLIPSE,0);

    //用该结构对源图象进行数学形态学的开操作后,估计背景亮度

    cvErode(src,tmp,element,9);

    //使用任意结构元素腐蚀图像

    cvDilate(tmp,src_back,element,9);

    //使用任意结构元素膨胀图像

}

 

 

IplImage *FindCountours(IplImage*src,IplImage *pContourImg)

{

    CvMemStorage *storage =cvCreateMemStorage(0); //提取轮廓需要的储存容量为默认KB

    CvSeq *pcontour = 0;  //提取轮廓的序列指针

    IplImage *temp =cvCreateImage(cvGetSize(src),src->depth,1);

 

    //cvSmooth(src,temp,CV_GAUSSIAN,3,1,0);

 

    cvSmooth(src,src,CV_GAUSSIAN,3,1,0);//平滑处理

    cvCvtColor(src,temp,CV_RGB2GRAY);//灰度化

 

    Getprobability(temp);

 

    printf("最好的阈值:%d\n",GetThreshold(per));

 

    //Threshold(temp);

 

    proBorder(temp);

    cvThreshold(temp,temp,GetThreshold(per),255,CV_THRESH_BINARY_INV);

 

    intcontoursNum = 0; // 轮廓数量

    //int mode = CV_RETR_LIST;

    intmode = CV_RETR_EXTERNAL;//提取最外层轮廓

    contoursNum =cvFindContours(temp,storage,&pcontour,sizeof(CvContour),mode,CV_CHAIN_APPROX_NONE);

    // contoursNum = cvFindContours(temp,storage,&pcontour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));

    //二值图,得到轮廓存储,轮廓指针序列,header_size,提取模式,逼近方法

 

    CvScalarexternalColor;// 保存颜色值

    CvScalarholeColor;

    //————–画轮廓—————-//

    for (;pcontour != 0; pcontour=pcontour ->h_next)

    {

        //holeColor=CV_RGB(rand()&255,rand()&255,rand()&255);

        //externalColor=CV_RGB(rand()&255,rand()&255,rand()&255);

        CvRect r = ((CvContour *)pcontour)->rect;

        if(r.height *r.width < 800)

        {

            holeColor=CV_RGB(0,0,0);

            externalColor=CV_RGB(0,0,0);

            cvDrawContours(pContourImg,pcontour,externalColor,holeColor,1,1,8);

        }

        else

        {

            //取得轮廓面积

            double contArea = fabs(cvContourArea(pcontour,CV_WHOLE_SEQ));

            //取得轮廓长度

            double contLenth = cvArcLength(pcontour,CV_WHOLE_SEQ,-1);

            // 圆形度

            double contcircularity = contLenth * contLenth / contArea

            double pxl =Eccentricity(temp);

            cout<<"面积为:"<<contArea<<endl;

            cout<<"周长为:"<<contLenth<<endl;

            cout<<"圆形度为:"<<contcircularity<<endl;

 

            holeColor=CV_RGB(255,255,255);

            externalColor=CV_RGB(255,255,255);

 

            cvDrawContours(pContourImg,pcontour,externalColor,holeColor,1,1,8);

        }

    }

    //IplConvKernel *element = cvCreateStructuringElementEx( 2, 2, 0, 0, CV_SHAPE_ELLIPSE,0);

    //cvDilate(pContourImg,pContourImg, element,9);

    returnpContourImg;

 

}

 

doubleEccentricity(IplImage *src)//偏心率

{

    Positionpos[4];

    intwidth = src->width;

    intheight = src->height;

    inti,j;

 

    for(i = 0;i < height;i++)

    {

        for(j = 0;j < width; j++)

        {

            int pixel = (int)cvGet2D(src,i,j).val[0];

            if(pixel != 0)

            {

                pos[0].x = j;

                pos[0].y = i;//

                goto s;

            }

        }

    }

s:  

    for(i =height 1;i >= 0; i)

    {

        for(j = 0;j < width ;j++)

        {

            int pixel = (int)cvGet2D(src,i,j).val[0];

            if(pixel != 0)

            {

                pos[1].x = j;

                pos[1].y = i;//

                goto w;

            }

        }

    }

w:

    for(i = 0 ;i < width ;i++)

    {

        for(j = 0;j <height; j++)

        {

            int pixel = (int)cvGet2D(src,j,i).val[0];

            if(pixel != 0)

            {

                pos[2].x = j;//

                pos[2].y = i;

                goto e;

            }

        }

    }

e:

    for(i =width 1; i >= 0; i)

    {

        for(j = 0 ;j < height ;j++)

        {

            int pixel = (int)cvGet2D(src,j,i).val[0];

            if(pixel != 0)

            {

                pos[3].x = j;//

                pos[3].y = i;

                goto f;

            }

 

        }

    }

 

f:

    intl_dis = abs(pos[0].y pos[1].y);

    ints_dis = abs(pos[2].x pos[3].x);

    inttmp_dis;

    if(l_dis >s_dis)

    {

        printf("偏心率:%f\n",l_dis*1.0/s_dis);

    }

    else

    {

        tmp_dis = l_dis;

        l_dis = s_dis;

        s_dis = tmp_dis;

        printf("偏心率:%f\n",l_dis*1.0/s_dis);

    }

 

    return 0;

}

 

voidGetprobability(IplImage *src)

{

    memset(per,0,sizeof(per));

    intwidth = src->width;

    intheight = src->height;

    for(inti = 0; i < height; i++) {

        for(intj = 0; j < width; j++) {

            per[(int)cvGet2D(src,i,j).val[0]]++;

        }

    }

    intPixlNum = width *height;

    for(i = 0;i < 256; i++)

        per[i] = per[i] /PixlNum;

 

}

 

int GetThreshold(double *constprob)

{

    intthreshold = 0;

    doublemaxf = 0;

    for (intcrrctThrshld = 1; crrctThrshld < 256 1; ++crrctThrshld) {

        doubleW0 = 0, W1 = 0,U0 = 0, U1 = 0;

        inti = 0;

        for (i = 0;i <= crrctThrshld; ++i) { 

            U0 += i * prob[i];

            W0 += prob[i];

        }

        for (;i < 256; ++i) {

            U1 += i * prob[i];

            W1 += prob[i];

        }

        if (W1 == 0 ||W1 == 0)

            continue;

        U0 /= W0;

        U1 /= W1;

        doubleD0 = 0, D1= 0;

        for (i = 0;i <= crrctThrshld; ++i

            D0 += pow((i U0) * prob[i], 2.0);

        for (;i < 256; ++i

            D1 += pow((i U1) * prob[i], 2.0);

        D0 /= W0;

        D1 /= W1;

        doubleDw = pow(D0, 2.0) *W0 + pow(D1, 2.0) *W1;

        doubleDb = W0 * W1 * pow((U1 U0), 2.0);

        doublef = Db / (Db +Dw);

        if (maxf <f) {

            maxf = f;

            threshold = crrctThrshld;

        }

    }

    returnthreshold;

}

 

voidproBorder(IplImage *src)// 边界的处理

{

    inti,j;

    intheight = src->height;

    intwidth = src->width;

 

    intN = 100;

 

    for(i = 0;i < N * width; i += width) // i表示向下走左上角

    {

        for(j = 0;j < N ; j++)

        {

            int index = i + j;

            src->imageData[index] = (char)255;

        }

    }

 

    intNN = 150;

    intsw = width * (height NN);//左下角 三角形

    int t = 1;

    for(i =sw; i < sw + NN * width;i += width,t++)

    {

        for(j = 0;j < t; j++)

        {

            int index = i + j;

            src->imageData[index] = (char)255;

        }

    }

 

    intse = (height NN 1) * width; // 右下角

    t = 0;

    for(i =se; i < width * height ; i += width,t++)

    {

        for(j = 0;j < t; j++)

        {

            int index = i + j t;

            src->imageData[index] = (char)255;

        }

    }

 

    intne = width NN;                   // 右上角 三角形剪切

    t = 0;

    for(i =ne; i < NN * width; i +=width,t++)

    {

        for(j = 0;j < NN t; j++)

        {

            int index = i + j + t;

            src->imageData[index] = (char)255;

        }

    }

 

}

 

voidThreshold(IplImage *src)

{

    intwidth = src->width;

    intheight = src->height;

    floatminpixel = cvGet2D(src,0,0).val[0];

    floatmaxpixel = cvGet2D(src,0,0).val[0];

    CvScalars;

    for(inti = 0; i < height; i++){

        for(intj = 0; j < width; j++){

            s = cvGet2D(src,i,j);

            if(s.val[0] >maxpixel)

                maxpixel = s.val[0];

            if(s.val[0] <minpixel)

                minpixel = s.val[0];

        }

    }

    floatfirstgrey = (maxpixel +minpixel) / 2;

    printf("%f\n",firstgrey);

 

    floatlastgrey;

    floatsum1 = 0,sum2 = 0;

    intnum1 = 0,num2 = 0;

    intresult = 0;

    while(1)

    {

        result ++;

        for(i = 0;i < height;i++){

            for(int j = 0;j < width; j++){

                s = cvGet2D(src,i,j);

                if(s.val[0] <firstgrey)

                {

                    sum1 += s.val[0];

                    num1++;

                }

                if(s.val[0] <firstgrey)

                {

                    sum2 += s.val[0];

                    num2++;

                }

            }

        }

        lastgrey = (sum1/num1 +sum2/num2)/2;

 

        if((int)lastgrey == (int)firstgrey)

            break;

        else

        {

            firstgrey = lastgrey;

            sum1 = sum2 = 0;

            num1 = num2 = 0;

        }

    }

 

    lastgrey = (sum1/num1 +sum2/num2)/2;

    printf("%f %d\n",firstgrey,result);

}

 

(编辑: fengbingchun)

网友评论
相关文章