天天看点

机器视觉实例(VC++6.0 + OpenCV1.0)

环境配置参考: VC6.0+opencv1.0配置

实例内容:

1.实现图像的去背景,将原始图像,背景图像和去背景图像保存下来

2.实现图像的阈值分割,分别用均值灰度,迭代阈值,OTSU方法进行分割

3.实现数米粒功能,输出米粒的颗数,最大米粒的面积,周长,在图像中位置

4.在黑色背景下用白色画出所有米粒的轮廓,并将最大米粒的轮廓用红色显示

完整代码如下:

#include "stdio.h"
#include "cv.h"
#include "highgui.h"

#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cxcore.lib")
#pragma comment(lib,"highgui.lib")
#pragma comment(lib,"cvaux.lib")
#pragma comment(lib,"cvcam.lib")


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];
  }
 }
 return int(sum*1.0/(inputGrayImg->height*inputGrayImg->width)+0.5);
}

int iterate(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]<newThreshold)
    {
     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<i;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]<g[i])max=i;
 }
 return max;
}


int main(int argc,char *argv[])
{
	IplImage *src,*backImg,*backRImg,*cutImg,*result,*show,*dst_contours;//定义
    int averyuzhi,iteryuzhi,otsuyuzhi;//定义三种阈值参数
	src = cvLoadImage("C:\\Users\\\\实验图片\\rice.jpg",CV_LOAD_IMAGE_GRAYSCALE);
	backImg = cvLoadImage("C:\\Users\\实验图片\\rice.jpg",CV_LOAD_IMAGE_GRAYSCALE);
    backRImg = cvLoadImage("C:\\Users\\实验图片\\rice.jpg",CV_LOAD_IMAGE_GRAYSCALE);
	cutImg = cvLoadImage("C:\\Users\\实验图片\\rice.jpg",CV_LOAD_IMAGE_GRAYSCALE);
	dst_contours = cvLoadImage("C:\\Users\\实验图片\\rice.jpg");
    //背景图像
	IplConvKernel* element=cvCreateStructuringElementEx(4,4,1,1,CV_SHAPE_ELLIPSE,0);
	cvErode(src,backImg,element,5);//腐蚀
	cvDilate(backImg,backImg,element,5);//膨胀
	cvSub(src,backImg,backRImg,0);//去背景图像
    //分割图像
    averyuzhi=aver(backRImg);//函数调用
    iteryuzhi=iterate(backRImg,averyuzhi);//函数调用
    otsuyuzhi=otsu(backRImg,averyuzhi);//函数调用
    printf("均值方法阈值:%d\n",averyuzhi);
    printf("迭代方法阈值:%d\n",iteryuzhi);
    printf("OTSU阈值:%d\n",otsuyuzhi);
    cvThreshold(backRImg,cutImg,averyuzhi,255,CV_THRESH_BINARY);
    // cvThreshold(backRImg,cutImg,iteryuzhi,255,CV_THRESH_BINARY);//其他两种方法
    // cvThreshold(backRImg,cutImg,otsuyuzhi,255,CV_THRESH_BINARY);

  
    cvErode(cutImg,cutImg,element,1);//腐蚀
    cvDilate(cutImg,cutImg,element,1);//膨胀
    cvThreshold(backRImg,cutImg,50,255,CV_THRESH_BINARY);
    //数米粒数
    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);
    printf("图中的米粒数为:%d\n",numberOfObject);

    //米粒面积,周长,位置
    float area=0;
    float length=0;
    int x1,y1;
    for (;cont != NULL;cont=cont->h_next)
	{
       CvRect rect=cvBoundingRect(cont,0);
	   double area1=fabs(cvContourArea(cont,CV_WHOLE_SEQ)); 
	   double length1=cvArcLength(cont);
	   if(area<area1) 
	   {  
		   area=area1;
		   length=length1;
		   y1=rect.y;
	   } 
	   cvDrawContours(dst_contours,cont,CV_RGB(255,255,255),CV_RGB(255,0,0),0,1,8,cvPoint(1,1));
	}
	printf("面积为:%f\n周长为:%f\n",area,length);
	printf("最大面积位置坐标为:%d  %d\n",x1,y1);
 //轮廓
 for (;cont1 != NULL;cont1=cont1->h_next)
  {
   CvRect rect=cvBoundingRect(cont1,0);
   float area1=fabs(cvContourArea(cont1,CV_WHOLE_SEQ));
   if(rect.x==x1&&y1==rect.y&&area1==area)
    cvDrawContours(dst_contours,cont1,CV_RGB(255,0,0),CV_RGB(255,0,0),0,1,8,cvPoint(1,1));
  }
    //窗口
    cvNamedWindow("show");
	cvShowImage("show",src);
	cvNamedWindow("show2");
	cvShowImage("show2",backImg);
	cvNamedWindow("show3");
	cvShowImage("show3",backRImg);
	cvNamedWindow("show4");
	cvShowImage("show4",cutImg);
	cvNamedWindow("show5");
	cvShowImage("show5",dst_contours);
	cvWaitKey(0);
	return 0;
}

           

所要用到的图片:

机器视觉实例(VC++6.0 + OpenCV1.0)

继续阅读