opencv入门之数米粒
要求:
给出一幅米粒图数出图中米粒数目以及最大米粒位置。
在原图上画出最大米粒的位置。
使用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入门之数米粒相关推荐
- python opencv 数米粒
1.介绍 opencv入门之数米粒:给出一幅米粒图数出图中米粒数目以及最大米粒位置.在原图上画出最大米粒的位置.并输出最大米粒的面积和最大米粒的周长.使用pycharm编码,亲测功能强大. 2.思路 ...
- python opencv学习笔记之数米粒,并返回每一个米粒的位置面积及总个数平均面积
之前曾经写过一道数米粒的作业,当时用的是c++中的opencv,这次用python试了一下. 原图及效果图 咦?水印怎么去啊 程序流程 程序的大致流程为: 1.读取图片 2.灰度化 3.二值化 4.膨 ...
- 【AI白身境】搞计算机视觉必备的OpenCV入门基础
文章首发于微信公众号<有三AI> [AI白身境]搞计算机视觉必备的OpenCV入门基础 今天是新专栏<AI白身境>的第五篇. 曾经看过一个视频,树莓派自平衡机器人自动追着小球跑 ...
- 转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析
[OpenCV入门教程之四] ROI区域图像叠加&初级图像混合 全剖析 浅墨_毛星云 2014-03-10 12:48:05 157425 收藏 19 最后发布:2014-03-10 12:4 ...
- 【opencv入门篇】 10个程序快速上手opencv【上】
导言:本系列博客目的在于能够在vs快速上手opencv,理论知识涉及较少,大家有兴趣可以查阅其他博客深入了解相关的理论知识,本博客后续也会对图像方向的理论进一步分析,敬请期待:) PS:官方文档永远是 ...
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/23184547 作者:毛星云(浅墨) ...
- OpenCV入门(七)快速学会OpenCV6色彩空间
OpenCV入门(七)快速学会OpenCV6色彩空间 作者:Xiou 1.色彩空间概述 色彩空间 (Color Space) 即以同的空间维度来表示某一色彩 (通常使用 3 个或者 4 个 值). R ...
- Opencv 入门篇学习记录(图片)
title: Opencv 入门篇学习记录(图片) Opencv 入门篇学习记录(图片) 前言 很早以前就接触Python了,大学的时候还自学了一段时间去做了课设,写了一些最速梯度下降法.黄金分割法. ...
- 【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨) ...
最新文章
- 计算机课堂有趣的游戏,有趣的课堂游戏作文9篇
- VS2017控制台工程日志输出到log文件的同时输出到屏幕
- 部署虚拟服务器,把网站部署到虚拟服务器
- python控制电脑关机_Python利用智能音箱语音控制电脑开关机
- php柱状图html代码,html5生成柱状图(条形图)效果的实例代码
- 一站式解决,Android 拍照 图库的各种问题
- 写作有困扰?不知道用什么词?不知道怎么解释不一致的结果?这个网站来帮你。
- 送你一份后端必备的 Git 分支开发规范指南
- scp传文件时报错Add correct host key in /root/.ssh/known_hosts to get rid of this message
- 机器学习算法实践:决策树 (Decision Tree)(转载)
- TensorFlow 语法及常用 API
- 植入式医疗电子设备供电电源原理与设计
- css 全文字体大小,CSS 字体大小
- php项目经验总结,php项目心得以及总结
- 中公教育12月04日内外盘分析
- bat for循环_bat教程[285] FOR/F options选项中usebackq的用法
- sql UPDATE的时候可以使用join吗
- C++ 强制类型转换:static_cast、dynamic_cast、const_cast 和 reinterpret_cast
- 如何查询以太信道接口_查询区块
- Centos hydra安装
热门文章
- FOC之park变换推导笔记
- 汽车的一类、二类、三类、四类底盘是怎么划分的?
- 【开关电源】电源仿真smplis
- 推荐几款很棒的文本编辑器
- 【AI案例】(二)搭建大数据Python生态知识体系
- matlab如何求解sbm模型,非期望产出的SBM模型代码问题
- 配置mybatis时xml出现 URI is not registed / Resource registered by this uri is not recognized 解决方法
- Opencv学习笔记1:安装opencv和VS2015并进行环境配置
- 04-ET框架的事件系统
- 逆战无法修复服务器,逆战登录时的各种问题 这些问题该如何解决?