多边形的最大内接圆

如果想减少运行时间,可以试试:在平面中,如果一个凸多边形有内切圆,那么凸多边形的面积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



在MATLAB中,计算多边形最大内接通常涉及到几何形状分析,特别是找到一个多边形中心点到其各顶点距离中的最小值,这个最小值对应的半径即为其内切的半径。以下是一个简单的步骤: 1. **创建或导入多边形**: 首先,你需要有一个表示多边形的顶点数据。这可以是二维数组,其中每个行代表一个顶点的坐标。 ```matlab vertices = [x1 y1; x2 y2; ...; xn yn]; % 用(x,y)替换实际坐标 ``` 2. **计算各边长度**:对于多边形的每条边,通过两点间距离公式(`sqrt((xi-xj)^2 + (yi-yj)^2)`)计算出长度。 3. **找出最短边**:找出所有邻边中最短的一对,它们共同决定了一个角以及该角内切的直径。 4. **求内切半径**:内切的半径等于最短边长度除以2。 5. **确定内切中心**:多边形中心通常是它的质心,可以通过将所有顶点的横纵坐标的平均值得到。 如果你想要编写一个完整的函数来处理这个问题,你可以参考以下伪代码: ```matlab function [radius, center] = maxInnerCircle(vertices) % 计算各个边长 edges = sqrt(diff(vertices).^2); % 找到最短边 min_edge_index = find(edges == min(edges)); % 内切半径 radius = edges(min_edge_index) / 2; % 计算质心作为内切中心 center = mean(vertices, 'all'); end ``` 然后,调用这个函数并传入你的多边形顶点: ```matlab [radius, center] = maxInnerCircle(vertices); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值