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