这是视觉检测试验中的米粒计数:
c++源程序如下:
- // 米粒计数.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include "cv.h"
- #include "highgui.h"
- #include "cxcore.h"
- #include "stdlib.h"
- #include <iostream>
- using namespace std;
- //获取灰度图像
- IplImage * LoadImage()
- {
- //IplImage(Cxcore基础结构)
- //载入彩色图像(3信道)(HighGUI读取与保存图像)
- IplImage * pImageSrc = cvLoadImage("rice.png",1);//测试图.jpg
- if(!pImageSrc)
- {
- cout << "Could not load image file!" << endl;
- exit(0);
- }
-
- //显示图像(HighGUI简单图形界面)
- cvNamedWindow("原米粒图像");
- // cvShowImage("原米粒图像",pImageSrc);
- // cvWaitKey(0);
- // cvDestroyWindow("原米粒图像");
-
-
- //灰度图(Cxcore数组操作)
- IplImage* pImageGray = cvCreateImage(cvGetSize(pImageSrc),IPL_DEPTH_8U,1);
- //色彩空间转换(Cv图像处理)
- cvCvtColor(pImageSrc,pImageGray,CV_BGR2GRAY);
-
- cvShowImage("原米粒图像",pImageGray);
- cvWaitKey(0);
-
- //Cxcore数组操作
- cvReleaseImage(&pImageSrc);
- return pImageGray;
- }
- //对灰度图像进行预处理(均值滤波)
- IplImage * PreProcess(IplImage * pImageGray)
- {
- //预处理结果图(Cxcore数组操作)
- IplImage* pImagePrePro = cvCreateImage(cvGetSize(pImageGray),IPL_DEPTH_8U,1);
- //均值滤波(Cv图像处理)
- cvSmooth(pImageGray, pImagePrePro,CV_BLUR,3,3,0,0);
- //显示图像(HighGUI简单图形界面)
- cvNamedWindow("均值滤波图像");
- cvShowImage("均值滤波图像",pImagePrePro);
- cvWaitKey(0);
-
- /* //opencv滤波结果
- for(int xindex = 10; xindex < 20; xindex ++)
- {
- for(int yindex = 10; yindex < 20; yindex ++)
- {
- cout << cvRound(cvGet2D(pImagePrePro,yindex,xindex).val[0]) << '\t';
- }
- }
- cout << endl;*/
-
- //自己编程对比
- //图像拷贝(Cxcore数组操作)
- IplImage* pImagePrePro1 = cvCloneImage(pImageGray);
- // cvSet(pImagePrePro1,cvScalarAll(0),0);
-
- //均值滤波(Cxcore数组操作)
- CvScalar sum;
- //滑动窗口增量
- int xincrement = -1,xincrement1 = 1;
- int yincrement = -1,yincrement1 = 1;
- for(int xindex = 1; xindex < pImageGray->width - 1; xindex ++)
- {
- for(int yindex = 1; yindex < pImageGray->height - 1; yindex ++)
- {
- sum.val[0] = 0;
- //滑动窗口计算均值
- for(int xtemp = xincrement; xtemp <= xincrement1 ;xtemp ++)
- {
- for(int ytemp = yincrement; ytemp <= yincrement1;ytemp ++)
- {
- //注意:数组和图像的xy坐标不一样
- sum.val[0] += cvGet2D(pImageGray,yindex + ytemp,xindex + xtemp).val[0];
- }
- }
- //求均值(Cxcore数组操作)
- sum.val[0] = cvRound(sum.val[0] / ((yincrement1 - yincrement + 1) * (xincrement1 - xincrement + 1)));
- cvSet2D(pImagePrePro1,yindex,xindex,sum);
- }
- }
- //显示图像(HighGUI简单图形界面)
- cvNamedWindow("均值滤波图像1");
- cvShowImage("均值滤波图像1",pImagePrePro1);
- cvWaitKey(0);
-
- /* //测试滤波的正确性
- //自己编程实现滤波结果
- for(xindex = 10; xindex < 20; xindex ++)
- {
- for(int yindex = 10; yindex < 20; yindex ++)
- {
- cout << cvRound(cvGet2D(pImagePrePro1,yindex,xindex).val[0]) << '\t';
- }
- }
- cout << endl;*/
-
- cvReleaseImage(&pImagePrePro1);
- return pImagePrePro;
- }
- //迭代阈值分割
- IplImage * Segmentation(IplImage * pImagePrePro)
- {
- IplImage* pImageBw = cvCloneImage(pImagePrePro);
-
- //二值分割图像(Cv图像处理)
- cvThreshold(pImagePrePro, pImageBw, 119 ,255, CV_THRESH_BINARY);
-
- //显示图像(HighGUI简单图形界面)
- cvNamedWindow("二值图像");
- cvShowImage("二值图像",pImageBw);
- cvWaitKey(0);
-
- //自己编程实现迭代阈值分割
- IplImage* pImageBw1 = cvCloneImage(pImagePrePro);
- //初始阈值为图像的平均灰度(Cxcore数组操作)
- CvScalar threshold = cvAvg(pImageBw1);
- // cout << threshold.val[0] << endl;
-
- /*//求平均灰度,验证初始阈值的正确性(可以用cvSum)
- CvScalar sum;
- sum.val[0] = 0;
- for(int xindex = 0; xindex < pImagePrePro->width; xindex ++)
- {
- for(int yindex = 0; yindex < pImagePrePro->height; yindex ++)
- {
- sum.val[0] += cvGet2D(pImagePrePro,yindex,xindex).val[0];
- }
- }
- sum.val[0] = sum.val[0] / (pImagePrePro->width * pImagePrePro->height);
- cout << sum.val[0] << endl;
- */
-
- //迭代阈值分割
- CvScalar threshold1;
- threshold1.val[0] = 0;
- CvScalar temp1,temp2;
- temp1.val[0] = 0;
- temp2.val[0] = 0;
- while(abs(threshold.val[0] - threshold1.val[0]) > 0.1)
- {
- threshold1 = threshold;
- IplImage* pImageTemp = cvCloneImage(pImageBw1);
- //计算前景的平均灰度
- cvThreshold(pImageBw1, pImageTemp,threshold1.val[0],255, CV_THRESH_TOZERO);
- //注意:不能用cvAvg (Cxcore数组操作)
- temp1.val[0] = cvSum(pImageTemp).val[0] / cvCountNonZero(pImageTemp);
-
- //计算背景的平均灰度
- cvThreshold(pImageBw1, pImageTemp,threshold1.val[0],255, CV_THRESH_TOZERO_INV);
- temp2.val[0] = cvSum(pImageTemp).val[0] / cvCountNonZero(pImageTemp);
-
- //获取新阈值
- threshold.val[0] = (temp1.val[0] + temp2.val[0]) / 2;
- cvReleaseImage(&pImageTemp);
- }
- //迭代后得到分割阈值
- cout << "迭代阈值:" << threshold.val[0] << endl;
-
- //二值分割图像(Cv图像处理)
- cvThreshold(pImageBw1, pImageBw1, threshold.val[0] ,255, CV_THRESH_BINARY);
-
- //显示图像(HighGUI简单图形界面)
- cvNamedWindow("二值图像1");
- cvShowImage("二值图像1",pImageBw1);
- cvWaitKey(0);
-
- cvReleaseImage(&pImageBw1);
- return pImageBw;
- }
- void GetParameter(IplImage * pImageBw)
- {
- //轮廓的存储容器(Cxcore动态结构)
- CvMemStorage* storage = cvCreateMemStorage(0);
- //输出参数:包含第一个输出轮廓的指针
- CvSeq* first_contour = 0;
- IplImage* pImageBw1 = cvCloneImage(pImageBw);
- //在二值图像中寻找定点序列轮廓(Cv图像处理)//注意pImgBw1会被改变
- int contourNum = cvFindContours(pImageBw1,storage,&first_contour,
- sizeof(CvContour), CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
-
- //freeman链码
- //轮廓的存储容器1(Cxcore动态结构)
- CvMemStorage* storage1 = cvCreateMemStorage(0);
- //输出参数:包含第一个输出轮廓的指针
- CvSeq* first_contour1 = 0;
- IplImage* pImageBw2 = cvCloneImage(pImageBw);
- //在二值图像中寻找freeman链码轮廓(Cv图像处理)//注意pImgBw1会被改变
- int contourNum1 = cvFindContours(pImageBw2,storage1,&first_contour1,
- sizeof(CvChain), CV_RETR_EXTERNAL,CV_CHAIN_CODE);
-
- //轮廓图
- IplImage* image = cvCloneImage(pImageBw);
- cvSet(image,cvScalarAll(0),0);
- //将所有轮廓画出(Cxcore绘图函数)
- cvDrawContours(image, first_contour, CV_RGB(255,255,255), CV_RGB(255,255,255),2, 1, 0);
- cvNamedWindow( "轮廓图");
- cvShowImage( "轮廓图", image);
- cvWaitKey(0);
-
- //获取freeman链码
- CvSeqReader reader;
-
- //用于显示外接矩形
- IplImage* image1 = cvCreateImage(cvGetSize(pImageBw),IPL_DEPTH_8U,3);
-
- for(CvSeq* contour = first_contour,*contour1 = first_contour1;
- contour != 0,contour1 != 0;contour=contour->h_next,contour1=contour1->h_next)
- {
-
- cvSet(image,cvScalarAll(0),0);
- cvDrawContours(image,contour,CV_RGB(255, 255, 255),CV_RGB(255, 255, 255),0, CV_FILLED, 8);
- // cvShowImage( "轮廓图", image);
-
- cout << "轮廓点数:" << contour->total << '\t';
- //(Cv结构分析)
- cout << "周长:" << cvArcLength(contour) << '\t';
-
- //自己计算周长
- //(Cxcore动态结构)
- cvStartReadSeq((CvSeq*)contour1, &reader, 0 );
- double perimeter = 0;
- for(int cNum = 0; cNum < contour->total; cNum ++ )
- {
- char code;
- //获取链码
- CV_READ_SEQ_ELEM(code, reader);
- //链码为偶数则周长+1
- if(int(code) % 2 == 0)
- {
- perimeter += 1;
- }
- //链码为奇数,则周长+sqrt(2)
- if(int(code) % 2 != 0)
- {
- perimeter += sqrt(2);
- }
- }
- cout << "计算的周长:" << perimeter << '\t';
-
- cout << "面积:" << fabs(cvContourArea(contour)) << '\t';
- cout << "轮廓内非0点数:" << cvCountNonZero(image) << '\t';
- // cvWaitKey(0);
-
- //最小外接矩形图
- cvSet(image1,cvScalarAll(0),0);
- cvDrawContours(image1,contour,CV_RGB(255, 255, 255),CV_RGB(255, 255, 255),0, CV_FILLED, 8);
- //对给定2D点集,寻找最小面积的外围矩形(Cv结构分析)
- CvBox2D box = cvMinAreaRect2(contour,NULL);
- cout << "中心坐标:(" << box.center.x << "," << box.center.y << ")" << '\t';
- cvSet2D(image1,box.center.y,box.center.x,CV_RGB(0, 0, 255));
- cout << "长:" << (box.size.height > box.size.width?box.size.height:box.size.width) << '\t';
- cout << "宽:" << (box.size.height > box.size.width?box.size.width:box.size.height) << '\t';
- //绘制外接最小矩形
- CvPoint2D32f pt[4];
- //寻找盒子的顶点(Cv结构分析)
- cvBoxPoints(box,pt);
- for(int i = 0;i < 4; ++ i)
- {
- //(Cxcore绘图函数、Cxcore基础结构)
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
代码.docx
(17.08 KB, 下载次数: 31)
|