|
這是視覺檢測試驗中的米粒計數(shù):
c++源程序如下:
- // 米粒計數(shù).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基礎(chǔ)結(jié)構(gòu))
- //載入彩色圖像(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數(shù)組操作)
- IplImage* pImageGray = cvCreateImage(cvGetSize(pImageSrc),IPL_DEPTH_8U,1);
- //色彩空間轉(zhuǎn)換(Cv圖像處理)
- cvCvtColor(pImageSrc,pImageGray,CV_BGR2GRAY);
-
- cvShowImage("原米粒圖像",pImageGray);
- cvWaitKey(0);
-
- //Cxcore數(shù)組操作
- cvReleaseImage(&pImageSrc);
- return pImageGray;
- }
- //對灰度圖像進行預(yù)處理(均值濾波)
- IplImage * PreProcess(IplImage * pImageGray)
- {
- //預(yù)處理結(jié)果圖(Cxcore數(shù)組操作)
- 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濾波結(jié)果
- 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數(shù)組操作)
- IplImage* pImagePrePro1 = cvCloneImage(pImageGray);
- // cvSet(pImagePrePro1,cvScalarAll(0),0);
-
- //均值濾波(Cxcore數(shù)組操作)
- 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 ++)
- {
- //注意:數(shù)組和圖像的xy坐標(biāo)不一樣
- sum.val[0] += cvGet2D(pImageGray,yindex + ytemp,xindex + xtemp).val[0];
- }
- }
- //求均值(Cxcore數(shù)組操作)
- 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);
-
- /* //測試濾波的正確性
- //自己編程實現(xiàn)濾波結(jié)果
- 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);
-
- //自己編程實現(xiàn)迭代閾值分割
- IplImage* pImageBw1 = cvCloneImage(pImagePrePro);
- //初始閾值為圖像的平均灰度(Cxcore數(shù)組操作)
- 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數(shù)組操作)
- 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動態(tài)結(jié)構(gòu))
- CvMemStorage* storage = cvCreateMemStorage(0);
- //輸出參數(shù):包含第一個輸出輪廓的指針
- 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動態(tài)結(jié)構(gòu))
- CvMemStorage* storage1 = cvCreateMemStorage(0);
- //輸出參數(shù):包含第一個輸出輪廓的指針
- 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繪圖函數(shù))
- 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 << "輪廓點數(shù):" << contour->total << '\t';
- //(Cv結(jié)構(gòu)分析)
- cout << "周長:" << cvArcLength(contour) << '\t';
-
- //自己計算周長
- //(Cxcore動態(tài)結(jié)構(gòu))
- cvStartReadSeq((CvSeq*)contour1, &reader, 0 );
- double perimeter = 0;
- for(int cNum = 0; cNum < contour->total; cNum ++ )
- {
- char code;
- //獲取鏈碼
- CV_READ_SEQ_ELEM(code, reader);
- //鏈碼為偶數(shù)則周長+1
- if(int(code) % 2 == 0)
- {
- perimeter += 1;
- }
- //鏈碼為奇數(shù),則周長+sqrt(2)
- if(int(code) % 2 != 0)
- {
- perimeter += sqrt(2);
- }
- }
- cout << "計算的周長:" << perimeter << '\t';
-
- cout << "面積:" << fabs(cvContourArea(contour)) << '\t';
- cout << "輪廓內(nèi)非0點數(shù):" << 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結(jié)構(gòu)分析)
- CvBox2D box = cvMinAreaRect2(contour,NULL);
- cout << "中心坐標(biāo):(" << 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結(jié)構(gòu)分析)
- cvBoxPoints(box,pt);
- for(int i = 0;i < 4; ++ i)
- {
- //(Cxcore繪圖函數(shù)、Cxcore基礎(chǔ)結(jié)構(gòu))
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
代碼.docx
(17.08 KB, 下載次數(shù): 31)
2017-6-7 22:50 上傳
點擊文件名下載附件
|
評分
-
查看全部評分
|