要求:

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

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

使用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. 计算机课堂有趣的游戏,有趣的课堂游戏作文9篇
  2. VS2017控制台工程日志输出到log文件的同时输出到屏幕
  3. 部署虚拟服务器,把网站部署到虚拟服务器
  4. python控制电脑关机_Python利用智能音箱语音控制电脑开关机
  5. php柱状图html代码,html5生成柱状图(条形图)效果的实例代码
  6. 一站式解决,Android 拍照 图库的各种问题
  7. 写作有困扰?不知道用什么词?不知道怎么解释不一致的结果?这个网站来帮你。
  8. 送你一份后端必备的 Git 分支开发规范指南
  9. scp传文件时报错Add correct host key in /root/.ssh/known_hosts to get rid of this message
  10. 机器学习算法实践:决策树 (Decision Tree)(转载)
  11. TensorFlow 语法及常用 API
  12. 植入式医疗电子设备供电电源原理与设计
  13. css 全文字体大小,CSS 字体大小
  14. php项目经验总结,php项目心得以及总结
  15. 中公教育12月04日内外盘分析
  16. bat for循环_bat教程[285] FOR/F options选项中usebackq的用法
  17. sql UPDATE的时候可以使用join吗
  18. C++ 强制类型转换:static_cast、dynamic_cast、const_cast 和 reinterpret_cast
  19. 如何查询以太信道接口_查询区块
  20. Centos hydra安装

热门文章

  1. FOC之park变换推导笔记
  2. 汽车的一类、二类、三类、四类底盘是怎么划分的?
  3. 【开关电源】电源仿真smplis
  4. 推荐几款很棒的文本编辑器
  5. 【AI案例】(二)搭建大数据Python生态知识体系
  6. matlab如何求解sbm模型,非期望产出的SBM模型代码问题
  7. 配置mybatis时xml出现 URI is not registed / Resource registered by this uri is not recognized 解决方法
  8. Opencv学习笔记1:安装opencv和VS2015并进行环境配置
  9. 04-ET框架的事件系统
  10. 逆战无法修复服务器,逆战登录时的各种问题 这些问题该如何解决?