机器视觉课程设计.docx

上传人:b****5 文档编号:6107085 上传时间:2023-01-03 格式:DOCX 页数:13 大小:47.98KB
下载 相关 举报
机器视觉课程设计.docx_第1页
第1页 / 共13页
机器视觉课程设计.docx_第2页
第2页 / 共13页
机器视觉课程设计.docx_第3页
第3页 / 共13页
机器视觉课程设计.docx_第4页
第4页 / 共13页
机器视觉课程设计.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

机器视觉课程设计.docx

《机器视觉课程设计.docx》由会员分享,可在线阅读,更多相关《机器视觉课程设计.docx(13页珍藏版)》请在冰豆网上搜索。

机器视觉课程设计.docx

机器视觉课程设计

机器视觉课程设计

对圆盘形零件圆心与直径和矩形

零件长与宽尺寸测量

 

学生学院机电学院

专业班级

学号

学生姓名

指导教师

 

2015年1月20日

1问题描述

1.1基本目标

显示一张图片(包含一个矩形或一个圆),测量矩形的长宽或圆的直径。

完成得及格分,扩展有加分!

要求图片

1.2基本要求

“机器视觉”考试结果要求独立在计算机上完成,建议使用VisualC++和OpenCV实现一个具有视觉捕捉、图像显示、尺寸测量等功能的对话框程序,其中必须完成对圆盘形零件圆心与直径和矩形零件长与宽尺寸测量内容。

在教师提供的基本框架程序基础上,修改、补充界面和功能。

2程序及其算法

2.1检测与计算圆半径的程序

思路:

从图片中间横扫取点得M_Point[0],M_Point[1](x坐标相加除2的圆心的x坐标)中间纵向取点得M_Point[2],M_Point[3](y坐标相加除2的圆心的y坐标)

圆上四个点到圆心的距离(半径)取平均值,输出为半径。

 

显示图片

程序如下:

doublec_DialogTeclarn:

:

f_MakeCircle(doublee_dThreshold)

{

if(NULL==m_pIplImageSource)

{return0;}

//定义变量存图像的宽,高,行像素

intq_iWidth=m_pIplImageSource->width;

intq_iHeight=m_pIplImageSource->height;

intq_iWidthStep=m_pIplImageSource->widthStep;

uchar*q_pchDataImage=(uchar*)m_pIplImageSource->imageData;

CvPointM_Point[4]={};//存放检索出的四个点循环检索

//01纵扫

for(intCycle_Y=1;Cycle_Y

{

if(e_dThreshold>q_pchDataImage[q_iWidth/2+q_iWidthStep*(Cycle_Y-1)])

{

M_Point[0].x=q_iWidth/2;

M_Point[0].y=Cycle_Y;

}

}

for(intCycle_Y=q_iHeight;Cycle_Y>1;Cycle_Y--)

{

if(e_dThreshold>q_pchDataImage[q_iWidth/2+q_iWidthStep*(Cycle_Y-1)])

{

M_Point[1].x=q_iWidth/2;

M_Point[1].y=Cycle_Y;

}

}

for(intCycle_X=1;Cycle_X

{

if(e_dThreshold>q_pchDataImage[Cycle_X+q_iWidthStep*(q_iHeight/2-1)])

{

M_Point[2].x=Cycle_X;

M_Point[2].y=q_iHeight/2;

}

}

for(intCycle_X=q_iWidth;Cycle_X>1;Cycle_X--)

{

if(e_dThreshold>q_pchDataImage[Cycle_X+q_iWidthStep*(q_iHeight/2-1)])

{

M_Point[3].x=Cycle_X;

M_Point[3].y=q_iHeight/2;

}

}

for(inti=0;i<4;i++)//画边界圆

{cvCircle(m_pIplImageSource,M_Point[i],8,cvScalarAll(127),2);}

intRidius=0,clear=0;

intcircle_y=abs(M_Point[1].y+M_Point[0].y)/2;

intcircle_x=abs(M_Point[3].x+M_Point[2].x)/2;

floatc=0,j=0;

for(inti=0;i<4;i++)

{

j=(M_Point[i].x-circle_x)*(M_Point[i].x-circle_x)+(M_Point[i].y-circle_y)*(M_Point[i].y-circle_y);

c=c+sqrt(j);

}

Ridius=c/4;

//在窗口中显示长和高

charch1[10],ch2[10];

itoa(Ridius,ch1,10);

itoa(clear,ch2,10);

SetDlgItemText(IDC_LONG,ch1);

SetDlgItemText(IDC_SHORT,ch2);

CWnd*e_pCWndPicture=this->GetDlgItem(ID_PICTURE_DISPLAY);

f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);

cvSaveImage(_T(".//Result_Image.jpg"),m_pIplImageSource);

return0;

}

2.2检测与计算矩形长和宽的程序

思路:

这个程序主要包括:

打开摄像头---保存图片(拍照)---加载刚刚保存的图片---找出点并计算长和高四个按钮,每一个按钮包含下面的一段代码,拍摄的图片保存为CurrentImage.jpg,这里事先保存了一张同名的图片,所以可以直接点击LoadImage读取。

2.2.1打开摄像头程序

voidc_DialogTeclarn:

:

OnBnClickedButtonOpenCamera()

{

CvCapture*q_pCvCapture=cvCreateCameraCapture(0);

if(NULL==q_pCvCapture)

{

return;

}

IplImage*q_pIplImageCapture=cvQueryFrame(q_pCvCapture);

if(NULL==q_pIplImageCapture)

{

return;

}

if(NULL!

=m_pIplImageSource)

{

cvReleaseImage(&m_pIplImageSource);

m_pIplImageSource=NULL;

}

m_pIplImageSource=cvCloneImage(q_pIplImageCapture);

cvReleaseCapture(&q_pCvCapture);

CWnd*e_pCWndPicture=this->GetDlgItem(ID_PICTURE_DISPLAY);

f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);

}

注:

绿色的为检测是否成功打开摄像头,蓝色的是读取摄像头拍摄的图片到内存,后面的语句是让图片在mfc窗口显示出来。

2.2.2保存拍摄的照片程序

voidc_DialogTeclarn:

:

OnBnClickedButtonSaveImage()

{

//TODO:

在此添加控件通知处理程序代码

cvSaveImage(_T(".//CurrentImage.jpg"),m_pIplImageSource);

}

2.2.3读取拍摄到的图片(读取文名字CurrentImage.jpg的图片)

voidc_DialogTeclarn:

:

OnBnClickedButtonLoadImage()

{

//TODO:

在此添加控件通知处理程序代码

if(NULL!

=m_pIplImageSource)

{

cvReleaseImage(&m_pIplImageSource);

m_pIplImageSource=NULL;

}

m_pIplImageSource=cvLoadImage(_T(".//CurrentImage.jpg"),0);

CWnd*e_pCWndPicture=this->GetDlgItem(ID_PICTURE_DISPLAY);

f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);

}

2.2.4检测边上的点和计算长和高的函数

思路是:

第一步找到边上的点,设定一个变量e_dThreshold值为127,通过循环让它与每一个像素的像素值进行比较。

如果检测到一个点的像素值比127小,则这个点可能就是需要的点(黑色=0,白色=255)如果每个像素都要比较运算太多,所以上边两个

点的检测是沿着图片长的的2/5分处和3/5分处向下检测,下边的点是沿着1/2处向上检测。

第二步是用找到6个点的坐标算出三角形的面积,然后除以底边边长得到高。

求三角形的面积用的是行列式的值等于三角形面积的2倍

 

程序如下:

doublec_DialogTeclarn:

:

f_MakeRectangleWidth(doublee_dThreshold)

{

//TODO:

在此添加控件通知处理程序代码

//定义一些点和变量

intq_iWidth=m_pIplImageSource->width;

intq_iHeight=m_pIplImageSource->height;

intq_iWidthStep=m_pIplImageSource->widthStep;

uchar*q_pchDataImage=(uchar*)m_pIplImageSource->imageData;

intq_iXLeftTop=2*q_iWidth/5;

intq_iXRightTop=3*q_iWidth/5;

intq_iXBottom=q_iWidth/2;

intq_iYLeftTop=2*q_iHeight/5;

intq_iYLeftBottom=3*q_iHeight/5;

intq_iYRightMid=q_iHeight/2;

CvPointq_CvPointLeftTop,q_CvPointRightTop,q_CvPointBottom;

CvPointq_CvPointLeft_Top,q_CvPointRight_Mid,q_CvLeft_Bottom;

//求上下两边上的点,3个循环

for(intq_iCycleHeight=0;q_iCycleHeight

{

if(e_dThreshold>q_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXLeftTop])

{

q_CvPointLeftTop.x=q_iXLeftTop;

q_CvPointLeftTop.y=q_iCycleHeight;

break;

}

}

for(intq_iCycleHeight=0;q_iCycleHeight

{

if(e_dThreshold>q_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXRightTop])

{

q_CvPointRightTop.x=q_iXRightTop;

q_CvPointRightTop.y=q_iCycleHeight;

break;

}

}

for(intq_iCycleHeight=q_iHeight-1;q_iCycleHeight>=0;q_iCycleHeight--)

{

if(e_dThreshold>q_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXBottom])

{

q_CvPointBottom.x=q_iXBottom;

q_CvPointBottom.y=q_iCycleHeight;

break;

}

}

//求左右两边上的点,3个循环

for(intq_iCycleWidth=0;q_iCycleWidth

{

if(e_dThreshold>q_pchDataImage[q_iCycleWidth+q_iWidthStep*(q_iYLeftTop-1)])

{

q_CvPointLeft_Top.x=q_iCycleWidth;

q_CvPointLeft_Top.y=q_iYLeftTop;

break;

}

}

for(intq_iCycleWidth=0;q_iCycleWidth

{

if(e_dThreshold>q_pchDataImage[q_iCycleWidth+q_iWidthStep*(q_iYLeftBottom-1)])

{

q_CvLeft_Bottom.x=q_iCycleWidth;

q_CvLeft_Bottom.y=q_iYLeftBottom;

break;

}

}

for(intq_iCycleWidth=q_iHeight-1;q_iCycleWidth>=0;q_iCycleWidth--)

{

if(e_dThreshold>q_pchDataImage[q_iCycleWidth+q_iWidthStep*(q_iYRightMid-1)])

{

q_CvPointRight_Mid.x=q_iCycleWidth;

q_CvPointRight_Mid.y=q_iYRightMid;

break;

}

}

//在检测到的点上画圆,只是为了更好看到找点的情况

cvCircle(m_pIplImageSource,q_CvPointLeftTop,5,cvScalarAll(127),2);

cvCircle(m_pIplImageSource,q_CvPointRightTop,5,cvScalarAll(127),2);

cvCircle(m_pIplImageSource,q_CvPointBottom,5,cvScalarAll(127),2);

cvCircle(m_pIplImageSource,q_CvPointLeft_Top,5,cvScalarAll(127),2);

cvCircle(m_pIplImageSource,q_CvLeft_Bottom,5,cvScalarAll(127),2);

cvCircle(m_pIplImageSource,q_CvPointRight_Mid,5,cvScalarAll(127),2);

//显示画圆后的图片

CWnd*e_pCWndPicture=this->GetDlgItem(ID_PICTURE_DISPLAY);

f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);

//计算长和高的像素值,三角形3点的坐标构成行列式,行列式的值=2*面积,行列式的值/底边=高

CvMatMa;

intHIGH,WIDE;

floatArea;

inta=q_CvPointLeftTop.x-q_CvPointRightTop.x;

intb=q_CvPointLeftTop.y-q_CvPointRightTop.y;

doublec=a*a+b*b;

//定义行列式

doublearr[9]={q_CvPointLeftTop.x,q_CvPointLeftTop.y,1,q_CvPointRightTop.x,q_CvPointRightTop.y,1,q_CvPointBottom.x,q_CvPointBottom.y,1};

cvInitMatHeader(&Ma,3,3,CV_64FC1,arr);

Area=abs(cvDet(&Ma));

HIGH=Area/sqrt(c);

intA=q_CvPointLeft_Top.x-q_CvLeft_Bottom.x;

intB=q_CvPointLeft_Top.y-q_CvLeft_Bottom.y;

doubleC=A*A+B*B;

//定义行列式

DoubleARR[9]={q_CvPointLeft_Top.x,q_CvPointLeft_Top.y,1,q_CvLeft_Bottom.x,q_CvLeft_Bottom.y,1,q_CvPointRight_Mid.x,q_CvPointRight_Mid.y,1};

cvInitMatHeader(&Ma,3,3,CV_64FC1,ARR);

Area=abs(cvDet(&Ma));

WIDE=Area/sqrt(C);

//在窗口中显示长和高

charch1[10],ch2[10];

itoa(HIGH,ch1,10);

itoa(WIDE,ch2,10);

SetDlgItemText(IDC_LONG,ch1);

SetDlgItemText(IDC_SHORT,ch2);

cvSaveImage(_T(".//Result_Image.jpg"),m_pIplImageSource);

return0;

}

//调用上面的函数进行检测点和计算长和高的值,点击第四个按钮会调用这段程序,当里面的函数调用时,它会调用上面那段函数

voidc_DialogTeclarn:

:

OnBnClickedButtonRectangle()

{

//TODO:

在此添加控件通知处理程序代码

f_MakeRectangleWidth();

}

2.2.5老师写的显示图片的函数

voidc_DialogTeclarn:

:

f_ControlShowImage(IplImage*&e_pIplImageShow,CWnd*e_pCWndControl,IplImage*e_pIplImageSource)

{

if((NULL==e_pCWndControl)||(NULL==e_pIplImageSource))

{

return;

}

CRectq_CRectControl;

e_pCWndControl->GetClientRect(&q_CRectControl);

if(NULL!

=e_pIplImageShow)

{

cvReleaseImage(&e_pIplImageShow);

e_pIplImageShow=NULL;

}

e_pIplImageShow=cvCreateImage(cvSize(q_CRectControl.Width(),q_CRectControl.Height()),

IPL_DEPTH_8U,

e_pIplImageSource->nChannels);

cvResize(e_pIplImageSource,e_pIplImageShow);

HDCq_HDCControl=e_pCWndControl->GetDC()->GetSafeHdc();

unsignedintq_piBuffer[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256];

BITMAPINFO*e_pBITMAPINFODisplay=(BITMAPINFO*)q_piBuffer;

BITMAPINFOHEADER*e_pBITMAPINFOHEADERDisplay=&(e_pBITMAPINFODisplay->bmiHeader);

memset(e_pBITMAPINFOHEADERDisplay,0,sizeof(*e_pBITMAPINFOHEADERDisplay));

e_pBITMAPINFOHEADERDisplay->biSize=sizeof(BITMAPINFOHEADER);

e_pBITMAPINFOHEADERDisplay->biWidth=e_pIplImageShow->width;

e_pBITMAPINFOHEADERDisplay->biHeight=-e_pIplImageShow->height;

e_pBITMAPINFOHEADERDisplay->biPlanes=1;

e_pBITMAPINFOHEADERDisplay->biBitCount=8*e_pIplImageShow->nChannels;

e_pBITMAPINFOHEADERDisplay->biCompression=BI_RGB;

RGBQUAD*palette=e_pBITMAPINFODisplay->bmiColors;

if(8==e_pBITMAPINFOHEADERDisplay->biBitCount)

{

for(intq_iCycle=0;q_iCycle<256;q_iCycle++)

{

palette[q_iCycle].rgbBlue=(BYTE)q_iCycle;

palette[q_iCycle].rgbGreen=(BYTE)q_iCycle;

palette[q_iCycle].rgbRed=(BYTE)q_iCycle;

palette[q_iCycle].rgbReserved=(BYTE)0;

}

}

StretchDIBits(q_HDCControl,

q_CRectControl.left,

q_CRectControl.top,

e_pIplImageShow->width,

e_pIplImageShow->height,

q_CRectControl.left,

q_CRectControl.top,

e_pIplImageShow->width,

e_pIplImageShow->height,

e_pIplImageShow->imageData,

e_pBITMAPINFODisplay,

DIB_RGB_COLORS,

SRCCOPY);

}

3运行结果

运行结果图形如下:

 

 

4小结

通过本次设计,让我很好的锻炼了理论联系实际,与具体项目、课题相结合开发、

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1