首页 > 程序开发 > 综合编程 > 其他综合 >

opencv入门之数米粒

2017-04-17

opencv入门之数米粒:给出一幅米粒图数出图中米粒数目以及最大米粒位置。在原图上画出最大米粒的位置。使用otsu、迭代和平均灰度进行二值分割。

opencv入门之数米粒:给出一幅米粒图数出图中米粒数目以及最大米粒位置。在原图上画出最大米粒的位置。使用otsu、迭代和平均灰度进行二值分割。

声明:

本次实验采用opencv版本为opencv1.0。

编程软件为vc6.

#include "cv.h"
#include "highgui.h"
#include
#include
using namespace std;


int aver(IplImage *inputGrayImg)//平均灰度
{
uchar *data= (uchar *)inputGrayImg->imageData;
int wp = inputGrayImg->widthStep;
int i,j;
int sum=0;


for( i = 0; i < inputGrayImg->height; i++)
{
for(j = 0; j < inputGrayImg->width; j++)
{
sum = sum + data[i * wp + j];
}
}//获得所有灰度的和sum
return int(sum*1.0/(inputGrayImg->height*inputGrayImg->width)+0.5);




}


int diedai(IplImage *inputGrayImg,int a)
{



int threshold = 0;
int newThreshold = a;
while(threshold != newThreshold)
{

int p=1,q=1;
int sum1=0,sum2=0;
uchar *data= (uchar *)inputGrayImg->imageData;
int wp = inputGrayImg->widthStep;
int i,j;
for( i = 0; i < inputGrayImg->height; i++)
{
for(j = 0; j < inputGrayImg->width; j++)
{
if(data[i * wp + j] {
sum1+=data[i * wp + j];
p++;
}
else
{
sum2+=data[i * wp + j];
q++;
}


}
}


int avg1=int(sum1/p);
int avg2=int(sum2/q);
threshold = newThreshold;
newThreshold = (avg1+avg2)/2;
}


return threshold;
}




int otsu(IplImage *inputGrayImg,int u)
{
int hui[256]={0};
float g[256];
uchar *data= (uchar *)inputGrayImg->imageData;
int wp = inputGrayImg->widthStep;
int i,j;


for( i = 0; i < inputGrayImg->height; i++)
{
for(j = 0; j < inputGrayImg->width; j++)
{
hui[data[i * wp + j]]+=1;
}
}
int sum=inputGrayImg->height*inputGrayImg->width;
for(i=0;i<256;i++)
{
int sum1=1,sum2=1;
int hui1=1,hui2=1;
for(j=0;j {
sum1+=hui[j];
hui1+=hui[j]*j;
}
for(j=i;j<256;j++)
{
sum2+=hui[j];
hui2+=hui[j]*j;
}
float w0,w1;
int u0,u1;
w0=sum1*1.0/sum;
w1=sum2*1.0/sum;
u0=int(hui1/sum1);
u1=int(hui2/sum2);
g[i]=w0 * (u0 - u) * (u0 - u) + w1 * (u1 - u) * (u1 - u);


}
int max=0;
for(i=1;i<256;++i)
{
if(g[max] max=i;
}
return max;
}
void main()
{






int averyuzhi,diedaiyuzhi,otsuyuzhi;
IplImage *image=cvLoadImage("D:\\shumili\\rice.jpg",0);
IplImage *image1=cvLoadImage("D:\\shumili\\rice.jpg",1);
if(image==NULL)
{
printf("无法读取图像数据!\n");
return;//不作任何操作,就不会执行后面的程序了
}

IplImage *backImg=cvCreateImage(cvSize(image->width,image->height),8,1);
IplImage *backRImg=cvCreateImage(cvSize(image->width,image->height),8,1);
IplImage *cutImg=cvCreateImage(cvSize(image->width,image->height),8,1);
IplImage *beijing=cvCreateImage(cvSize(image->width,image->height),8,3);


uchar *data= (uchar *)beijing->imageData;
int wp = beijing->widthStep;


for(int i = 0; i < beijing->height; i++)
{
for(int j = 0; j < beijing->width; j++)
{
data[i * wp + 3 * j]=0;
data[i * wp + 3 * j + 1]=0;
data[i * wp + 3 * j + 2]=0;
}
}


cvNamedWindow("图像显示",CV_WINDOW_AUTOSIZE);
cvShowImage("图像显示",image1);//创建窗口展示图像*/
// cvSaveImage("D:\\saveImage.jpg",image);


IplConvKernel* element=cvCreateStructuringElementEx(4,4,1,1,CV_SHAPE_ELLIPSE,0);
//形态学结构指针[创建结构元素,4列4行,椭圆形】


cvErode(image,backImg,element,5);//腐蚀
cvDilate(backImg,backImg,element,5);//膨胀
cvNamedWindow("背景图像显示",CV_WINDOW_AUTOSIZE);
cvShowImage("背景图像显示",backImg);//创建窗口展示图像




cvSub(image,backImg,backRImg,0);


cvNamedWindow("去背景图像显示",CV_WINDOW_AUTOSIZE);
cvShowImage("去背景图像显示",backRImg);//创建窗口展示图像


averyuzhi=aver(backRImg);//33
diedaiyuzhi=diedai(backRImg,averyuzhi);//49
otsuyuzhi=otsu(backRImg,averyuzhi);//58
printf("%d\n",averyuzhi);
printf("%d\n",diedaiyuzhi);
printf("%d\n",otsuyuzhi);
// cvThreshold(backRImg,cutImg,averyuzhi,255,CV_THRESH_BINARY);
cvThreshold(backRImg,cutImg,diedaiyuzhi,255,CV_THRESH_BINARY);
// cvThreshold(backRImg,cutImg,otsuyuzhi,255,CV_THRESH_BINARY);
//cutImg是分割图像


cvErode(cutImg,cutImg,element,1);//腐蚀
cvDilate(cutImg,cutImg,element,1);//膨胀
//经过一次腐蚀膨胀去掉图像中的噪声


cvNamedWindow("otsu分割图像显示",CV_WINDOW_AUTOSIZE);
cvShowImage("otsu分割图像显示",cutImg);//创建窗口展示图像



CvMemStorage* stor=cvCreateMemStorage(0);
CvSeq *cont=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
CvSeq *cont1=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
int numberOfObject=cvFindContours(cutImg,stor,&cont,sizeof(CvContour),CV_RETR_TREE);
int numberOfObject1=cvFindContours(cutImg,stor,&cont1,sizeof(CvContour),CV_RETR_TREE);
//findcontours找轮廓

printf("米粒个数为 %d\n",numberOfObject);


float tmpArea=0;
float tmpLength=0;
int x1,y1;
for (;cont != NULL;cont=cont->h_next)
{
CvRect rect=cvBoundingRect(cont,0);
float tmpArea1=fabs(cvContourArea(cont,CV_WHOLE_SEQ));
float tmpLength1=cvArcLength(cont);
if(tmpArea {
tmpArea=tmpArea1;
tmpLength=tmpLength1;
x1=rect.x;
y1=rect.y;
}
cvDrawContours(beijing,cont,CV_RGB(255,255,255),
CV_RGB(255,0,0),0,1,8,cvPoint(1,1));//在图像上绘制轮廓.

}
for (;cont1 != NULL;cont1=cont1->h_next)
{
CvRect rect=cvBoundingRect(cont1,0);
float tmpArea1=fabs(cvContourArea(cont1,CV_WHOLE_SEQ));
if(rect.x==x1&&y1==rect.y&&tmpArea1==tmpArea)
cvDrawContours(beijing,cont1,CV_RGB(255,0,0),
CV_RGB(255,0,0),0,1,8,cvPoint(1,1));//在图像上绘制轮廓.

}
printf("面积为:%f\n周长为:%f\n",tmpArea,tmpLength);
printf("最大面积位置坐标为:%d %d\n",x1,y1);
cvNamedWindow("图像显示",CV_WINDOW_AUTOSIZE);
cvShowImage("图像显示",beijing);//创建窗口展示图像


cvWaitKey(0);//一直等待按键没有这句的话图像不能正常显示
cvReleaseImage(&image);//释放图像内存
cvDestroyWindow("图像显示");//销毁窗口资源




cvDestroyWindow("背景图像显示");//销毁窗口资源
cvDestroyWindow("去背景图像显示");//销毁窗口资源
cvDestroyWindow("otsu分割图像显示");//销毁窗口资源
//读取和显示完图像之后,要及时释放所占的内存资源.

}

相关文章
最新文章
热点推荐