OpenCV统计米粒数目-计算联通区域的个数及联通区域内像素的个数

分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net

基于对话框的程序。

实现界面:

打开图片的消息响应函数:

void CcountRiceDlg::OnBnClickedOpen()
{
	// TODO: 在此添加控件通知处理程序代码
	TCHAR szFilters[]=_T("BMP Files (*.bmp)|*.png|All Files (*.*)|*.*||");
	CFileDialog dlg(TRUE,_T("All Files(*.*)"),_T("*.*"),OFN_OVERWRITEPROMPT,szFilters);
	if (dlg.DoModal())
	{
		CString	path=dlg.GetPathName();
		int sizeOfString = (path.GetLength() + 1);
		LPCTSTR  lpsz = new TCHAR[sizeOfString];
		lpsz =(LPCTSTR)path;

    	        CRect outputRect;
		GetDlgItem(IDC_ORIGIN_PIC)->GetWindowRect(&outputRect); //检索指定的对话框中的控件句柄;返回指定窗口的边框矩形的尺寸
		if (m_cvImage->Load(lpsz))
		{
			m_hasLoadImg=true;
			m_cvImage->Show(GetDlgItem(IDC_ORIGIN_PIC)->GetDC()->GetSafeHdc(),0,0,outputRect.Width(),outputRect.Height());
		}

	}
}

图片处理的消息响应函数:

void CcountRiceDlg::OnBnClickedProcess()
{
	// TODO: 在此添加控件通知处理程序代码
	if (!m_hasLoadImg)
	{
		OnBnClickedOpen();
	}
	CvvImage* tmp=new CvvImage;
	CvvImage* backImage=new CvvImage;
	IplConvKernel* element=cvCreateStructuringElementEx(4,4,1,1,CV_SHAPE_ELLIPSE,0);//形态学结构指针[创建结构元素,4列4行,椭圆形】

	tmp->CopyOf(*m_cvImage);
	backImage->CopyOf(*m_cvImage);
	cvErode(m_cvImage->GetImage(),tmp->GetImage(),element,10);//腐蚀
	cvDilate(tmp->GetImage(),backImage->GetImage(),element,10);//这里得到的backImage是背景图像
	cvSub(m_cvImage->GetImage(),backImage->GetImage(),tmp->GetImage(),0);//用原始图像减去背景图像,tmp是结果图像

	cvThreshold(tmp->GetImage(),backImage->GetImage(),50,255,CV_THRESH_BINARY);//这里得到的backImage是二值图

	CvMemStorage* stor=cvCreateMemStorage(0);
	CvSeq * cont=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
	IplImage* dst;

	dst = cvCreateImage( cvGetSize(backImage->GetImage()), backImage->GetImage()->depth, 1 );
	cvCvtColor(backImage->GetImage(), dst, CV_BGR2GRAY );//3通道->1通道

	int numberOfObject=cvFindContours(dst,stor,&cont,sizeof(CvContour),CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));

	double maxArea=0;
	double tmpArea=0;
	CvSeq* maxAreaRice=0;
	double maxLength=0;
	double tmpLength=0;
	CvSeq* maxLengthRice=0;
	//cvThreshold(dst,dst,0,255,CV_THRESH_BINARY);//在画轮廓前先把图像变成白色
	IplImage* dst_contours = cvCreateImage( cvGetSize(dst), dst->depth, dst->nChannels);
	cvThreshold( dst_contours, dst_contours ,0, 0, CV_THRESH_BINARY ); //在画轮廓前先把图像变成黑色。 threshold=0,pixel>0,pixel = 0.

	for (;cont;cont=cont->h_next)
	{	

		tmpArea=fabs(cvContourArea(cont,CV_WHOLE_SEQ));
		if(tmpArea>maxArea)
		{
			maxArea=tmpArea;
			maxAreaRice=cont;
		}
		tmpLength=cvArcLength(cont);
		if (tmpLength>maxLength)
		{
			maxLength=tmpLength;
			maxLengthRice=cont;
		}

		if (tmpArea>10)
		{
			cvDrawContours(dst_contours,cont,CV_RGB(0,0,255),CV_RGB(255,0,0),0,1,8,cvPoint(0,0));//在图像上绘制外部和内部轮廓.
			//【图像,第一个轮廓指针,外轮廓的颜色,内轮廓的颜色,画轮廓的最大层数(如果是0,只绘制contour),线条粗细,线条类型,按给定值移动所有点的坐标 】
		}

	}

	CRect outputRect;
	GetDlgItem(IDC_PROCESSED_PIC)->GetWindowRect(&outputRect);
	m_ProcessedImage->CopyOf(dst_contours,1);

	CRect rect;
	SetRect( rect, 0, 0, outputRect.Width(),outputRect.Height() );   

	m_ProcessedImage->DrawToHDC(GetDlgItem(IDC_PROCESSED_PIC)->GetDC()->GetSafeHdc(),&rect);

	m_result.Format(_T("米粒数目为: %d 个\n米粒最大面积: %f\n米粒最大周长: %f"),numberOfObject,maxArea,maxLength);
	UpdateData(FALSE);

	cvReleaseImage(&dst);
	cvReleaseImage(&dst_contours);
	cvReleaseMemStorage(&stor);
}

退出按钮的消息响应,重载了一下 Dialog的 OnCancel 函数:

void CcountRiceDlg::OnBnClickedExit()
{
	// TODO: 在此添加控件通知处理程序代码
	CDialog::OnCancel();
}

记得在析构函数里面释放图片哦~

CcountRiceDlg::~CcountRiceDlg()
{
	if (m_cvImage)
	{
		delete m_cvImage;
	}
	if (m_ProcessedImage)
	{
		delete m_ProcessedImage;
	}
}

在 DoDataExchange 函数里面, DDX_Text(pDX, IDC_RESULT, m_result);

是将 CString 类型的m_result 将 控件 IDC_RESULT 关联起来~然后,就可以在static text 显示字符串了。。。。。

控件和变量的关联是在 DoDataExchange 中显示的 : DDX_Text(pDX, IDC_RESULT, m_result);

方法VC classwizard -- member variables 。vs 中是在控件上右击--添加变量~~~是吧

在 OnInitDialog()

中添加~

m_cvImage=new CvvImage;
m_ProcessedImage=new CvvImage;
m_hasLoadImg=false;

在OnPaint() 的

else 中添加:

                CDialog::OnPaint();
		CRect outputRect;

		GetDlgItem(IDC_PROCESSED_PIC)->GetWindowRect(&outputRect);
		m_ProcessedImage->Show(GetDlgItem(IDC_PROCESSED_PIC)->GetDC()->GetSafeHdc(),0,0,outputRect.Width(),outputRect.Height());

		GetDlgItem(IDC_ORIGIN_PIC)->GetWindowRect(&outputRect);
		CRect rect;
		SetRect( rect, 0, 0, outputRect.Width(),outputRect.Height() );
	        m_cvImage->DrawToHDC(GetDlgItem(IDC_ORIGIN_PIC)->GetDC()->GetSafeHdc(),&rect);

【paint 函数什么时候被调用呢?当注释掉 OnBnClickedOpen() 中显示图片用的是show函数 时,没有影响~~~~

WM_PAINT消息仅用于以下两种情况:
1. 当用户移动窗口或显示窗口,或用户改变窗口的大小,或滚动窗口用户区时,Windows会向窗口函数发送WM_PAINT消息。
2. 当Windows关闭覆盖窗口部分区域的对话框时,以及菜单下拉出来又被释放时,窗口用户区被临时覆盖,系统会试图恢复显示区域,可能向窗口函数发送一条WM_PAINT消息,要求应用程序刷新其用户区。
这两种情况下将使MFC调用OnPaint处理函数。也仅有这两种情况,视图对象具有一个OnPaint处理函数。

开始点击 [打开图片] 时,算是哪种情况呢?%>_<% 】

 

核心代码:

int numberOfObject=cvFindContours(dst,stor,&cont,sizeof(CvContour),CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));

 

Area=fabs(cvContourArea(cont,CV_WHOLE_SEQ));

 

Length=cvArcLength(cont)

圈圈的个数就是 连通区域的个数了

 

关于LPCTSTR转换为const char * ??

如何将LPCTSTR转换为const char * ?? 项目--属性--配置属性--字符集 改为使用多字节 居然可以这么简单~~~【LPCTSTR 1、在非UNICODE环境下为 const char * 2、在UNICODE环境下为 const unsigned short * so,需要将宽字符转换为多字节】

可是,Release版本下,这个还是通不过,网上查了好多,可素,感觉乱七八糟的,谁有简单又方便的方案????

这个应该自己设计算法来实现的~~~~~哎~~~菜鸟啊菜鸟,这个才2行核心代码而已啊,赶紧学着自己写一个吧%>_<%

具体代码: http://download.csdn.net/detail/timidsmile/3671517

http://blog.csdn.net/timidsmile/article/details/6859954

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net

原文地址:https://www.cnblogs.com/sownchz/p/10499617.html

时间: 2024-08-30 07:40:55

OpenCV统计米粒数目-计算联通区域的个数及联通区域内像素的个数的相关文章

统计页面停留时间计算

一.页面停留时间与网站停留时间是如何计算出来的? 假设用户访问了网站的主页(Home).分析工具将这个访问者标记为一个Visit,接着这个访问者又浏览了另外两个页面(Page2和Page3),然后他离开了你的网站.如下图所示: 我们想要知道的是: Tp = 花费在一个页面上的时间 Ts = 花费在这网站上的总时间 假如这个用户从10:00开始访问网站: 对于Page2而言,访问时间是10:05-10:01,即4分钟. 接着访问者来到了Page3页面,他发现改页面无法满足他的需求或是他要找的内容已

MapReduce流程、如何统计任务数目以及Partitioner

核心功能描述 应用程序通常会通过提供map和reduce来实现 Mapper和Reducer接口,它们组成作业的核心. Map是一类将输入记录集转换为中间格式记录集的独立任务. 这种转换的中间格式记录集不需要与输入记录集的类型一致.一个给定的输入键值对可以映射成0个或多个输出键值对.Hadoop Map/Reduce框架为每一个InputSplit产生一个map任务,而每个InputSplit是由该作业的InputFormat产生的. 什么是InputSplit?InputSplit是指分片,在

统计文件数目(不包括隐藏文件/文件夹)

统计文件数目(不包括隐藏文件/文件夹) ls -l | grep "^-" | wc -l 统计当前目录下文件的数目 ls -lR | grep "^-" | wc -l 统计当前目录下文件的数目,包括子目录里的 ls -l | grep "^d" | wc -l 统计当前目录下文件夹(也就是目录)的数目 ls -lR | grep "^d" | wc -l 统计当前目录下文件夹(也就是目录)的数目,包括子目录里的 注意是英文

计算1-1000之间能被3整除的偶数的个数

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目

Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是几份基本的模版 首先是无向图割点桥的代码 下面的代码是用于求割点数目的 其中add_block[u] = x  表示删除u点之后增加的联通块个数.注意是增加的联通块个数 const int MAXN = 1010; const int MAXM = 10010; const int INF = 0x

笔记 OSPF多区域配置 STUB区域 路由重分发 NSSA区域配置

主题:OSPF 多区域配置 ABR:area border router ,区域边界路由器 -作用 实现不同区域之间的互通: -定义 同时连接骨干区域和非骨干区域的路由器: OSPF为什么会引入/划分区域? 划分区域以后,可以带来以下好处: 1.节省区域中的每一个设备的系统资源 (大区域被划分以后,小区域中的数据库内容就会变少) (同一个区域中的所有的路由器,数据库是完全相同) 2.增强 OSPF 网络的稳定性 (一个不稳定链路造成的不良影响,仅在同一个区域) (中传播,不会影响到其他区域) 验

UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A<=pi<=B,l<=i<=r). 参考链接:http://www.cnblogs.com/zj62/p/3558967.html #include <iostream> #include <cstdio> #include <cstring> #incl

【c语言】统计一个数二进制中的1的个数

// 统计一个数二进制中的1的个数 #include <stdio.h> int count(int a) { int count = 0; while (a) { count++; a = a & (a - 1); } return count; } int main() { printf("%d\n", count(10)); printf("%d\n", count(0)); printf("%d\n", count(-

Linux学习之路之DNS的配置文件和正解区域文件、反解区域文件

DNS正解区域文件 在DNS中,我们知道有域和区域的概念,域的英文名称是domain,它是一种逻辑概念:而区域英文全称zone,它是一种物理概念.且zone分为正解区域和反解区域 正解区域:提供正向解析的服务,即FQDN-->IP的过程 反解区域:提供反向解析的服务,即IP-->FQDN的过程 不管好似正解区域还是反解区域,都通过了一个配置文件,这个文件中的每一个条目就是一个资源记录(Resource Record,RR). 资源记录的类型主要有这些,且这些资源记录的格式为: SOA:起始授权