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

基于对话框的程序。

实现界面:




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

[cpp]  view plain copy
  1. void CcountRiceDlg::OnBnClickedOpen()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     TCHAR szFilters[]=_T("BMP Files (*.bmp)|*.png|All Files (*.*)|*.*||");  
  5.     CFileDialog dlg(TRUE,_T("All Files(*.*)"),_T("*.*"),OFN_OVERWRITEPROMPT,szFilters);  
  6.     if (dlg.DoModal())  
  7.     {  
  8.         CString path=dlg.GetPathName();  
  9.         int sizeOfString = (path.GetLength() + 1);  
  10.         LPCTSTR  lpsz = new TCHAR[sizeOfString];  
  11.         lpsz =(LPCTSTR)path;  
  12.   
  13.                 CRect outputRect;  
  14.         GetDlgItem(IDC_ORIGIN_PIC)->GetWindowRect(&outputRect); //检索指定的对话框中的控件句柄;返回指定窗口的边框矩形的尺寸  
  15.         if (m_cvImage->Load(lpsz))  
  16.         {  
  17.             m_hasLoadImg=true;  
  18.             m_cvImage->Show(GetDlgItem(IDC_ORIGIN_PIC)->GetDC()->GetSafeHdc(),0,0,outputRect.Width(),outputRect.Height());  
  19.         }  
  20.   
  21.     }  
  22. }  


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

[cpp]  view plain copy
  1. void CcountRiceDlg::OnBnClickedProcess()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     if (!m_hasLoadImg)  
  5.     {  
  6.         OnBnClickedOpen();  
  7.     }  
  8.     CvvImage* tmp=new CvvImage;  
  9.     CvvImage* backImage=new CvvImage;  
  10.     IplConvKernel* element=cvCreateStructuringElementEx(4,4,1,1,CV_SHAPE_ELLIPSE,0);//形态学结构指针[创建结构元素,4列4行,椭圆形】  
  11.   
  12.     tmp->CopyOf(*m_cvImage);  
  13.     backImage->CopyOf(*m_cvImage);  
  14.     cvErode(m_cvImage->GetImage(),tmp->GetImage(),element,10);//腐蚀  
  15.     cvDilate(tmp->GetImage(),backImage->GetImage(),element,10);//这里得到的backImage是背景图像  
  16.     cvSub(m_cvImage->GetImage(),backImage->GetImage(),tmp->GetImage(),0);//用原始图像减去背景图像,tmp是结果图像  
  17.   
  18.     cvThreshold(tmp->GetImage(),backImage->GetImage(),50,255,CV_THRESH_BINARY);//这里得到的backImage是二值图  
  19.   
  20.     CvMemStorage* stor=cvCreateMemStorage(0);  
  21.     CvSeq * cont=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);  
  22.     IplImage* dst;  
  23.   
  24.     dst = cvCreateImage( cvGetSize(backImage->GetImage()), backImage->GetImage()->depth, 1 );  
  25.     cvCvtColor(backImage->GetImage(), dst, CV_BGR2GRAY );//3通道->1通道  
  26.   
  27.     int numberOfObject=cvFindContours(dst,stor,&cont,sizeof(CvContour),CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));  
  28.   
  29.   
  30.     double maxArea=0;  
  31.     double tmpArea=0;  
  32.     CvSeq* maxAreaRice=0;  
  33.     double maxLength=0;  
  34.     double tmpLength=0;  
  35.     CvSeq* maxLengthRice=0;  
  36.     //cvThreshold(dst,dst,0,255,CV_THRESH_BINARY);//在画轮廓前先把图像变成白色  
  37.     IplImage* dst_contours = cvCreateImage( cvGetSize(dst), dst->depth, dst->nChannels);  
  38.     cvThreshold( dst_contours, dst_contours ,0, 0, CV_THRESH_BINARY ); //在画轮廓前先把图像变成黑色。 threshold=0,pixel>0,pixel = 0.  
  39.   
  40.     for (;cont;cont=cont->h_next)  
  41.     {     
  42.   
  43.         tmpArea=fabs(cvContourArea(cont,CV_WHOLE_SEQ));  
  44.         if(tmpArea>maxArea)  
  45.         {     
  46.             maxArea=tmpArea;  
  47.             maxAreaRice=cont;  
  48.         }  
  49.         tmpLength=cvArcLength(cont);  
  50.         if (tmpLength>maxLength)  
  51.         {  
  52.             maxLength=tmpLength;  
  53.             maxLengthRice=cont;  
  54.         }  
  55.       
  56.         if (tmpArea>10)  
  57.         {  
  58.             cvDrawContours(dst_contours,cont,CV_RGB(0,0,255),CV_RGB(255,0,0),0,1,8,cvPoint(0,0));//在图像上绘制外部和内部轮廓.  
  59.             //【图像,第一个轮廓指针,外轮廓的颜色,内轮廓的颜色,画轮廓的最大层数(如果是0,只绘制contour),线条粗细,线条类型,按给定值移动所有点的坐标 】  
  60.         }  
  61.   
  62.   
  63.     }  
  64.   
  65.     CRect outputRect;   
  66.     GetDlgItem(IDC_PROCESSED_PIC)->GetWindowRect(&outputRect);  
  67.     m_ProcessedImage->CopyOf(dst_contours,1);  
  68.   
  69.     CRect rect;  
  70.     SetRect( rect, 0, 0, outputRect.Width(),outputRect.Height() );     
  71.   
  72.     m_ProcessedImage->DrawToHDC(GetDlgItem(IDC_PROCESSED_PIC)->GetDC()->GetSafeHdc(),&rect);  
  73.   
  74.     m_result.Format(_T("米粒数目为: %d 个\n米粒最大面积: %f\n米粒最大周长: %f"),numberOfObject,maxArea,maxLength);  
  75.     UpdateData(FALSE);  
  76.   
  77.     cvReleaseImage(&dst);  
  78.     cvReleaseImage(&dst_contours);  
  79.     cvReleaseMemStorage(&stor);  
  80. }  

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

[cpp]  view plain copy
  1. void CcountRiceDlg::OnBnClickedExit()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     CDialog::OnCancel();  
  5. }  

记得在析构函数里面释放图片哦~
[cpp]  view plain copy
  1. CcountRiceDlg::~CcountRiceDlg()  
  2. {  
  3.     if (m_cvImage)  
  4.     {  
  5.         delete m_cvImage;  
  6.     }  
  7.     if (m_ProcessedImage)  
  8.     {  
  9.         delete m_ProcessedImage;  
  10.     }  
  11. }  


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 中添加:

[cpp]  view plain copy
  1.               CDialog::OnPaint();  
  2. CRect outputRect;  
  3.   
  4. GetDlgItem(IDC_PROCESSED_PIC)->GetWindowRect(&outputRect);  
  5. m_ProcessedImage->Show(GetDlgItem(IDC_PROCESSED_PIC)->GetDC()->GetSafeHdc(),0,0,outputRect.Width(),outputRect.Height());  
  6.   
  7. GetDlgItem(IDC_ORIGIN_PIC)->GetWindowRect(&outputRect);  
  8. CRect rect;  
  9. SetRect( rect, 0, 0, outputRect.Width(),outputRect.Height() );     
  10.        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版本下,这个还是通不过,网上查了好多,可素,感觉乱七八糟的,谁有简单又方便的方案????


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值