要求:

给出一幅米粒图数出图中米粒数目以及最大米粒位置。

在原图上画出最大米粒的位置。

使用otsu、迭代和平均灰度进行二值分割。

声明:

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

编程软件为vc6.

opencv1.0环境配置请访问http://blog.csdn.net/qq_32300341/article/details/70186379

#include "cv.h"
#include "highgui.h"
#include<stdio.h>
#include<iostream>
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]<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;
}
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<tmpArea1)
{  
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分割图像显示");//销毁窗口资源
//读取和显示完图像之后,要及时释放所占的内存资源.

}

此为米粒原图

opencv入门之数米粒相关推荐

  1. python opencv 数米粒

    1.介绍 opencv入门之数米粒:给出一幅米粒图数出图中米粒数目以及最大米粒位置.在原图上画出最大米粒的位置.并输出最大米粒的面积和最大米粒的周长.使用pycharm编码,亲测功能强大. 2.思路 ...

  2. python opencv学习笔记之数米粒,并返回每一个米粒的位置面积及总个数平均面积

    之前曾经写过一道数米粒的作业,当时用的是c++中的opencv,这次用python试了一下. 原图及效果图 咦?水印怎么去啊 程序流程 程序的大致流程为: 1.读取图片 2.灰度化 3.二值化 4.膨 ...

  3. 【AI白身境】搞计算机视觉必备的OpenCV入门基础

    文章首发于微信公众号<有三AI> [AI白身境]搞计算机视觉必备的OpenCV入门基础 今天是新专栏<AI白身境>的第五篇. 曾经看过一个视频,树莓派自平衡机器人自动追着小球跑 ...

  4. 转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析

    [OpenCV入门教程之四] ROI区域图像叠加&初级图像混合 全剖析 浅墨_毛星云 2014-03-10 12:48:05 157425 收藏 19 最后发布:2014-03-10 12:4 ...

  5. 【opencv入门篇】 10个程序快速上手opencv【上】

    导言:本系列博客目的在于能够在vs快速上手opencv,理论知识涉及较少,大家有兴趣可以查阅其他博客深入了解相关的理论知识,本博客后续也会对图像方向的理论进一步分析,敬请期待:) PS:官方文档永远是 ...

  6. 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/23184547 作者:毛星云(浅墨) ...

  7. OpenCV入门(七)快速学会OpenCV6色彩空间

    OpenCV入门(七)快速学会OpenCV6色彩空间 作者:Xiou 1.色彩空间概述 色彩空间 (Color Space) 即以同的空间维度来表示某一色彩 (通常使用 3 个或者 4 个 值). R ...

  8. Opencv 入门篇学习记录(图片)

    title: Opencv 入门篇学习记录(图片) Opencv 入门篇学习记录(图片) 前言 很早以前就接触Python了,大学的时候还自学了一段时间去做了课设,写了一些最速梯度下降法.黄金分割法. ...

  9. 【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨) ...

最新文章

  1. 程序员必知的20个Python技巧
  2. 安装Ubuntu server并实现远程访问
  3. 2011年数据库大会纪行
  4. mysql 整数_MySQL 整数(int)数据类型
  5. tomcat session失效时间
  6. 射线计算机,面对射线-射频-计算机 我愿做“影像工匠师”
  7. 转载 WebService 的CXF框架 WS方式Spring开发
  8. Ubuntu 新建qt项目时出现 No valid kits found.
  9. php中输入这个网站的网址跳转到你定义的页面代码
  10. python下列数据中不属于字符串的是_下列数据中,不属于字符串的是( )。 (6.0分)_学小易找答案...
  11. .NET简谈反射(动态调用)
  12. 3dsmax模型导入超图
  13. 【2021/12/21】MySQL的json查询之json_keys、json_object、json_overlaps、json_pretty
  14. 保送北大,连发三篇Science,这位80后川妹子近日再发重磅级研究成果!
  15. lmp+heartbeat+drbd
  16. 下载webStorm,nodejs,git并简单配置,为JavaScript做准备
  17. JAVA Zip压缩 Tar压缩 tar.gz打包压缩
  18. python自动化测试平台方案_基于Python的软件测试自动化平台研究
  19. Linux下的Chm文件阅读器
  20. 2021年个人学习生活总结和2022年学习生活计划

热门文章

  1. 神经网络ANN算法——鸢尾花案例python实现
  2. 获取淘宝店铺所有商品数据
  3. BP(商业计划书写)
  4. 每天一道Java编程05--逢7过:在控制台打印出1-100之间的满足逢七必过规则的数据
  5. 二、Node 多版本管理
  6. 华大单片机HC32L136定时器时间如何计算
  7. 数学中的向量相关知识
  8. 【安富莱】【RL-TCPnet网络教程】第8章 RL-TCPnet网络协议栈移植(RTX)
  9. python局部静态变量_python如何设置静态变量
  10. Android使用Glide加载Gif慢 获取gif时间