if(e_dThreshold>q_pchDataImage[q_iWidth/2+q_iWidthStep*(Cycle_Y-l)J){
NLPoint[0].x=q_iWidth/2;
MPoint[01.y=CycleY;
for(intcyclelYuq_iHeight;cycle—Y〉l;CycleYI—)
亠
if(e—dThreshold〉尸pchDat巴mage〔尸iwidth、2+Fiwidthstep*(cycle—Y—1)」)
MPoint=〕•x=q—iwidth、2"
MPointLl〕・yucycleY八
)
}
for(intCyclexul八Cyclex〈q—iwidthnyclex++)
亠
if(eldThreshold〉q_pchDataImage〔cyclelx+尸iwidrhstep*(qliHeight、2丄)〕)
MPoint「2〕•xucyclelx;
MPoint「2,-•yuq—iHeight'2”
)
}
for(intCycleXHq—iwidthnyclex〉1"CycleXI—)
亠
rdThreshold〉尸pchDat巴mage「cycle—x2iwidthstep*(q」Height、2丄)(
MPoint「3〕•xucyclelx一
MPoint一3-•y=q—iHeight、2"
)
}
(intH-?
i〈4“i++)、、画娱初El
{cvCircle(m_plplImageSource,M_Point[i],8,cvScalarAl1(127),2);}
intRidius=Otclear=O;
intcirc1e_y=abs(MPoin111J.y+MPointI0].y)/2;
intcirc1e_x=abs(MPoint[3].x+MPoint[2].x)/2;
floatc=0,j=0;
for(inti=0;i<4;i++)
{
j=(M_Point[i]・x-cirelex)*(M_Point[i]・x-cirelex)+(M_Point[i]・y-circle_y)*(M_Point[i].y-circle_y);
c=c+sqrt(j);
}
Ridius=c/4;
//在窗口中显示长和高
charchi[101,ch2[101;
itoa(Ridius,chi,10);
itoa(clear,ch2t10);
SetDlgltemText(IDCLONG,chi);
SetDlgltemText(IDC_SHORT,ch2);
CWnd*e_pCWndPicture=this->GetDlgItem(IDPICTUREDISPLAY);
fContro1ShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);cvSavelmage(T("・//Result_Image・jpg"),m_plplImageSource);
return0;
}
2.2检测与计算矩形长和宽的程序
思路:
这个程序主要包括:
打开摄像头-一保存图片(拍照)-一加载刚刚保存的图片-一找出点并计算长和高四个按钮,每一个按钮包含下面的一段代码,拍摄的图片保存为Currentimage,jpg,这里事先保存了一同名的图片,所以可以直接点击LoadImage读取。
2.2.1打开摄像头程序
voidcDialogTec1arn:
:
OnBnC1ickedButtonOpenCamera()
{
CvCapture*qpCvCapture=cvCreateCameraCapture(0);
if(NULL==qpCvCapture)
{
return;
}
IplImage*qplplImageCapture^cvQueryFrame(qpCvCapture):
if(NULL==qplplImageCapture)
{
return;
}
if(NULL!
=mplplImageSource)
{
cvReleaseImage(&mplplImageSource);
mpIp1ImageSource=NULL;
}
m_pIplImageSource=cvCloneImage(q_plplImageCapture);
cvReleaseCapture(&qpCvCapture);
CWnd*epCWndPicture=this->GetDlgItem仃DPICTUREDISPLAY);
fConti'olShowImage(mpIplImageDisplay,epCWndPicture,mplplImageSource);
}
注:
绿色的为检测是否成功打开摄像头,蓝色的是读取摄像头拍摄的图片到存,后面的
语句是让图片在mfc窗口显示出来。
2.2.2保存拍摄的照片程序
voidcDialogTeclarn:
:
0nBnClickedButtonSavelmage()
{
//TODO:
在此添加控件通知处理程序代码
cvSaveImage(__T(ff.//CurrentImage>jpg”),m_plplImageSource);
}
2.2.3读取拍摄到的图片(读取文名字Currentimage,jpg的图片)
voidcDialogTeclarn:
:
OnBnC]ickedButtonLoadlmageO
{
//TODO:
在此添加控件通知处理程序代码
if(NULL!
=m_pIplImageSource)
(
cvReleaseImage(&mplplImageSource);
mplplImageSource二NULL;
}
m_pIplImageSource=cvLoadImageCT(".//CurrentImage・jpg"),0);
CWnd*epCWndPicture=this->GetDIgltem(IDPICTUREDISPLAY):
fControlShowImage(mplplImageDisplay,epCWndPicture,mplplImageSource);
2.2.4检测边上的点和计算长和高的函数
思路是:
第一步找到边上的点,设定一个变量eJThreshold值为127,通过循环让它与每一个像素的像素值进行企軌疝果芹测到一个点的像素值比127小,则这个点可能就是需要的点(黑色=o,白制別如』每个像素都要比较运算太多,所以上边两个、X3,Y3,1/
点的检测是沿着图片长的的2/5分处和3/5分处向下检测,下边的点是沿着1/2处向上检测。
第二步是用找到6个点的坐标算出三角形的面积,然后除以底边边长得到高。
求三角形的面积用的是行列式的值等于三角形面积的2倍
程序如下:
doublecDialogTeclarn:
:
fMakeRectangleWidth(doubleedThreshold)
{
//TODO:
在此添加控件通知处理程序代码
〃定义一些点和变量
intqiWidth-mplplImageSource->width;
intqiHeight=mplp1ImageSource->height;
intqiWidthStep二mplplImageSource->widthStep;
uchar*qpchDataImage=(uchar*)mpIp11mageSource->imageData:
intiXLeftTop=2*q_iWidth/5:
intqiXRightTop=3*qiWidth/5;
intqiXBottom=qiWidth/2;
intqiYLeftTop=2*q_iHeight/5;
intqiYLeftBottom=3*qiHeight/5;
intqiYRightMid=q_iHeight/2;
CvPointqCvPointLeftTop,qCvPointRightTop,qCvPointBottom:
CvPointqCvPointLeftTop,qCvPointRightMid,qCvLeftBottom:
//求上下两边上的点,3个循环
for(intcuiCycleHeight=O;q_iCycleHeight{
if(e_dThreshold>q_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXLeftTopl)
{
q_CvPointLeftTop.x=jiXLeftTop;
q_CvPointLeftTop.y=jiCyc1eHeight;break;
}
for(intqiCycleHeight=O;qiCycleHeight{
if(edThreshold>qpchDatalmageEqiCycleHeight*qiWidthStep+qiXRightTop])
{
qCvPointRightTop.x=qiXRightTop;
qCvPointRightTop・y=qiCycleHeight;break;
}
}
for(intqiCycleHeight=qiHeightT;qiCycleHeight>=0;qiCycleHeight--)
{
if(edThreshold>qpchDatalmageEqiCycleHeight*qiWidthStep+qiXBottom])
{
qCvPointBottom・x二qiXBottom;
qCvPointBottom・y二qiCycleHeight;
break;
}
}
〃求左右两边上的点,3个循环
for(intqiCycleWidth=0;q_iCycleWidth{
if(edThreshold>qpchDatalmageEq_iCycleWidth+qiWidthStep*(qiYLeftTop-1)])
{
qCvPointLeftTop.x=q_iCycleWidth;
q_CvPointLeft一Top.y=qiYLeftTop;break;
}
}
for(intqiCycleWidth=O;qiCycleWidth{
if(edThreshold>qpchDataImage[q_iCycleWidth+qiWidthStep*(qiYLeftBottom-1)]){
qCvLeftBottom.x=qiCycleWidth;
qCvLeftBottom・y二qiYLeftBottom;
break;
}
}
for(intqiCycleWidth=qiHeight-1;q_iCycleWidth>=0;qiCycleWidth--)
{
if(edThreshold>qpchDatalmagetqiCycleWidth+qiWidthStep*(qiYRightMid-1)])
qCvPointRightMid.x=qiCycleWidth;
qCvPointRightMid.y=qiYRightMid;
break;
}
}
〃在检测到的点上画圆,只是为了更好看到找点的情况
cvCircle(mpIp11mageSourcetqCvPointLeftTop,5,cvScalarAll(127),2);
cvCircle(mpIplImageSource,qCvPointRightTop,5tcvScalarAl1(127).2);
cvCircle(mplplImageSource,qCvPointBottom,5,cvScalarAU(127),2):
cvCircle(mplplImageSource,qCvPointLeftTop.5tcvScalarAl1(127),2);
cvCircle(mplplImageSource,qCvLeftBottom,5,cvScalarAll(127),2);
cvCircle(mplplImageSource,qCvPointRightMid,5tcvScalarAl1(127),2):
//显不画圆后的图片
CWnd*e^pCWndPicture=this->GetDlgItem(IDPICTURE.DISPLAY);
fControlShowimage(mplplImageDisplaytepCWndPicture,mplplImageSource):
〃计算长和高的像素值,三角形3点的坐标构成行列式,行列式的值二2*面积,行列式
的值/底边二高
CvMatMa;
intHIGH,WIDE;
floatArea;
inta=qCvPointLeftTop・x-qCvPointRightTop・x;
intb=qCvPointLeftTop・y-qCvPointRightTop・y;
doublec=a*a+b*b;
〃定义行列式
doub1e
arr[9]={qCvPointLeftTop.x.qCvPointLeftTop.y,l,qCvPointRightTop.xtqCvPointRightTop.
y,1,qCvPointBottom・x,qCvPointBottom・y,1};
cvlnitMatHeader(&Ma,313,CV.64FCl,arr);
Area=abs(cvDet(&Ma));
HIGH=Area/sqrt(c);
intA=qCvPointLeft_Top・x-q_CvLeftBottom・x;
intB=qCvPointLeftTop.y-qCvLeftBottom,y;
doubleC=A*A+B*B;
〃定义行列式
Double
ARR[9]={qCvPointLeft_Top.x,qCvPointLeftTop.y,ltq_CvLeftBottom.xtqCvLeftBottom,y,1,qCvPointRightid.x,q_CvPointRi(?
ht_Mid.y,1};
cvInitMatHeader(&Ma,3t3,CV64FC1,ARR):
Area=abs(cvDet(&Ma));
WIDE=Area/sqrt(C);
//在窗口中显示长和高
charchi[10],ch2[10];
itoa(HIGH,chl,10);
itoa(WIDE,ch2,10);
SetDlgltemText(IDCLONG,chi):
SetDlgltemText(IDC_SHORT.ch2);
cvSaveImage(T(w.//ResultImage・jpgn),mplplImageSource):
return0;
}
//调用上面的函数进行检测点和计算长和高的值,点击第四个按钮会调用这段程序,当里面的函数调用时,它会调用上面那段函数
voidcDialogTeclarn:
:
OnBnClickedButtonRectangle0
{
//TODO:
在此添加控件通知处理程序代码
f_MakeRectang1eWidth();
}
2.2.5老师写的显示图片的函数
voidcDialogTeclarn:
:
fContro1ShowImage(Ip11mage水&eplplImageShow,CWnd
*epCWndControl,IplImage*eplplImageSource)
{
if((NULL==epCWndControl)(NULL==eplplImageSource))
{
return;
}
CRectqCRectControl;
epCWndContro1-XietC1ientRect(&qCRectControl):
if(NULL!
=eplplImageShow)
{
cvReleaseImage(&eplplImageShow);
eplplImageShow二NULL;
}
epIp1ImageShow=cvCreateImage(cvSize(qCRectContro1.Width(),qCRectContro1.Height()),
IPLDEPTH_8Ut
eplplImageSource->nChannels):
cvResize(eplplImageSource,eplplImageShow):
HDCq_HDCControl=epCWndControl->GetDC()->GetSafeHdc();
unsignedintqpiBuffer[sizeof(BIWPINFOHEADER)+sizeof(RGBQUAD)*256]:
BITMAPINFO*e_pBITMAPINFODisplay=(BITMAPINFO*)q„piBuffer;
BITMAPINFOHEADER*epBITMAPINFOHEADERDisp1ay=&(epBITMAPINFODisplay->bmiHeader);
memset(epBITMAPINFOHEADERDisplay,0.sizeof(*epBITMAPINFOHEADERDisplay)):
epBITMAPINFOHEADERDisplay->biSize=sizeof(BITOPINFOHEADER);
舶摄图片一圆
检测图片--圆
拍摄图片-矩形
检测图片一矩形
4小结
通过本次设计,让我很好的锻炼了理论联系实际,与具体项目、课题相结合开发、设计产品的能力。
既让我们懂得了怎样把理论应用于实际,又让我们懂得了在实践中遇到的问题怎样用理论去解决。
在本次设计中,我们还需要大量的以前没有学到过的知识,于是图书馆和INTERNET成了我们很好的助手。
在查阅资料的过程中,我们要判断优劣、取舍相关知识,不知不觉中我们查阅资料的能力也得到了很好的锻炼。
我们学习的知识是有限的,在以后的工作中我们肯定会遇到许多未知的领域,这方面的能力便会使我们受益非浅。
在设计过程中,总是遇到这样或那样的问题。
有时发现一个问題的时候,需要做大量的工作,花大量的时间才能解决。
自然而然,我的耐心便在其中建立起来了。
为以后的工作积累了经验,增强了信心。