多邊形的最大內接圓

如果想減少運行時間,可以試試:在平面中,如果一個凸多邊形有內切圓,那麼凸多邊形的面積S、周長c與內切圓半徑r之間的關係爲S=cr/2

#if 1
#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <imgproc/imgproc.hpp>
#include <iostream>
#include <math.h>
#include <vector>


using namespace std;
using namespace cv;
#define  PI 3.1415926


typedef struct _POINT
{
    int x;
    int y;
}point;

int Otsu(IplImage* src)
{
    int height=src->height;
    int width=src->width;

    //histogram
    float histogram[256] = {0};
    for(int i=0; i < height; i++)
    {
        unsigned char* p=(unsigned char*)src->imageData + src->widthStep * i;
        for(int j = 0; j < width; j++)
        {
            histogram[*p++]++;
        }
    }
    //normalize histogram
    int size = height * width;
    for(int i = 0; i < 256; i++)
    {
        histogram[i] = histogram[i] / size;
    }

    //average pixel value
    float avgValue=0;
    for(int i=0; i < 256; i++)
    {
        avgValue += i * histogram[i];  //整幅圖像的平均灰度
    }

    int threshold = 0;;
    float maxVariance=0;
    float w = 0, u = 0;
    for(int i = 0; i < 256; i++)
    {
        w += histogram[i];  //假設當前灰度i爲閾值, 0~i 灰度的像素(假設像素值在此範圍的像素叫做前景像素) 所佔整幅圖像的比例
        u += i * histogram[i];  // 灰度i 之前的像素(0~i)的平均灰度值: 前景像素的平均灰度值

        float t = avgValue * w - u;
        float variance = t * t / (w * (1 - w) );
        if(variance > maxVariance)
        {
            maxVariance = variance;
            threshold = i;
        }
    }

    return threshold;
}

int main()
{
    IplImage *image = cvLoadImage("/Users/hanoi/Desktop/test.bmp",0);
    if(!image)
    {
        printf("load image fail\n");
        return -1;
    }
    int width = image->width;
    int height = image->height;
    int step = image->widthStep;
    printf("widht=%d height=%d step=%d\n",width,height,step);



    int threshold = Otsu(image);
    printf("threshold = %d\n",threshold);
    CvMemStorage *storage = cvCreateMemStorage(0);
    CvSeq *contours = 0, *contoursTemp = 0 , *testContours=0;;
    cvThreshold(image, image, threshold, 255, CV_THRESH_BINARY);
    cvFindContours(image, storage,&contours, sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
    contoursTemp = contours;
    int count = 0;
    double maxArrea = 0;

    for(;contoursTemp != 0; contoursTemp = contoursTemp -> h_next)
    {
        double contArea = fabs(cvContourArea(contoursTemp,CV_WHOLE_SEQ));
        if (contArea > maxArrea)
        {
            maxArrea = contArea;
            testContours = contoursTemp;
        }
        count ++;
    }
    if(count == 0)
    {
        cvReleaseMemStorage(&storage);
        cvReleaseImage(&image);
        printf("There is no counter\n");
        return -1;
    }


    //打印輪廓
    vector<point> myPoint;
    IplImage *counterImage = cvCreateImage(cvGetSize(image), image->depth,0);
    memcpy(counterImage->imageData, image->imageData, width*height);

    for(int i=0; i<testContours->total; i++)
    {
        CvPoint *pt = (CvPoint*) cvGetSeqElem(testContours, i);
        *(counterImage->imageData + pt->y*step + pt->x) = 128;
    }
    cvSaveImage("/Users/hanoi/Desktop/counter.png", counterImage);
    cvReleaseImage(&counterImage);


    CvPoint2D32f pt;
    double flag = 0;
     point tempPoint;
    IplImage *myImage = cvCreateImage(cvGetSize(image), image->depth,0);
    memcpy(myImage->imageData, image->imageData, width*height);
    for(int j=0; j<height; j++)
    {
        for(int i=0; i<width; i++)
        {
            pt.x = i;
            pt.y = j;
            flag = cvPointPolygonTest(testContours, pt, 0);
            if(flag > 0)//判斷點在輪廓之內
            {
                tempPoint.x = i;
                tempPoint.y = j;
                myPoint.push_back(tempPoint);
                 *(myImage->imageData + j*step +i) = 90;
            }
        }
    }
    cvSaveImage("/Users/hanoi/Desktop/counter111.png", myImage);


    int size = (int)myPoint.size();
    printf("size = %d\n",size);
    //窮舉法
    int radius = 1;
    bool isFind = false;

    vector<int>vectorRadius;
    vector<int>vectorX;
    vector<int>vectorY;
    int maxRadius = 0;
    int maxx=0;
    int maxy=0;
    for(int i=0; i<(int)myPoint.size(); i+=2)
    {
        radius = 5;
        isFind = false;
        while (1)
        {
            for(int degree=0; degree<360; degree+=10)
            {
                pt.x = myPoint.at(i).x + radius * cos(degree * PI / 180);
                pt.y = myPoint.at(i).y + radius * sin(degree * PI / 180);
                flag = cvPointPolygonTest(testContours, pt, 0);
                if(flag < 0)
                {
                    //說明找到最大半徑
                    isFind = true;
                    break;
                }
            }
            if(isFind)
            {
                break;
            }
            else
            {
                radius++;
            }
        }
        if(radius > maxRadius)
        {
            maxRadius = radius;
            maxx =  myPoint.at(i).x;
            maxy = myPoint.at(i).y;
        }
    }
    printf("maxRadius=%d\n",maxRadius);

    //畫半徑
    IplImage *realImage = cvCreateImage(cvGetSize(image), image->depth,0);
    memcpy(realImage->imageData, myImage->imageData, width*height);
    for(int degree=0; degree<360; degree++)
    {
        float x1 = maxx + maxRadius * cos(degree * PI / 180);
        float y1 = maxy + maxRadius * sin(degree * PI / 180);
         *(realImage->imageData + int(y1)*step + (int)x1) = 255;
    }
    cvSaveImage("/Users/hanoi/Desktop/circle.png", realImage);
    cvReleaseImage(&realImage);
    cvReleaseImage(&myImage);
    printf("Test finish\n");



    return 0;
}
#endif



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章