標題:
視覺檢測設(shè)計與實踐(米粒計數(shù))c++源程序
[打印本頁]
作者:
pp123456
時間:
2017-6-7 22:51
標題:
視覺檢測設(shè)計與實踐(米粒計數(shù))c++源程序
這是視覺檢測試驗中的米粒計數(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;
}
//對灰度圖像進行預處理(均值濾波)
IplImage * PreProcess(IplImage * pImageGray)
{
//預處理結(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坐標不一樣
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 << "中心坐標:(" << 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黑下載附件…………
復制代碼
所有資料51hei提供下載:
代碼.docx
(17.08 KB, 下載次數(shù): 31)
2017-6-7 22:50 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
midao
時間:
2017-7-3 17:38
謝謝
作者:
dhp
時間:
2017-12-1 11:52
想試試,這個程序編譯沒問題吧?
作者:
wq4801155
時間:
2018-1-2 13:36
正在研究圖像輪廓問題,方法值得借鑒。
作者:
Ppp0011010
時間:
2018-8-14 15:22
先看看
作者:
110426
時間:
2018-10-19 09:30
看看先
作者:
13806603876
時間:
2019-3-14 17:54
問下樓主能不能將這個程學放到的電腦上用?我給錢
聯(lián)系我:
465539798@qq.com
作者:
13806603876
時間:
2019-3-14 17:54
能不能幫我編譯
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1