找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4785|回复: 7
打印 上一主题 下一主题
收起左侧

视觉检测设计与实践(米粒计数)c++源程序

[复制链接]
跳转到指定楼层
楼主
ID:209005 发表于 2017-6-7 22:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这是视觉检测试验中的米粒计数:

c++源程序如下:
  1. // 米粒计数.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"
  4. #include "cv.h"
  5. #include "highgui.h"
  6. #include "cxcore.h"
  7. #include "stdlib.h"
  8. #include <iostream>
  9. using namespace std;

  10. //获取灰度图像
  11. IplImage * LoadImage()
  12. {
  13.         //IplImage(Cxcore基础结构)
  14.         //载入彩色图像(3信道)(HighGUI读取与保存图像)
  15.         IplImage * pImageSrc = cvLoadImage("rice.png",1);//测试图.jpg
  16.         if(!pImageSrc)
  17.         {
  18.                 cout << "Could not load image file!" << endl;
  19.                 exit(0);
  20.         }
  21.        
  22.         //显示图像(HighGUI简单图形界面)
  23.         cvNamedWindow("原米粒图像");
  24.         //        cvShowImage("原米粒图像",pImageSrc);
  25.         //        cvWaitKey(0);
  26.         //        cvDestroyWindow("原米粒图像");
  27.        
  28.        
  29.         //灰度图(Cxcore数组操作)
  30.         IplImage* pImageGray = cvCreateImage(cvGetSize(pImageSrc),IPL_DEPTH_8U,1);
  31.         //色彩空间转换(Cv图像处理)
  32.         cvCvtColor(pImageSrc,pImageGray,CV_BGR2GRAY);
  33.        
  34.         cvShowImage("原米粒图像",pImageGray);
  35.         cvWaitKey(0);
  36.        
  37.         //Cxcore数组操作
  38.         cvReleaseImage(&pImageSrc);
  39.         return pImageGray;
  40. }

  41. //对灰度图像进行预处理(均值滤波)
  42. IplImage * PreProcess(IplImage * pImageGray)
  43. {
  44.         //预处理结果图(Cxcore数组操作)
  45.         IplImage* pImagePrePro = cvCreateImage(cvGetSize(pImageGray),IPL_DEPTH_8U,1);
  46.         //均值滤波(Cv图像处理)
  47.         cvSmooth(pImageGray, pImagePrePro,CV_BLUR,3,3,0,0);
  48.         //显示图像(HighGUI简单图形界面)
  49.         cvNamedWindow("均值滤波图像");
  50.         cvShowImage("均值滤波图像",pImagePrePro);
  51.         cvWaitKey(0);
  52.        
  53.         /*        //opencv滤波结果
  54.         for(int xindex = 10; xindex < 20; xindex ++)
  55.         {
  56.         for(int yindex = 10; yindex < 20; yindex ++)
  57.         {
  58.         cout << cvRound(cvGet2D(pImagePrePro,yindex,xindex).val[0]) << '\t';
  59.         }
  60.         }
  61.         cout << endl;*/
  62.        
  63.         //自己编程对比
  64.         //图像拷贝(Cxcore数组操作)
  65.         IplImage* pImagePrePro1 = cvCloneImage(pImageGray);
  66.         //        cvSet(pImagePrePro1,cvScalarAll(0),0);
  67.        
  68.         //均值滤波(Cxcore数组操作)
  69.         CvScalar sum;
  70.         //滑动窗口增量
  71.         int xincrement = -1,xincrement1 = 1;
  72.         int yincrement = -1,yincrement1 = 1;
  73.         for(int xindex = 1; xindex < pImageGray->width - 1; xindex ++)
  74.         {
  75.                 for(int yindex = 1; yindex < pImageGray->height - 1; yindex ++)
  76.                 {
  77.                         sum.val[0] = 0;
  78.                         //滑动窗口计算均值
  79.                         for(int xtemp = xincrement; xtemp <= xincrement1 ;xtemp ++)
  80.                         {
  81.                                 for(int ytemp = yincrement; ytemp <= yincrement1;ytemp ++)
  82.                                 {
  83.                                         //注意:数组和图像的xy坐标不一样
  84.                                         sum.val[0] += cvGet2D(pImageGray,yindex + ytemp,xindex + xtemp).val[0];
  85.                                 }
  86.                         }
  87.                         //求均值(Cxcore数组操作)
  88.                         sum.val[0] = cvRound(sum.val[0] / ((yincrement1 - yincrement + 1) * (xincrement1 - xincrement + 1)));
  89.                         cvSet2D(pImagePrePro1,yindex,xindex,sum);
  90.                 }
  91.         }
  92.         //显示图像(HighGUI简单图形界面)
  93.         cvNamedWindow("均值滤波图像1");
  94.         cvShowImage("均值滤波图像1",pImagePrePro1);
  95.         cvWaitKey(0);
  96.        
  97.         /*        //测试滤波的正确性
  98.         //自己编程实现滤波结果
  99.         for(xindex = 10; xindex < 20; xindex ++)
  100.         {
  101.         for(int yindex = 10; yindex < 20; yindex ++)
  102.         {
  103.         cout << cvRound(cvGet2D(pImagePrePro1,yindex,xindex).val[0]) << '\t';
  104.         }
  105.         }
  106.         cout << endl;*/
  107.        
  108.         cvReleaseImage(&pImagePrePro1);
  109.         return pImagePrePro;
  110. }

  111. //迭代阈值分割
  112. IplImage * Segmentation(IplImage * pImagePrePro)
  113. {
  114.         IplImage* pImageBw = cvCloneImage(pImagePrePro);
  115.        
  116.         //二值分割图像(Cv图像处理)
  117.         cvThreshold(pImagePrePro, pImageBw, 119 ,255, CV_THRESH_BINARY);
  118.        
  119.         //显示图像(HighGUI简单图形界面)
  120.         cvNamedWindow("二值图像");
  121.         cvShowImage("二值图像",pImageBw);
  122.         cvWaitKey(0);
  123.        
  124.         //自己编程实现迭代阈值分割
  125.         IplImage* pImageBw1 = cvCloneImage(pImagePrePro);
  126.         //初始阈值为图像的平均灰度(Cxcore数组操作)
  127.         CvScalar threshold = cvAvg(pImageBw1);
  128.         //        cout << threshold.val[0] << endl;
  129.        
  130.         /*//求平均灰度,验证初始阈值的正确性(可以用cvSum)
  131.         CvScalar sum;
  132.         sum.val[0] = 0;
  133.         for(int xindex = 0; xindex < pImagePrePro->width; xindex ++)
  134.         {
  135.         for(int yindex = 0; yindex < pImagePrePro->height; yindex ++)
  136.         {
  137.         sum.val[0] += cvGet2D(pImagePrePro,yindex,xindex).val[0];
  138.         }
  139.         }
  140.         sum.val[0] = sum.val[0] / (pImagePrePro->width * pImagePrePro->height);
  141.         cout << sum.val[0] << endl;
  142.         */
  143.        
  144.         //迭代阈值分割
  145.         CvScalar threshold1;
  146.         threshold1.val[0] = 0;
  147.         CvScalar temp1,temp2;
  148.         temp1.val[0] = 0;
  149.         temp2.val[0] = 0;
  150.         while(abs(threshold.val[0] - threshold1.val[0]) > 0.1)
  151.         {
  152.                 threshold1 = threshold;
  153.                 IplImage* pImageTemp = cvCloneImage(pImageBw1);
  154.                 //计算前景的平均灰度
  155.                 cvThreshold(pImageBw1, pImageTemp,threshold1.val[0],255, CV_THRESH_TOZERO);
  156.                 //注意:不能用cvAvg (Cxcore数组操作)
  157.                 temp1.val[0] = cvSum(pImageTemp).val[0] / cvCountNonZero(pImageTemp);
  158.                
  159.                 //计算背景的平均灰度
  160.                 cvThreshold(pImageBw1, pImageTemp,threshold1.val[0],255, CV_THRESH_TOZERO_INV);
  161.                 temp2.val[0] = cvSum(pImageTemp).val[0] / cvCountNonZero(pImageTemp);
  162.                
  163.                 //获取新阈值
  164.                 threshold.val[0] = (temp1.val[0] + temp2.val[0]) / 2;
  165.                 cvReleaseImage(&pImageTemp);
  166.         }
  167.         //迭代后得到分割阈值
  168.         cout << "迭代阈值:" << threshold.val[0] << endl;
  169.        
  170.         //二值分割图像(Cv图像处理)
  171.         cvThreshold(pImageBw1, pImageBw1, threshold.val[0] ,255, CV_THRESH_BINARY);
  172.        
  173.         //显示图像(HighGUI简单图形界面)
  174.         cvNamedWindow("二值图像1");
  175.         cvShowImage("二值图像1",pImageBw1);
  176.         cvWaitKey(0);
  177.        
  178.         cvReleaseImage(&pImageBw1);
  179.         return pImageBw;
  180. }

  181. void GetParameter(IplImage * pImageBw)
  182. {
  183.         //轮廓的存储容器(Cxcore动态结构)
  184.         CvMemStorage* storage = cvCreateMemStorage(0);
  185.         //输出参数:包含第一个输出轮廓的指针
  186.         CvSeq* first_contour = 0;
  187.         IplImage* pImageBw1 = cvCloneImage(pImageBw);
  188.         //在二值图像中寻找定点序列轮廓(Cv图像处理)//注意pImgBw1会被改变
  189.         int contourNum = cvFindContours(pImageBw1,storage,&first_contour,
  190.                 sizeof(CvContour), CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
  191.        
  192.         //freeman链码
  193.         //轮廓的存储容器1(Cxcore动态结构)
  194.         CvMemStorage* storage1 = cvCreateMemStorage(0);
  195.         //输出参数:包含第一个输出轮廓的指针
  196.         CvSeq* first_contour1 = 0;
  197.         IplImage* pImageBw2 = cvCloneImage(pImageBw);
  198.         //在二值图像中寻找freeman链码轮廓(Cv图像处理)//注意pImgBw1会被改变
  199.         int contourNum1 = cvFindContours(pImageBw2,storage1,&first_contour1,
  200.                 sizeof(CvChain), CV_RETR_EXTERNAL,CV_CHAIN_CODE);
  201.        
  202.         //轮廓图
  203.         IplImage* image = cvCloneImage(pImageBw);
  204.         cvSet(image,cvScalarAll(0),0);
  205.         //将所有轮廓画出(Cxcore绘图函数)   
  206.     cvDrawContours(image, first_contour, CV_RGB(255,255,255), CV_RGB(255,255,255),2, 1, 0);
  207.         cvNamedWindow( "轮廓图");
  208.         cvShowImage( "轮廓图", image);
  209.         cvWaitKey(0);
  210.        
  211.         //获取freeman链码
  212.         CvSeqReader reader;
  213.        
  214.         //用于显示外接矩形
  215.         IplImage* image1 = cvCreateImage(cvGetSize(pImageBw),IPL_DEPTH_8U,3);
  216.        
  217.         for(CvSeq* contour = first_contour,*contour1 = first_contour1;
  218.         contour != 0,contour1 != 0;contour=contour->h_next,contour1=contour1->h_next)
  219.         {
  220.                
  221.                 cvSet(image,cvScalarAll(0),0);
  222.                 cvDrawContours(image,contour,CV_RGB(255, 255, 255),CV_RGB(255, 255, 255),0, CV_FILLED, 8);
  223.         //        cvShowImage( "轮廓图", image);
  224.                
  225.                 cout << "轮廓点数:" << contour->total << '\t';
  226.                 //(Cv结构分析)
  227.                 cout << "周长:" << cvArcLength(contour) << '\t';
  228.                
  229.                 //自己计算周长
  230.                 //(Cxcore动态结构)
  231.                 cvStartReadSeq((CvSeq*)contour1, &reader, 0 );
  232.                 double perimeter = 0;
  233.                 for(int cNum = 0; cNum < contour->total; cNum ++ )
  234.                 {
  235.                         char code;
  236.                         //获取链码
  237.                         CV_READ_SEQ_ELEM(code, reader);
  238.                         //链码为偶数则周长+1
  239.                         if(int(code) % 2 == 0)
  240.                         {
  241.                                 perimeter += 1;
  242.                         }
  243.                         //链码为奇数,则周长+sqrt(2)
  244.                         if(int(code) % 2 != 0)
  245.                         {
  246.                                 perimeter += sqrt(2);
  247.                         }
  248.                 }
  249.                 cout << "计算的周长:" << perimeter << '\t';
  250.                
  251.                 cout << "面积:" << fabs(cvContourArea(contour)) << '\t';
  252.                 cout << "轮廓内非0点数:" << cvCountNonZero(image) << '\t';
  253.         //        cvWaitKey(0);
  254.                
  255.                 //最小外接矩形图
  256.                 cvSet(image1,cvScalarAll(0),0);
  257.                 cvDrawContours(image1,contour,CV_RGB(255, 255, 255),CV_RGB(255, 255, 255),0, CV_FILLED, 8);
  258.                 //对给定2D点集,寻找最小面积的外围矩形(Cv结构分析)
  259.                 CvBox2D box = cvMinAreaRect2(contour,NULL);

  260.                 cout << "中心坐标:(" << box.center.x << "," << box.center.y << ")" << '\t';
  261.                 cvSet2D(image1,box.center.y,box.center.x,CV_RGB(0, 0, 255));
  262.                 cout << "长:" << (box.size.height > box.size.width?box.size.height:box.size.width) << '\t';
  263.                 cout << "宽:" << (box.size.height > box.size.width?box.size.width:box.size.height) << '\t';

  264.                 //绘制外接最小矩形  
  265.                 CvPoint2D32f pt[4];
  266.                 //寻找盒子的顶点(Cv结构分析)
  267.                 cvBoxPoints(box,pt);  
  268.                 for(int i = 0;i < 4; ++ i)
  269.                 {  
  270.                         //(Cxcore绘图函数、Cxcore基础结构)
  271. ……………………

  272. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
代码.docx (17.08 KB, 下载次数: 31)


评分

参与人数 1黑币 +1 收起 理由
owl1521 + 1 很给力!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:216861 发表于 2017-7-3 17:38 | 只看该作者
谢谢                                                         
回复

使用道具 举报

板凳
ID:256027 发表于 2017-12-1 11:52 | 只看该作者
想试试,这个程序编译没问题吧?
回复

使用道具 举报

地板
ID:270146 发表于 2018-1-2 13:36 | 只看该作者
正在研究图像轮廓问题,方法值得借鉴。
回复

使用道具 举报

5#
ID:105534 发表于 2018-8-14 15:22 | 只看该作者
先看看
回复

使用道具 举报

6#
ID:401842 发表于 2018-10-19 09:30 | 只看该作者
看看先
回复

使用道具 举报

7#
ID:490934 发表于 2019-3-14 17:54 | 只看该作者
问下楼主能不能将这个程学放到的电脑上用?我给钱
联系我:465539798@qq.com
回复

使用道具 举报

8#
ID:490934 发表于 2019-3-14 17:54 | 只看该作者
能不能帮我编译
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表